Jpa + Jackson Serialization 삽질기

Jpa를 사용하니 객체(Entity)의 연결이 매끄러워졌다.

A 객체를 조회했을 때 A.B 가 가능하고, 반대로 B 객체를 조회했을 때도 B.A가 가능하다.

심지어 개발자는 데이터베이스 질의(Query)를 고민할 필요가 없다.

이 얼마나 좋은 세상인가!

 

이 좋은 세상에서 나는 나의 꿈을 마음껏 펼칠려는 무렵 Jpa와 Jackson은 현실이 그렇게 녹록치 않음을 깨닫게 해줬다.

간단한 조회 API를 개발했고 조회 결과는 json으로 반환한다.

얼마나 멋지게 만들었는지 자찬하기 위해 API를 테스트해봤다.

헉 … 이 멋진 API의 json 응답 데이터 크기가 무려 375K ! ㄷㄷㄷ

 

마음 속의 거만함을 급히 내팽겨치고 왜 이런 일이 발생했는지 객체의 구조를 살펴봤다.

A.B.A.B.A ..  객체는 Circular reference의 형태였다. ㅠ

 

이제 나는 A를 조회하는 json API를 위해 A.B = null 을 할당해야 하는 암담한 현실을 이해한 것 같다.

이 얼마나 우아하지 못하고 실용적인 방식인가.

 

다른 개발자들은 이 문제를 어떻게 해결할까?

구글갓은 나의 기도 같은 검색 요청에 이번엔 친절했다.

infinite-recursion-with-jackson-json-and-hibernate-jpa-issue

jackson-serialization-of-entities-with-birectional-relationships-avoiding-cyc

JacksonFeatureObjectIdentity

 

위 3개의 링크를 통해 나는 2가지를 얻게 되었다. (3개를 봤는데 2개를 얻다니!)

  1. JsonIdentityInfo : 객체의 ID 속성을 이용해 한번만 serialize 되도록 해준다. 따라서 A.B.A.B … 의 객체 구조는 A.B 까지만 변환이 되고, B.A는 변환되지 않는다.
  2. Jackson-module-hiberate : Jpa Entity의 lazy loading 되는 부분은 json 변환에서 제외해준다. 상황에 따라서 다르겠지만 사실 나는 B도 불필요했기 때문에 유용하게 쓸 수 있을 것 같다.

 

JsonIdentityInfo는 Jpa Entity 클래스에 추가해주자.

예를 들어 아례와 같이 사용할 수 있다.

 

jackson-module-hibernate는 ObjectMapper에 적용해주자.

 

이 두가지를 적용해서 json API의 응답이 374KB 에서 400B로 줄어들었다.

다른 사람들이 보기 전에 해결해서 다행이다.

  • mars