99클럽 9일차 TIL: Bean 관련 에러

2024. 4. 12. 17:3899클럽/TIL

728x90
반응형

#1. 오늘의 학습 키워드

자바스프링부트에서의 아래 오류 해결 과정:

Description:

Parameter 1 of constructor in ~~ required a bean of type 'xx' that could not be found.

Action:

Consider defining a bean of type 'xx' in your configuration.

  • Loki 서버로 API 호출하는 Util 클래스를 만들고 배포하였을 때, 발생된 오류.
    • 컴파일 타임 및 기본 로컬 Profile 환경에서는 검출이 안 된 오류.
  • 오류의 의미는 LokiUtil 클래스가 bean 으로 등록되지 않았다는 것이다.
    • LokiUtil을 다른 곳에서 객체를 선언하고 사용하고 있었던 상황
  • 그런데 사실 LokiUtil 클래스는 @Component 어노테이션으로 빈 등록이 되어있는 상황이었고,
    • 클래스 내부 멤버 변수 (필드)들은 @Autowired 나, @Value 어노테이션으로 의존성 주입 및 환경변수 값이 주입 되어있는 상황이어서 컴파일 타임 및, 로컬 환경 런타임에는 문제가 없었다.
  • 결국 환경에 따라서 LokiUtil 클래스가 bean으로 등록 되거나 등록 되지 않는다는 것이고, 이는 곧 @Profile 어노테이션 때문임을 알게 되었다.
    • Test 환경에서는 Loki를 사용하지 않아도 되게끔 LokiUtil 클래스 상단에 아래와 같이 어노테이션을 달아줬고, 해당 환경의 config 파일에 별도의 LokiUtil 관련 설정을 하지 않았으니 오류가 발생했던 것이다.

#2. 공부한 내용

  • Bean 등록
    • Bean
      • 객체의 생성, 소멸 등 담당하는 스프링 컨테이너가 존재하며, 이 컨테이너에 의해 생성된 객체를 Bean 이라고 부른다.
      • 스프링 컨테이너에 의해 관리되는 점 이외는 일반 객체와 큰 차이는 없다.
    • 스프링 부트에서는 아래와 같은 어노테이션으로 빈 등록을 할 수 있다. 어노테이션으로 등록된 클래스들은 스프링 컨테이너에 의해 자동 객체 생성이 되며 스프링 빈으로 등록된다.
      • @Bean
      • @Component
      • @Service
      • @Controller
      • @Repository
      • @Configuration
    • 클래스 선언부 위에 해당 어노테이션들을 붙인다.
  • @Autowired
    • 의존성 주입하는 방법 중 하나
      • 스프링 빈 객체를 특정 참조 변수에 매핑해줌으로써 의존성을 주입
    • 아래의 3가지 경우에 @Autowired 를 붙여서 의존성을 주입할 수 있다.
      • 생성자
        • 생성자 메서드에 의존성 주입을 받고자하는 field를 나열하는 방법.
      • setter
        • 의존성이 선택적으로 필요한 경우 사용
        • 생성자에 모든 의존성을 주입하는 것에 부담을 조금 덜어줄 수 있음
      • 필드
        • 간단함
        • 의존성이 눈에 띄지 않고, 단일 책임 원칙(SRP) 에 반하는 안티패턴
    • @Autowired(required=false)
      • @Autowired의 기본값은 true라서 의존성 주입할 대상을 IoC 컨테이너 속 등록된 빈에서 찾지 못 한다면 어플리케이션 구동에 실패한다.
      • 그러나 만약 위처럼 실행하면, 주입할 대상이 빈으로 등록되어있지 않더라도, 그 클래스 자체는 빈으로 등록이 가능하다.
  • Mockito.mock()
    • Mockito는 모의 객체를 생성하고 관리하는 데 사용되는 자바 오픈소스 프레임워크다.
      • 실제 사용되는 객체 생성을 대체하기 위해 테스트에 사용되는 모의 객체를 생성한다.
  • 참조:

#3. 오늘의 회고

  • 위에서 공부한 내용과 @Profile 어노테이션을 결합하여 생각하면 오류 원인은 다음과 같다.
    • 해당 오류는 LokiUtil 클래스를 Bean으로 등록하려할 때, @Profile(”!test”) 어노테이션에 의해 test 환경에서는 LokiUtil 클래스가 Bean으로 등록되지 않았다.
    • 그리고 LokiUtil 객체를 필드에 매핑하고자 하는 다른 클래스에서 @Autowired 어노테이션을 사용하여 의존성 주입을 하려할 때, 스프링 컨테이너에 해당 빈이 없기에 어플리케이션 구동이 실패했던 것이다.
    • 따라서 Test 환경의 Configuration 클래스에서 Mockito.mock() 메서드를 통해 LokiUtil의 클래스의 모의 객체를 생성한 후 빈으로 등록해주면 오류가 나지 않는다.
      • 스스로의 문제 해결 방법은 LokiUtil에서 @Profile 어노테이션을 제거하였다.
  • @Bean 과 @Autowired는 의존성 주입을 위한 핵심 어노테이션이고, 이를 통해 개발자는 객체 간 의존성을 유지하며 코드의 유연성과 재사용성을 높일 수 있다.
    • 즉 이미 다른 어딘가의 클래스에서의 코드를 가져다 쓰기 쉽게 해준다.
  • 스프링에서는 이러한 객체 간 의존성을 스프링 컨테이너가 관리를 해준다.
    • 개발 과정이 간소화 된다.
  • 이와 같은 스프링의 특징과 관련된 개념들은 초기에는 복잡하게 다가왔지만, 사실은 개발에 큰 도움을 주는 툴이며, 사용시에도 간편하다.
    • 적극적으로 활용을 하도록 하자.
728x90
반응형