Post

MongoRepository에 @Repository가 없어도 빈 등록이 되는 이유


인턴십을 하면서 코드 리뷰를 하며 남의 코드를 유심히 들여다 보는 것도 큰 성장임을 알게 되었다. 사이드 프로젝트를 할 때도 남의 코드를 자세히 보고 이유있는 수정을 요구하려고 노력 중이다! 그 첫번째 경험을 하게 되어 공유한다.

@Autowired의 지속적인 등장

아래의 코드가 UserChallengeService, PublicChallengeService, ChecklistService, ReactionService에 계속해서 등장하고 있었는데, @Autowired를 반복할 필요가 없다고 생각해서, 삭제를 요청했다.

1
2
    @Autowired
    private ChallengeRepository challengeRepository;

이번 사이드 프로젝트에서는 뭐든지 “이유있는” 행동을 하고싶었다. 삭제해달라고 요청했을 때 왜? 라는 질문을 받는다면 과연 나는 잘 대답할 수 있을까? 생각해보았는데 대답은 No 였다. ✅ 이제부터 @Autowired를 repository 선언마다 사용할 필요가 없는 이유에 대해 알아보자!


MongoRepository의 빈 등록

1
public interface ChallengeRepository extends MongoRepository<Challenge, UUID>

이렇게 ChallengeRepositoryMongoRepository를 상속받는다.

MongoRepository@NoRepositoryBean이고 ListCrudRepository<T, ID>, ListPagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>를 받는다.

그리고 이들 각각도, 전부 @NoRepositoryBean으로 등록되어 있다.


@NoRepositoryBean

레포지토리 코드들을 아무리 타고타고 들어가서 확인해봐도, 정확히 @Bean으로 등록하는 부분이 없어서 이상하게 생각하고 있었다! @NoRepositoryBean이 굉장히 수상해서 찾아보게 되었다.

Annotation Interface NoRepositoryBean

In this case you typically derive your concrete repository interfaces from the intermediate one but don’t want to create a Spring bean for the intermediate interface.

✅ 즉, 중간에 위치한 기본 인터페이스는 빈으로 생성되지 않고, 이를 상속하는 하위 리포지토리들만 빈으로 등록될 수 있도록 하는 어노테이션이었다! 실제로 애플리케이션 실행 시점에 스프링이 생성하는 빈들을 확인해보면, ChallengeRepository와 관련해서 아래 두 개를 생성하는 것을 확인할 수 있었다.

  • challengeRepository : @Autowired에 의해 생성되는 빈, 여러 번 코드에 등장하지만 실제로는 하나의 인스턴스만 생성하고 이후에 등장할 때 빈 목록에서 challengeRepository를 찾아 재사용한다

  • mongodb.ChallengeRepository.fragments#0 : @NoRepositoryBean에 의해서 MongoRepository를 상속하는 가장 하위 리포지토리인 ChallengeRepository를 빈으로 등록한 것

✅ 이러한 이유와 함께 코드 리뷰를 하니, 리뷰 받는 분도 납득하고 코드를 수정할 수 있었고, 나도 @NoRepositoryBean의 역할에 대해 정확히 알아갈 수 있었다.

Untitled


애플리케이션 생성 시점에 등록된 빈 목록 확인하는 코드

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {

    ConfigurableApplicationContext context = SpringApplication.run(BeApplication.class, args);
    String[] beanNames = context.getBeanDefinitionNames();
    Arrays.sort(beanNames);
    for (String beanName : beanNames) {
        System.out.println(beanName);
    }
}



This post is licensed under CC BY 4.0 by the author.