ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA Repository 기본 postfix로 인한 순환참조 해결
    Spring Framework 2023. 7. 30. 19:40
    반응형

    1) 서론

    요즈음 스프링 프레임워크를 사용한다면 Spring Data JPA는 기본적으로 사용하게 되는데요.

     

    ORM 프레임워크는 RDB의 테이블을 객체로서 나타내고 맵핑할 수 있게 합니다. 애플리케이션에서 테이블에 질의할 때 쿼리와 데이터 중심이 아닌 객체로서 바라보는 것이 가능해졌습니다. 객체지향적인 설계에 큰 도움을 주게 됩니다.

     

    이외에도 메서드를 활용하여 자동완성 되는 쿼리를 손쉽게 사용할 수 있는데요.

     

    하지만 JDBCTemplate 같은것을 활용하여 쿼리를 날리는 것에 비해 주의해야 할 점이 많이 생겼습니다. 영속성 컨텍스트를 이해하지 못하거나 트랜잭션의 관리가 잘 되지 않는다면 예상치 못한 문제들이 발생할 수도 있는데요.

     

    이번에는 Repository를 정의하고, 이에 대한 순환참조가 발생한것을 간단히 정리해보려고 합니다.


    2) 배경

    전체 패키지 구조는 이렇습니다.

    테스트를 위해서 간단한(엉망인) 엔티티를 하나 생성합니다.

    • BaseEntity에서 id, createdAt, updatedAt과 같은 간단한 정보들을 가집니다
    • HelloEntity에서는 hello 필드만 가집니다. 그리고 BaseEntity를 상속받습니다

     

    코틀린이 생소할 수 있지만 일반적인 자바에서 사용하는것과 동일합니다. 인터페이스를 구현하고, 의존성 주입합니다.


    3) 순환참조 문제 발생

     

    빌드했을 때 위와 같이 순환참조가 발생하는데요. 단순히 JpaRepository 인터페이스를 상속받고, 이것을 Impl 클래스에서 구현하고 있습니다. 순환참조가 발생할 이유가 없어 보입니다.

     

    의존성 주입한 HelloRepository를 제거하면 정상적으로 빌드가 되는데요. 이유가 뭘까요?


    4) 원인

    Spring Data JPA의 기본 설정이 순환참조의 원인인데요.

     

    Spring Boot Data JPA의 repository 인터페이스는 접미사(postfix) Impl인 클래스를 scan 하게 되는데요. 즉 HelloRepository는 bean으로 등록될 때 HelloRepositoryImpl 클래스를 구현체로서 탐색하게 됩니다. 해당 클래스가 꼭 있어야 하는 것은 아닙니다.

     

    하지만 HelloRepositoryImpl 클래스에 HelloRepository가 의존성 주입되어 있습니다. 즉, 아래와 같은 과정을 거치는데요.

    1. HelloRepository bean으로 등록
    2. HelloRepositoryImpl를 의존성 주입
    3. HelloRepositoryImpl > HelloRepository를 탐색
    4. HelloRepository > HelloRepositoryImpl 다시 의존성 주입 시도 (순환참조)

     

    위와 같은 일련의 과정을 거치며, 서로가 서로를 참조하는 순환참조가 발생합니다.

     

    여기서 생성자 방식의 순환참조의 장점이 드러납니다. ApplicationContext에 bean이 생성되고 등록되는(객체 생성) 시점에서 문제를 발견할 수 있습니다. setter 방식을 사용했다면 해당 클래스가 요청됐을 때 발견됐을 것이고, 무한으로 순환참조가 발생하다가 스택오버플로우가 발생할 것입니다.

     

    그렇다면 어떻게 해결할 수 있을까요?


    5) 해결방법

    5. 1) 이름 변경하기

    가장 쉽고 단순한 방법은 HelloRepository 혹은 HelloRepositoryImpl의 이름을 변경합니다. HelloRepository > HelloJpaRepository로 이름을 변경합니다.

    HelloJpaRepositoryHelloJpaRepositoryImpl 구현체를 탐색합니다. 그리고 현재 의존성 주입 중인 impl 클래스와는 이름이 다르기 때문에 문제없습니다.

     

    정상적으로 빌드되고 애플리케이션이 구동됩니다.

    5. 2) 접미사(postfix) 재정의하기

    만약 프로젝트의 컨벤션이 존재한다면 어떻게 될까요? 관련하여 문제가 될 수 있는 모든 부분을 변경하는 것은 쉽지 않을 것입니다. 이미 정의된 다른 이름들과 혼동이 오고, 전체 컨벤션이 깨질 수 있는데요.

    위와 같이 @EnableJpaRepositories 애노테이션을 이용하여 접두사를 재정의할 수 있습니다. 'impl'로 되어 있는 기본 설정을 재정의하는 것인데요. 재정의 하게 되면 repository는 해당 접두사로 된 구현 클래스를 탐색하게 됩니다.

     

    접두사를 재정의하게 되면 위와 같이 정상적으로 빌드와 애플리케이션 구동이 완료됩니다.

    6) 참고 문헌


    Spring Data JPA 공식 문서

    반응형

    댓글

Designed by Tistory.