• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

커스텀 인터페이스 구현체 이름 작성 시 순환 참조 발생 질문

24.01.18 23:27 작성 조회수 160

1

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오) 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예

[질문 내용]
여기에 질문 내용을 남겨주세요.

 

안녕하세요 영한님. 이번 강의도 잘 수강한 학생입니다.

강의 내용과 공식 문서를 참고하며 간단한 게시글 리포지토리를 만들어보고자, 아래처럼 작성했었습니다.

 

public interface BoardRepository {

    Long save(final Board board);
    ...
}
@Repository
@RequiredArgsConstructor
public class BoardJpaRepositoryImpl implements BoardRepository {

    private final BoardJpaRepository boardJpaRepository;
    ...
}
public interface BoardJpaRepository extends JpaRepository<Board, Long> {
}


강의 내용대로 스프링 데이터 JPA인 BoardJpaRepository에 Impl을 붙인 BoardJpaRepositoryImpl을 만들었는데, 아래와 같이 순환 참조 문제가 발생했습니다.

 

The dependencies of some of the beans in the application context form a cycle:

   boardController defined in file [/Users/hyunjoonchoi/Desktop/2024/2024-mju-mentoring/build/classes/java/main/com/mju/mentoring/board/controller/BoardController.class]
      ↓
   boardService defined in file [/Users/hyunjoonchoi/Desktop/2024/2024-mju-mentoring/build/classes/java/main/com/mju/mentoring/board/service/BoardService.class]
┌─────┐
|  boardJpaRepositoryImpl defined in file [/..../build/classes/java/main/com/mju/mentoring/board/infrastructure/BoardJpaRepositoryImpl.class]
└─────┘


Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.


그런데 이름을 BoardRepositoryImpl, JpaBoardRepositoryImpl 등 다른 이름으로 하니까 순환 참조 문제가 해결되더라구요

이에 대해서 다른 외국 개발자 분들도 이슈로 올리고, 그것들을 찾아봤으나 메인테이너 분이 @Lazy를 사용하거나 ObjectProvider를 사용해야 한다고 말씀해주시는 것 밖에 없었습니다.

 

공식 문서 (https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/repositories.html#repositories.create-instances)를 보면 스프링 데이터 JPA + Impl로 할 시 자동으로 스프링 데이터 JPA의 구현체로 인식한다고 되어 있는 것 같은데, 이런 순환 참조 이슈가 발생한 원인을 알 수 있을까요? 이를 해결해보고자 스프링 데이터 JPA 레포지토리에 직접 이슈로 남기고 (https://github.com/spring-projects/spring-data-jpa/issues/3320) 답변을 받았긴 했습니다만, 여전히 다른 이야기를 하시는 것 같아 영한 님께도 문의드리고 싶습니다!

답변 1

답변을 작성해보세요.

1

devholic님의 프로필

devholic

질문자

2024.01.18

공식 답변은 아니지만 추측으로 원인을 알 수 있을 것 같습니다.

 

영한 님의 자료나 공식 문서에서는 스프링 데이터 JPA 인터페이스를 구현한 구현체에 스프링 데이터 JPA 인터페이스를 주입하지 않고, EntityManager 등을 이용하여 CRUD를 구현하였습니다.

 

그런데 저는 스프링 데이터 JPA 인터페이스를 구현한 구현체에 스프링 데이터 JPA 인터페이스를 바로 필드로 주입받도록 했습니다. 즉, 순수 자바로 치면 SampleRepositoryImpl에 SampleRepository를 받은 것 입니다. 따라서 자기 자신을 직접 참조하게 되어 이 과정에서 순환 참조가 발생한 것으로 판단됩니다. (기본 전략이 스프링 데이터 JPA 인터페이스의 이름 + Impl이라, 지금 예시를 보면 정확히 그렇습니다.)

 

만약 스프링 데이터 JPA 환경에서의 구현체를 만들고 싶으신 분들은 기본 설정을 변경하거나, 파일 이름을 변경하는 등 (ex: BoardJpaRepository일 경우 BoardJpaRepositoryImpl 말고 JpaBoardRepositoryImpl로 하는 등)의 전략을 취하셔야 할 것 같습니다.

devholic님 스스로 문제를 찾고 또 답변까지 남겨주셔서 감사합니다. 저도 관련 이슈가 있으면 말씀하신 내용을 참고해봐야겠네요 🙂