본문 바로가기

Back-End 공부/Spring

Spring에서 발생하는 대표적인 순환참조 문제 해결하기

1. 서로가 IoC에 등록되길 기다리는 경우

 

 

[ AuthorService.java ]

@Service
public class AuthorService {
    private final AuthorRepository authorRepository;
    private final PostService postService;
    @Autowired
    public AuthorService(AuthorRepository authorRepository, PostService postService) {
        this.authorRepository = authorRepository;
        this.postService = postService;
    }

 

[ PostService.java ]

@Service
public class PostService {
    private final PostRepository postRepository;
    private final AuthorService authorService;
    @Autowired
    public PostService(PostRepository postRepository, AuthorService authorService) {
        this.postRepository = postRepository;
        this.authorService = authorService;
    }

 

서로가 서로를 주입 받으려고 하는데

어느 것 하나 싱글톤으로 완전히 등록되지 않기 때문에 서로가 등록되기를 무한 기다림 => 순환참조 이슈 발생

 

 

 

PostService에서 AuthorService를 주입받지 말고,

필요한 메서드를 AuthorRepository에 구현하면서 순환참조 문제를 해결해준다.

 

 

 

2. 엔티티(Json) 순환참조

 

[ AuthorController.java ]

// 직렬화 순환참조 이슈
@GetMapping("author/{id}/circle/entity")
@ResponseBody
//연관관계가 있는 Author 엔티티를 json으로 직렬화를 하게 될 경우
//순환참조 이슈 발생하므로, DTO 사용 필요.
public Author circleIssueTest1(@PathVariable Long id){
    return authorService.findById(id);
}

@GetMapping("author/{id}/circle/dto")
@ResponseBody
public AuthorDetailResDto circleIssueTest2(@PathVariable Long id){
    return authorService.findAuthorDetail(id);
}

 

 

Author 객체

{

   "id" : xxx,

   "name" : xxx,

   "posts" : [ {"id" : xxx. "author" : xxx}, {} ] 

}

author 객체를 만들기 위해 post를 가서 보니

post는 Author author를 가지고 있어, post에서 author를 다시 참고하러 옴.

author에는 아직 posts 정보를 가져오기 못했기 때문에 다시 post로 감.

➡️ 무한 순환참조 발생

 

 

DTO를 통해 Author 객체에서 post 객체를 가지고 있는 것이 아닌,

post 객체의 특정 속성이나, 특정 속성을 통해 계산한 값을 참조하게 변경해주면 된다.

@Data
public class AuthorDetailResDto {
    private Long id;
    private String name;
    private String email;
    private String password;
    private String role;
    private int counts;
    private LocalDateTime createdTime;
}

 

 

 

(1) 순환참조 발생하는 경우

Author 클래스에는 List<Post> posts가 있고, Post에는 Author author를 가지는 경우이다.

 

post 테이블에서 글을 쓴 author_id를 넣고 테스트해보면 된다.

 

 

 

(2) DTO를 통해 순환참조 풀어줘서 에러 발생하지 않는 경우