1 분 소요

이번 포스트에서는 스프링 부트에서 빈(@Bean)과 의존 관계 주입(DI, Dependency Injection)의 핵심 개념에 대해 간단히 다룬다.

스프링 빈

스프링 빈 이란 스프링이 관리하는 객체를 말한다.

  • 우리가 직접 만든 클래스들 (Controller, Service, Repository 등)을 스프링 컨테이너가 자동 생성해서 관리해주는 개념이다.
  • 이렇게 등록한 객체는 필요한 곳에 자동으로 주입할 수 있다.

  • 예시

    @Controller
    public class MemberController {
      
        private final MemberService memberService;
      
        @Autowired
        public MemberController(MemberService memberService) {
            this.memberService = memberService;
        }
    }
    
    • @Controller : 이 클래스를 스프링이 자동으로 스프링 빈으로 등록한다.
    • @Autowired : MemberService를 스프링 컨테이너에서 찾아와 자동으로 주입한다.
    • 이런 방식이 바로 DI (Dependency Injection) 라고 한다.

    즉, “필요한 객체는 내가 new로 만들지 않고, 스프링이 자동으로 넣어준다는 개념이다.”

왜 의존성 주입을 해야할까?

의존성 주입 : 어떤 객체가 필요로 하는 개체를 직접 만들지 않고, 외부에서 넣어주는 것을 말한다.

Why?

  1. 유연한 구조가 가능
    • 직접 new로 만들면, 나중에 바꾸고 싶은 게 생겼을 때 코드 수정이 필요하다.
    • 의존성 주입을 통해 외부에서 어떤 구현체를 넣을지 결정이 가능하게 되면 유연하고 테스트하기에 좋다.
      • 인터페이스에 의존하고, 구현체는 나중에 주입
  2. 테스트 하기가 쉬워진다.
    • 테스트에서는 Mock 객체 (가짜 객체)를 넣어서 독립적인 테스트가 가능하다.
    • 의존 객체가 내부에서 생성되면 테스트가 어려워진다.
  3. 스프링이 대신 관리해주기 때문이다.
    • 스프링은 우리가 직접 new를 해주지 않아도
    • @Autowired, @Service, @Repository 등으로 객체를 스프링 컨테이너가 자동 생성하고 관리한다.
    • 구조를 활용하기 위해 스프링이 의존관계를 알아야한다.
      • 그래서 의존성은 외부에서 주입되어야 함.

컴포넌트 스캔 원리

스프링은 @Component가 붙은 클래스를 자동으로 스캔해서 빈으로 등록한다.

  • 컴포넌트의 특수한 형태 (자주 쓰이는 것들)
애노테이션 역할
@Controller 웹 컨트롤러로 사용됨
@Service 서비스 계층 등록
@Repository DAO/리포지토리 계층 등록

스프링 빈 등록 방법 2번째 : 수동 등록

먼저 코드의 예시를 보겠다.

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}
  • @Configuration : 설정 클래스로 선언
  • @Bean : 이 메서드가 리턴하는 객체를 스프링 빈으로 등록
    • 컴포넌트 스캔 대신에 수동으로 빈을 등록하는 방법

이러한 방식은 빈 교체나 구현체 변경이 필요할 때 유용하다.

  • 예시 ) 메모리 구현에서 DB 구현으로 교체

DI 의 종류

방식 특징
생성자 주입 가장 권장됨. final 키워드 사용 가능
필드 주입 테스트 어렵고 변경 불가 (권장 X)
Setter 주입 선택적 주입 시 사용, 유연하나 노출됨