1. 제어의 역전 (IoC, Inversion of Control)
객체의 생성과 주입을 Spring이 대신 담당하는 개념
- 객체가 필요할때 개발자가 직접 생성(
new)로 생성하여 사용할것인가?
- 아니면 어떤 주체가, 객체가 필요할때 객체를 대신 생성하여 필요한곳에 주입해줄것인가?
기존 방식 vs IoC 방식
| 기존 방식 (개발자가 직접 객체 생성) | IoC 방식 (Spring이 객체 생성 & 주입) |
|---|
개발자가 new 키워드로 직접 객체 생성 | Spring이 대신 객체를 생성하고 주입 |
| 객체 관리가 어려움 | 객체 관리를 Spring이 자동으로 수행 |
| 테스트 시 Mock 주입이 어려움 | 테스트 시 Mock 객체 주입 가능 |
2. IoC 5가지 구현 방법
| IoC 구현 방법 | 설명 |
|---|
| Template Pattern | 상속을 통해 일부 로직을 미리 구현 |
| Delegate (위임) | 실행을 다른 객체에 위임 |
| Event | 이벤트를 발생시키고 리스너가 처리 |
| Service Locator | 개발자가 직접 Locator에서 Bean을 가져와 사용 |
| DI (Dependency Injection) | Spring이 Bean을 대신 주입 (Spring이 사용하는 방식!) |
3. Service Locator vs DI 비교
Service Locator (개발자가 직접 Bean 가져옴) - 예전방식
public class UserController {
private final UserService userService;
public UserController() {
this.userService = ServiceLocator.getUserService();
}
}
- 의존성 파악 불가능
- 테스트 시 Mock 주입 어려움
DI (Spring이 Bean 주입)
@Service
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
}
- Spring이 생성자 주입을 통해 객체를 주입
- 의존성 파악 가능
- 테스트 시 Mock 주입 가능
4. Spring Bean 관리
Bean이란?
Spring이 관리하는 객체 (싱글톤으로 관리됨)
Bean 등록 방법
| 방법 | 설명 |
|---|
| @ComponentScan + @Component | 특정 패키지 내 자동 Bean 등록 |
| @Controller, @Service, @Repository | Spring이 자동으로 Bean 등록 |
| @Configuration + @Bean | 직접 Bean을 등록 |
Bean 사용 방법
| Bean 사용 방식 | 설명 |
|---|
| 구체 클래스 사용 | UserService userService 직접 사용 |
| 부모 클래스 사용 | ServiceInterface userService 인터페이스 활용 |
| Collection 사용 | 여러 개의 Bean을 리스트로 주입 |
5. Spring Bean 주입 방법 (DI)
1. 생성자 주입 (Spring 공식 추천)
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
}
- 순환 참조 방지 가능
- Bean 불변성 (final 필드 사용 가능)
- 테스트 시 Mock 주입 용이
2. 필드 주입 (권장 X)
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
- 테스트 시 Mock 객체 주입 어려움
- 순환 참조 문제 발생 가능
3. 수정자 주입 (Setter Injection)
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
- 필요한 경우만 의존성 변경 가능
- 객체가 불변하지 않음 (final 사용 불가)