본문 바로가기
Spring

[Spring Boot] ByteBuddyInterceptor 직렬화 에러 원인 및 해결 방법

by clolee 2025. 8. 4.

✅ [Spring Boot] ByteBuddyInterceptor 직렬화 에러 원인 및 해결 방법

🧨 에러 메시지 요약

No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor 
and no properties discovered to create BeanSerializer
...
(through reference chain: java.util.ArrayList[0]->pharos.groupware.service.team.domain.Team$HibernateProxy["hibernateLazyInitializer"])

💡 발생 원인

Spring에서 @RestController 혹은 @ResponseBody를 사용해 객체(List 등)를 JSON으로 반환할 때, Hibernate Lazy 로딩된 프록시 객체를 직렬화하려고 하면 위와 같은 오류가 발생할 수 있습니다.

즉,

@GetMapping("/api/team/teams")
public List<Team> getAllTeams() {
    return teamRepository.findAll(); // ← 이 Team 객체가 Lazy 프록시일 수 있음
}

이렇게 JPA 엔티티(Team)를 그대로 반환할 경우, 내부적으로 Hibernate 프록시 객체 (Team$HibernateProxy) 가 생성되며, Jackson은 이 객체를 직렬화할 수 없어 예외를 던지게 됩니다.


🔧 해결 방법

✅ 1. DTO로 변환해서 반환하기

가장 권장되는 방법은 Entity를 직접 반환하지 말고 DTO로 변환해서 리턴하는 것입니다.

💡 TeamDto 작성 예시 (record 사용):

public record TeamDto(Long id, String name) {
    public static TeamDto from(Team team) {
        return new TeamDto(team.getId(), team.getName());
    }
}
필요하다면 일반 클래스로 DTO를 선언해도 괜찮습니다. record는 단순 조회용에 적합하고, 일반 클래스는 유연성과 확장성 면에서 더 나은 선택일 수 있습니다.

 

💡 Service/Controller 수정:

// Service
public List<TeamDto> findAllTeams() {
    return teamRepository.findAll()
                         .stream()
                         .map(TeamDto::from)
                         .toList();
}

// Controller
@Operation(summary = "팀 목록 조회", description = "조직 내 모든 팀 정보를 조회합니다.")
@GetMapping("/api/team/teams")
public ResponseEntity<List<TeamDto>> getAllTeams() {
    return ResponseEntity.ok(teamService.findAllTeams());
}

🟨 DTO를 사용하면 Hibernate Lazy 프록시 문제를 자연스럽게 피할 수 있고, API 응답 필드를 명확히 제어할 수 있습니다.


🛑 2. Entity 직접 반환 (비추)

아래와 같은 방법들도 있지만 유지보수성과 확장성을 위해 추천되지 않습니다:

  • 엔티티에 @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) 추가
  • jackson-datatype-hibernate 모듈 추가 및 설정
  • FetchType.LAZY → EAGER 로 변경 (N+1 성능 문제 유발)

✅ 결론

구분 설명

❌ 문제 Hibernate 프록시 객체 직렬화 실패 (ByteBuddyInterceptor)
💡 원인 Lazy 로딩된 Entity 직접 반환 시 Jackson이 직렬화 못함
✅ 해결 Entity → DTO로 변환해서 반환 (TeamDto 등)
⛔ 피할 것 엔티티 직접 반환, Lazy → EAGER 변경 등

 

댓글