JPA에서 엔티티를 등록하고 ToString을 호출할 때 연관 관계가 적용되어있으면 순환 참조로 인해 StackOverFlow가 발생하게 된다.
Lombok @ToString 동작 원리
다음과 같은 상황을 보자.
@Entity
@Getter
@ToString
public class Member {
@Id
@GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
@Entity
@Getter
@ToString
public class Team {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
Lombok의 @ToString Annotation은 다음과 같이 출력한다고 한다.
@Override public String toString() {
return "Team(" + this.getId() + ", " + members.toString() + ")";
}
@Override public String toString() {
return "Member(" + this.getId() + ", " + this.team + ")";
}
@ToString 순환 참조 문제
이 과정에서 문제가 생긴다.
Collections.toString()은 Collection에 등록되어 있는 각 객체에 선언되어 있는 toString() 메서드를 보고 객체마다 출력해주는 역할을 한다.
그런데 지금 상황을 보면 team에도 toString이 있고, member에도 toString이 있다.
team에 속해있는 1명의 멤버에 대해서 toString을 실행하면 member.team 을 또 호출하고, team은 또 team.members.toString()을 또 호출하게 되는 상황이 발생하여, 계속해서 콜 스택이 쌓이게 되고 그 결과로 StackOverFlow가 발생하게 되는 것이다.
@ToString 순환 참조 해결방안
그럼에도 불구하고, @ToString은 객체에 대한 정보를 호출해주는데 있어서 너무나도 많은 역할을 해준다.
순환참조에 대한 해결은 직접 필드를 등록해줌으로써 해당 필드는 toString에 포함이 되지 않도록 할 수 있다.
@Entity
@Getter
// @ToString(of = "id") id만 toString
@ToString(of = {"id", "age"}) // id와 age toString
public class Member {
@Id
@GeneratedValue
private Long id;
private int age;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
위와 같은 방식으로 직접 사용하고자 하는 필드를 선언해줄 수 있다. 또 위처럼 직접 필드를 주입하는 것이 귀찮다면 다음과 같은 방법을 선택 할 수도 있다.
@Entity
@Getter
@ToString
public class Member {
@Id
@GeneratedValue
private Long id;
private int age;
@ToString.Exclude // 해당 필드는 toString에 포함하지 않는다.
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
필드의 개수에 맞게 적절하게 사용하는 것이 좋겠다.
@ToString을 사용하면서 어떻게 순환 참조를 해결할까 하다가 공식문서를 보고 해결하게 되었다.
나중에 기회가 된다면 Lombok 총 정리 포스팅을 한 번 해볼까 한다.
참고 문서
https://projectlombok.org/features/ToString
https://www.baeldung.com/lombok-tostring
'Language' 카테고리의 다른 글
[UML] 클래스 다이어그램 (2) | 2023.05.20 |
---|---|
gradle build vs Intellij IDEA build (0) | 2023.05.20 |
전략 패턴 (0) | 2023.04.16 |
템플릿 메서드 패턴 (2) | 2023.04.15 |