문제 현상
- 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를 활용하여 필요한 데이터만 선별하여 반환하자!
'Spring' 카테고리의 다른 글
AWS Route 53으로 도메인 연결하기 (5) | 2025.06.24 |
---|---|
EC2 인스턴스 + Docker 컨테이너 배포 (2) | 2025.06.23 |
Spring Boot + Redis + Docker 연결 문제 트러블 슈팅 (1) | 2025.06.20 |
인기 검색어에 Redis 캐싱과 TTL적용 (8) | 2025.06.12 |
15만권 도서 검색 서비스에 캐시 적용하기 (4) | 2025.06.09 |