스프링 빈과 의존 관계
이번 포스트에서는 스프링 부트에서 빈(@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?
- 유연한 구조가 가능
- 직접 new로 만들면, 나중에 바꾸고 싶은 게 생겼을 때 코드 수정이 필요하다.
- 의존성 주입을 통해 외부에서 어떤 구현체를 넣을지 결정이 가능하게 되면 유연하고 테스트하기에 좋다.
- 인터페이스에 의존하고, 구현체는 나중에 주입
- 테스트 하기가 쉬워진다.
- 테스트에서는 Mock 객체 (가짜 객체)를 넣어서 독립적인 테스트가 가능하다.
- 의존 객체가 내부에서 생성되면 테스트가 어려워진다.
- 스프링이 대신 관리해주기 때문이다.
- 스프링은 우리가 직접 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 주입 | 선택적 주입 시 사용, 유연하나 노출됨 |