Could not write JSON: Infinite recursion (StackOverflowError) (through reference chain: com.codersgate.ticketraider.domain.event.model.Event["place"]->com.codersgate.ticketraider.domain.place.model.Place["eventList"]->org.hibernate.collection.spi.PersistentBag[0]->com.codersgate.ticketraider.domain.event.model.Event["place"]->com.codersgate.ticketraider.domain.place.model.Place["eventList"]->org.hibernate.collection.spi.PersistentBag[0]->com.codersgate.ticketraider.domain.event.model.Event["place"]->com.codersgate.ticketraider.domain.place.model.Place["eventList"]->org.hibernate.collection.spi.PersistentBag[0]->com.codersgate.ticketraider.domain.event.model.Event["place"]->com.codersgate.ticketraider.domain.place.model.Place["eventList"]->org.hibernate
Entity 를 직접 직렬화 시도할 경우 만약 양방향 관계가 설정되어있을 경우 위와같은 순환참조 오류가 발생할 수 있다.
이럴 경우 대상 Entity의 구조를 수정하여 순환참조를 제거해주어야 하는데( Jackson ObjectMapper) 를 사용하여 순환참조를 무시하게 할 수도 있다고 한다. ) 만약 양방향 참조가 필요하다거나, softDelete 를 위해 영속성 전파가 필요하다면 더 간단한 방법이 있다.
바로 JSON 직렬화를 위한 DTO 클래스를 만들어 순환 참조를 끊는 것이다. ( ~~Response 처럼 자주 쓰이는 DTO 들 )
DTO 를 활용하여 데이터를 전송하여 Entity 는 DB 만 상호작용 할 수 있도록 하는 것이 구조적으로도 올바른 사용법이기 때문이다.
그 외에도 몇가지 장점이 있다.
직렬화의 용이성: DTO는 주로 데이터 전송 객체로 사용되며, 일반적으로 Entity보다 더 간단하고 직렬화하기 쉽다. 캐시에는 직렬화된 형태의 데이터를 저장하므로 DTO를 사용하면 더 효율적으로 데이터를 저장하고 검색할 수 있다.
데이터 의존성 감소: DTO를 사용하면 캐시에 저장되는 데이터가 엔티티와 직접적으로 연결되지 않아 데이터 의존성이 줄어든다. 이는 시스템의 유지보수성을 향상시키고 데이터 모델의 유연성을 높인다.
데이터 정규화: DTO를 사용하면 필요한 필드만 포함하여 캐시에 저장할 수 있다. 이는 캐시에 저장되는 데이터의 크기를 줄이고 네트워크 대역폭을 절약할 수 있다.
보안 및 개인 정보 보호: Entity에는 애플리케이션의 중요한 정보가 포함될 수 있으므로, 보안상의 이유로 DTO를 사용하여 캐시에 저장하는 것이 안전하다. 민감한 개인 정보를 포함하지 않는 간소화된 데이터를 사용함으로써 보안 문제를 방지할 수 있다.
의존성 관리: Entity는 데이터베이스와 직접적으로 연결되어 있으므로, 캐시에 Entity를 직접 저장하면 데이터베이스의 변경이 캐시에도 영향을 줄 수 있다. 하지만 DTO를 사용하면 데이터베이스와의 의존성을 낮추고, 캐시와의 의존성을 높일 수 있다.