Spring

Spring - 엔티티를 직접 Response로 반환할 경우

윤승 2025. 6. 20. 20:26

문제 현상

  • REST API에서 DTO 없이 엔티티(Entity)를 직접 Response로 반환할 경우, 서로의 연관 관계가 계속 참조를 일으켜 무한 순환 참조 문제가 발생한다.
  • 결과적으로 API 응답 시 무한 로딩 현상 및 StackOverflowError가 발생하게 된다.

📌 원인 분석

 순환 참조란?

  • 두 엔티티가 서로를 참조하면서 객체 직렬화 과정에서 무한히 서로를 호출하는 상황.

 

Profile 엔티티와 연관된 Keyword 엔티티를 직접 반환하면, 다음과 같은 순환 구조가 형성될 수 있다:

💡 Profile → ProfileKeyword → Keyword → ProfileKeyword → Profile → … (무한 반복)

🔸 문제 예시 코드

// Entity를 그대로 반환하는 잘못된 예시
@Entity
public class Profile {
    @OneToMany(mappedBy = "profile")
    private List<ProfileKeyword> profileKeywords;
}

@Entity
public class ProfileKeyword {
    @ManyToOne
    private Profile profile;

    @ManyToOne
    private Keyword keyword;
}

@Entity
public class Keyword {
    @OneToMany(mappedBy = "keyword")
    private List<ProfileKeyword> profileKeywords;
}

  • 위와 같이 서로가 서로를 직접 참조하고 있어, JSON으로 직렬화할 때 순환 참조로 인해 무한 반복이 발생하게 된다.

JSON 예시:

keywords : [
      id:
      name:
      profileKeywords: [
            id:
            profile: {
         
            },
            keyword: {
 
            }
]
]

 


 트러블 슈팅 해결 방법

✅ DTO를 활용

  • DTO를 만들어 순환 참조를 끊고 필요한 정보만 전달하여 무한 참조를 방지한다.
// ProfileResponseDto 예시
public class ProfileResponseDto {
    private Long id;
    private String title;
    private List<String> keywords;

    public static ProfileResponseDto from(Profile profile) {
        ProfileResponseDto dto = new ProfileResponseDto();
        dto.id = profile.getId();
        dto.title = profile.getTitle();
        dto.keywords = profile.getProfileKeywords().stream()
            .map(pk -> pk.getKeyword().getName())
            .collect(Collectors.toList());
        return dto;
    }
}

  • 이렇게 하면 실제 엔티티 대신 간단한 문자열 리스트나 프리미티브 타입만 담긴 DTO를 반환하여 순환 참조를 막는다.

 

REST API에서 데이터를 반환할 때는 항상 DTO를 활용하여 필요한 데이터만 선별하여 반환하자!