[SpringBoot] spring-data-jpa 사용시 @Repository 어노테이션은 꼭 필요한가?

이상훈·2021년 12월 12일
3

spring

목록 보기
1/4
post-custom-banner

📕 필요 없어!

결론부터 말하면 spring-data-jpa의 JpaRepository를 상속받아 사용 시 의존성 주입 및 빈등록을 위해 @Repository 어노테이션을 사용할 필요가 없다.

📕 스프링 컨테이너와 빈(Bean)

스프링 어플리케이션은 동작시 @ComponentScan 어노테이션을 통해 코드의 컴포넌트를 읽어 싱글톤 패턴으로 빈을 컨테이너에 등록한다.

그래서 우리는 개발을 할때 @Controller, @Service, @Repository 같은 어노테이션을 활용해 의존성 주입을 위한 빈 등록을 해준다.

📕 @Repository의 사용처

@Repository의 사용

public interface TestRepository {
    Long 회원가입();
    User 회원조회();
    User 회원수정();
    void 회원삭제();
}
@Repository
public class TestRepositoryImpl implements TestRepository{
    @Override
    public Long 회원가입() {
        return null;
    }

    @Override
    public User 회원조회() {
        return null;
    }

    @Override
    public User 회원수정() {
        return null;
    }

    @Override
    public void 회원삭제() {

    }
}

위와같이 인터페이스를 정의하고 클래스로 그 구현체를 만들어 사용한다.

@Test
void repositoryBeanDefinitionTest() {
	for(String s : df.getBeanDefinitionNames()){
		if(s.contains("Repository")) System.out.println(s);
	}
}

위 테스트 코드를 스프링부트 통합테스트를 통해 실행해주면

와 같이 정상적으로 TestRepositoryImpl이 빈으로 등록되어 출력되는걸 확인할 수 있다.

만약 TestRepositoryImpl에 @Repository를 생략하게되면 빈등록이 되지 않아 의존성 주입을 할 수 없게된다.

📕 @Repository와 spring-data-jpa

JpaRepository를 상속받은 리포지토리는

public interface TestRepository extends JpaRepository<User, Long> {
    
}

이런형식으로 된 코드를 확인할 수 있다.
스프링 컨테이너 및 빈등록, 의존성 주입 등을 공부하며 돌아보니, 여기에는 왜 @Repository 어노테이션이 없어도 의존성 주입이 되는거지? 라는 의문점이 들었다.

위의 코드를 테스트 돌려보면 아래와같이 빈 등록이 정상적으로 되어있는것을 확인할 수 있다.

여기서 든 생각은 JpaRepository 인터페이스를 상속하면 자동으로 빈 주입이 되는것인가? 라는 생각이 문득 들었다.

JpaRepository 코드를 뜯어보니

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> 

@NoRepositoryBean이라는 어노테이션을 확인하였고, 검색을 통해 찾아본 결과

Repository 인터페이스를 상속받았기 때문에 실제 빈을 만들지 않도록 하기 위하여 사용되고,
실제 사용되는 Repository가 아님을 표시하는것 이였습니다.

그럼 실제 빈등록은 어디서 이루어 질까?

📕 @EnableJpaRepositories

spring-data-jpa의 리포지토리 빈 등록은 @EnableJpaRepositories 어노테이션에서 이루어 집니다.
SpringBoot에서는 자동 설정되어 생략해도 되지만, 원리를 파악해보기 위해 코드를 뜯어보겠습니다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(JpaRepositoriesRegistrar.class)
public @interface EnableJpaRepositories

위 코드의 5번째 라인을 보면 JpaRepositoriesRegistrar.class가 임포트 되어있는것을 확인할 수 있습니다.
여기에서 실제로 JpaRepository를 상속받은 repository 인터페이스를 빈으로 등록해주는 역활을 합니다.

profile
Hello!
post-custom-banner

2개의 댓글

comment-user-thumbnail
2021년 12월 26일

여기에서 실제로 JpaRepository를 상속받은 repository 인터페이스를 빈으로 등록해주는 역활을 합니다.
구체적으로 어떤 클래스의 메소드에서 진행되는지 힌트를 받을 수 있을까요..?

답글 달기
comment-user-thumbnail
2023년 12월 14일

EnableJpaRepositories는 언제 호출되는건가요?

답글 달기