★ 에러 발생 상황 ★
1. 멤버 등록
2. 제품 등록
3. 제품 주문
여기서 주문 조회를 클릭했을 때 빈 화면이 나오면서 에러 로그가 화면에 출력되었다
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->site.devdaramg.shop.dto.OrderResponseDto["orderItems"]->org.hibernate.collection.internal.PersistentBag[0]->site.devdaramg.shop.entity.OrderItem["product"]->site.devdaramg.shop.entity.Product$HibernateProxy$6bWNacdL["hibernateLazyInitializer"])
에러명 : com.fasterxml.jackson.databind.exc.InvalidDefinitionException
에러명으로는 무슨 에러인지 잘 모르겠다
좀 더 자세하게 확인 해보자
: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered
to create BeanSerializer
고민을 하면서 여러가지 시도를 해보다가 원인을 찾은 것 같다
에러 원인
: 반환되는 값을 Jackson이 변환하지 못해서 발생하는 문제
> 로그를 찍어보니 product 값이 없는 상태에서 이 값을 Jackson으로 변환하려고 하니까 문제가 발생
그럼 도대체 왜 값을 못가져 왔던걸까?
그 이유는 Product를 가져올 때 Lazy Loading으로 가져오게끔 해두었기 때문이다
즉, 다른 값들은 다 가지고 있지만, product 값은 지연로딩(Lazy Loading)이기 때문에 실제로는 값이 없는상태에서 Jackson 변환 시도
※ 지연로딩의 경우 실제로 product를 사용할 때, 쿼리를 날려서 값을 가져오는 방식
JPA와 Entity에 대해서 아직 잘 모르기 때문에 발생한 초보적인 실수라고 생각한다
해결 방법 3가지
1. FetchType.LAZY 부분을 제거한다(지연 로딩 => 즉시 로딩 변경)
2. @JsonIgnore를 문제가 발생하는 속성 위에다가 붙여주기(자동으로 Jackson 직렬화에서 제외)
3. 새로운 getter를 만들어준다
반환할 때 @Getter 속성(즉, getXXX으로 시작하는 모든 메소드)는 데이터에 담아서 반환하는 방식을 이용
해결 코드
에러 나는 product는 @JsonIgnore를 통해서 직렬화 되는 것을 막고, 필요한 product 데이터는 get메서드를 만들어서 가져오는 방식
문제 해결
[개인적인 의견]
1번의 경우 즉시로딩으로 변경 필요
- 하지만 우리는 지연로딩을 쓰고 싶다 (나중에 N+1등 문제를 예방하는데 도움이 된다)
2번의 경우 원하는 데이터를 수집할 수가 없다(JsonIgnore를 사용하기 때문에 product 정보를 가져올 수 없기 때문이다)
그래서 일단 3번을 적용해서 필요한 데이터를 가져오는 방식을 사용해서 코드를 수정하였다
☆ 가장 중요 Point : 반환 시 Entity를 반환하는게 아니라 ResponseDTO를 만들어서 반환하자
[요약]
REST API를 사용해서 반환할 때는 Entity가 아닌 ResponseDTO를 만들어서 반환하자
만약 Jackson 에러가 발생하면 속성의 값이 있는지 여부를 체크하자(지연로딩 체크)
getXXX메서드를 붙여주면 반환 데이터에 그 값이 포함된(원하는 데이터를 직접 추가할 수 있다)
아직 JPA와 Spring에 대해서 학습 진행중이기 때문에 잘못된 정보가 들어있을수 있습니다
부족하지만 저와 비슷한 경험을 하시는 분들에게 도움이 되었으면 좋겠으며, 혹여라도 잘못된 정보가 있을경우 댓글 또는 메일로 알려주시면 수정하도록 하겠습니다
긴 글 읽어주셔서 감사합니다
'Programming > Spring & Springboot' 카테고리의 다른 글
스프링부트3 백엔드 개발자 되기#1 (0) | 2023.12.09 |
---|---|
[MSA] Spring Cloud로 개발하는 마이크로서비스 애플리케이션 #1(Service Discovery) (0) | 2023.10.22 |
[REST] RESTful Service 구현방법 #6(RESTFUL API 설계 가이드) (0) | 2023.10.22 |
[REST] RESTful Service 구현방법 #2(SpringBoot와 RESTFUL Service) (0) | 2023.10.22 |
[REST] RESTful Service 구현방법 #1 (0) | 2023.10.22 |