본문 바로가기

IT 고찰/일상에서만난IT오류

JPA repository 사용시 무한 순환에 빠지는 문제(Equals and HashCode) [lombok]

좋은 글 : lombok 라이브러리와 하이버네이트 사용 시 주의해야 할 점. 

 

https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/

 

Lombok & Hibernate: How to Avoid Common Pitfalls

Lombok is incredibly popular for basic Java classes. But it introduces some dangerous pitfalls when used together with Hibernate.

thorben-janssen.com


 

Lombok 라이브러리를 생각없이 사용하다가 수백 분을 날려버렸다.

 

스프링 부트 프로젝트 진행 중에 1 to N 관계의 테이블을 사용하게 되었다.

 

구글링을 통해 처리해야 할 설정을 명확히 했음에도 불구하고

 

repository에서 findBy~ 관련 메서드를 날리면 무한순환에 빠지면서 스택오버플로우로 죽어버렸다.

 

에러 메시지를 보면 어디선가 순환 구조에 빠졌다는 것이 명백하다.

 

하지만 어디서 이 문제가 생기는 것인지를 몰라서 많은 시간을 허비했다. 

 

내가 설정한 엔티티의 경우 순환구조를 가지다 보니(양방향) 몇몇 개의 롬복 애너테이션으로 생성된 메서드가 순환 참조를 하게 되면서 서로를 무한히 호출하는 구조에 빠져버리는 것이다.

 

이런 문제는 고질적으로 많이들 접하는 문제였고 해당 문제를 해결하기 위해서 애너테이션에 속성 값을 넣을 수 있었다.

 

@ToString.Exclude 설정과. 

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)

와 같은 설정이 대표적이었다. 

 

나의 경우 json의 문제도 아니었고, toString()의 문제도 아니었다.

 

진짜 문제는 EqualsAndHashCode에 있었다.

 

아무 생각없이 롬복 라이브러리 활용에 있어서 @EqualsAndHashCode을 사용해서 생긴 문제였다. 

 

이 글의 맨위에 있는 링크에서 하이버네이트를 이용할 때 롬복 애너테이션을 활용할 경우 EqualsAndHashCode를 피하라고 한다.

 

ORM은 관계형 DB 테이블을 객체지향에서이 엔티티와 매핑해주는 기술이다.

 

Equals 메서드로 확인하고자 하는 동일성에 대한 의미가 없는 영역이다.

 

이미 DB를 설계할 때 우리는 테이블에 primary key 값을 세팅한다. 해당 값이 같으면 동일하다고 말할 수 있다.

 

그리고 우리는 엔티티를 그렇게 비교한다.

 

그래서 EqualsAndHashCode는 쓸모가 없는 것이다. 

 

혹시 나와 같이 toString과 Json이 순환 참조되는 것을 방지했음에도 쿼리가 제대로 실행되지 않는 경우라면

 

EqualsAndHashCode 애너테이션을 사용한 것이 아닌지 살펴보자.

 

마찬가지 이유에서 ToString()의 경우도 주의하라고 한다. 

 

프로젝트를 진행하다 보니까 DB쪽에서 상당한 어려움을 경험하고 있다.

 

객체지향적인 시각 -> DB(관계지향적(절차적인))쪽으로의 시선으로 넘어가야 하기 때문..

 

그래서 JPA가 꽤나 어려운 영역이라고 하는 것 같다.

 

시간이 되면 JPA관련해서 공부 좀 해야겠다.

반응형