본문 바로가기

Spring

Could not write JSON: Infinite recursion (stackOverflowError)

728x90
반응형
SMALL

 

해당 오류가 난 원인은 무한적인 재귀호출로 인한 스택오버플로우가 난거다.

 

Member 테이블 과 Team 테이블이 있다.   (Member : Team = N : 1) 다 대 1 관계다.

public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
    
    
}
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String teamName;
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

}

 

Controller 이다.

    @GetMapping("")
    public List<Member> select(){
        List<Member> members = memberRepository.findAll();
        for (Member member:members){
            System.out.println("member = " + member.getTeam().getTeamName());
        }
        return members;

Member 와 Team 이 서로 양방향 관계에 놓여있어, JSON 포맷팅 과정에서 무한순환참조가 된다.

그래서 해당 오류가 발생한다.

 

 

해결책 3가지

 

1. @JsonIgnore

@oneToMany 부분에 @JsonIgnore 를 붙여주면 해결이다.

이는 해당 프로퍼티의 값을 null로 만들어주며, 데이터가 들어가는걸 막아준다.

 

 

 

2. @JsonMangedReference와 @JsonBackReference

    @JsonManagedReference
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
    @JsonBackReference
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;

이런 식으로 연관관게가 걸려있는 곳에 적어준다.

@JsonMangedReference 가 걸려있는 클래스에서는 해당 부분을 직렬화시키며,

@JsonBackReference 가 걸려있는 클래스에서는 직렬화를 막는다.

 

 

3. DTO 사용

엔티티 자체를 응답값으로 리턴하려고 하니, 이런 이슈들이 발생한다.

결론적으로 엔티티 자체를 리턴하기에는 보안쪽으로도 치명적일수 있을 뿐더러, 필요없는 값까지 넘겨줘야 한다.

그럴때는 응답DTO를 새로 만들어, 필요한 데이터만 리턴할수 있도록 하는것이 가장 베스트 라고 생각한다.

 

DTO를 사용한다면, 글의 제목에 보이는 오류는 절대 만나지않을것이다.

728x90
반응형
LIST

'Spring' 카테고리의 다른 글

spring 에서 @Async 어노테이션 사용하기(비동기)  (1) 2023.04.20
List -> Page 변환  (0) 2023.03.20
@ModelAttribute 와 @RequestParam  (0) 2022.12.29
SpringBoot 란?(스프링부트)  (0) 2022.04.08
Spring(스프링) 이란? 뭘까?  (0) 2022.03.27