일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 값 타입
- spring
- Git
- 알고리즘
- VB
- PDFBOX
- 코딩테스트
- 연관관계
- 프로그래머스
- Hibernate
- Java
- querydsl
- 제작기
- 테킷
- spring jpa
- JPA
- Visual Basic
- 반복문 탈출
- 멋쟁이사자처럼
- GitFlow
- 부트캠프
- break-label
- DOCS
- springboot
- 커밋 컨벤션
- 체인호출
- PDF병합
- responsepart
- orm
- 스프링부트 쇼핑몰 프로젝트
- Today
- Total
섭섭한 개발일지
[SpringBoot RestAPI] 반환 객체 proxy 에러 hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor 본문
[SpringBoot RestAPI] 반환 객체 proxy 에러 hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor
Seop 2024. 3. 1. 03:53Response 시 무한참조로 인한 JSON infinity exception
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError)]
프로젝트 중에 위와 같은 에러를 마주쳤다.
에러는 문의사항 1개의 정보를 가져오는 부분에서 에러가 발생을 했고 에러 내용은 무한한 json을 만드는 것으로 확인된다.
찾은 이유는 아래의 코드에서 발생한 문제로 확인된다.
@Entity
public class Member extends BaseEntity {
@Comment("회원의 문의 내역")
@OneToMany(mappedBy = "member")
@Builder.Default
private List<Question> questions = new ArrayList<>();
}
@Entity
public class Question extends BaseEntity {
@Comment("문의사항 작성자")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Member member;
public void addMember(Member member) {
this.member = member;
member.getQuestions().add(this);
}
}
Entity를 보기 편하게 문제가 된 부분만 축소시켰다.
문제는 여기다 Member와 Question이 Lazy 로딩으로 인해서 서로가 필요에 따라 데이터를 조회하게 되는데 이때 무한히 순환이 되면서 JSON Infinite가 발생하는 것이다.
문제를 해결하기 위해 Member에서 Question에 대한 데이터를 가지고 있을 필요는 없을 것 같다고 생각했고 Member에서는 Question에 대한 매핑관계를 해제했다.
Resolved [org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]]
Member와 Question이 순환하며 발생하던 에러가 매핑 관계를 해제하니 변경되었다. 참고 게시글
이 에러는 response dto에서 entity의 프록시 객체를 사용하기에 발생하는 오류로 확인이 된다.
현재 response dto를 확인해보면
public class QuestionResponse {
@Schema(description = "문의사항 고유 식별 번호")
private Long id;
@Schema(description = "문의사항 작성자")
private Member member;
@Schema(description = "문의사항 제목")
private String title;
@Schema(description = "문의사항 내용")
private String content;
@Schema(description = "문의사항 등록 이미지")
private NcpFileResponse file;
@Schema(description = "문의사항에 등록된 답변")
private List<AnswerResponse> answers;
}
위와 같이 되어 있고
Member 가 response 가 아닌 실제 엔티티 클래스로 타입이 잡혀있다.
이 오류의 주된 문제는 Jackson 라이브러리가 클래스에 대한 직렬화 기능을 찾지 못했다는 것이다.
이 문제는 하이버네이트의 프록시 객체때문인데 지연로딩을 하기위해서는 프록시 객체를 사용하므로 Question에 있는 Member 가 문제가 된 것이다.
그럼 문제가 있는지 확인하기 위해
우선 QuestionResponse 에서 Member를 Response 형태로 변경을 해보겠다.
public class QuestionResponse {
...
@Schema(description = "문의사항 작성자")
private MemberResponse member;
...
}
postman 으로 조회가 가능해졌다.
Response를 통해서 문제가 처리된 걸 생각해서
첫번째 순환참조가 되며 무한히 만들어지던 문제는 다시 원본 코드로 복구를 해도 될 것 같다
복구를 해도 정상적으로 데이터가 조회가 되며
결과적으로 문제는 rest 통신간에 java 데이터를 json으로 변환하는 하는 과정에서 프록시 객체의 문제점으로 파악이 된다 !
끝 !
'프로그래밍 > Spring' 카테고리의 다른 글
[Swagger] Java DTO를 Record로 사용 시 Swagger 오류 (0) | 2024.07.19 |
---|---|
[SpringBoot RestAPI] Controller에서 json(dto)과 multipart 동시 요청 (0) | 2024.02.21 |