IoC(제어의 역전)
일반적인 자바 개발의 경우 객체를 사용하기 위해 아래와 같은 코드를 사용합니다.
@RestController
public class MemoController {
private MemoService service = new MemoService();
@GetMapping("/memos")
public String getMemo() {
return service.getMemo();
}
}
사용하려는 객체를 선언하고 해당 객체의 의존성을 생성한 후 객체에서 제공하는 기능을 사용합니다. 객체를 생성하고 사용하는 일련의 작업을 개발자가 직접 제어하는 구조 입니다.
하지만, 제어 역전(Inversion of Control)을 특징으로 하는 스프링은 기존 자바 개발 방식과 다르게 동작 합니다. IoC를 적용한 환경에서는 사용할 객체를 직접 생성하지 않고 객체의 생명주기 관리를 외부에 위임합니다. 여기서 '외부'는 스프링 컨테이너(Spring Container) 또는 IoC 컨테이너(IoC Container)를 의미합니다. 객체의 관리를 컨테이너에 맡겨 제어권이 넘어간 것을 제어 역전이라고 부르며, 제어 역전을 통해 의존성 주입(DI), 관점 지향 프로그래밍(AOP) 등이 가능해집니다.
DI(의존성 주입)
의존성 주입(Dependency Injection)이란 제어 역전의 방법 중 하나로, 사용할 객체를 직접 생성하지 않고 외부 컨테이너가 생성한 객체를 주입받아 사용하는 방식을 의미합니다.
스프링에서 의존성을 주입받는 방법은 3가지가 있습니다.
- 생성자를 통한 주입
- 필드 객체 선언을 통한 의존성 주입
- setter 메서드를 통한 의존성 주입
스프링에서는 @Autowired 라는 어노테이션을 통해 의존성을 주입할 수 있습니다. 단, Spring IoC 컨테이너에 의해 관리되는 클래스에서만 가능합니다.
@Autowired는 다음의 경우에서는 생략 가능합니다.
- Spring 4.3 버전부터 @Autowired 생략 가능
- 단, 생성자 선언이 1개일 때만 생략 가능
- @RequiredArgsConstructor 사용 가능
1) 생성자를 통한 의존성 주입
@RestController
public class MemoController {
private final MemoService memoService;
@Autowired
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
}
2) 필드를 통한 의존성 주입
@RestController
public class MemoController {
@Autowired
private MemoService memoService;
}
3) setter 메소드를 통한 의존성 주입
@RestController
public class MemoController {
private MemoService memoService;
@Autowired
public void setMemoService(MemoService memoService) {
this.memoService = memoService;
}
}
스프링 공식 문서에서 권장하는 의존성 주입 방법은 생성자를 통해 의존성을 주입받는 방식입니다. 그 이유는 객체의 불변성을 보장하기 때문입니다.
IoC Container와 Bean
DI를 사용하기 위해서는 객체 생성이 우선되어야 합니다. Spring에서는 Spring 프레임워크가 필요한 객체를 생성하고 관리하는 역할을 대신 해줍니다.
- 빈(Bean) : Spring이 관리하는 객체
- Spring IoC 컨테이너 : Bean을 모아둔 컨테이너
1) Spring Bean 등록 방법
- @Component 계열 어노테이션
@Component
public class MyComponent {
public void doSomething() {
System.out.println("Hello from MyComponent");
}
}
Spring 이 실행될 때 Bean 객체를 생성하여 가지고 있다가 의존성 주입이 필요할 때 주입해 줍니다.
@Component : 기본 어노테이션
@ComponentScan : @ComponentScan에 설정해 준 packages 위치와 하위 packages들을 전부 확인하여 @Component가 설정된 클래스들을 Bean으로 등록해줍니다.
@Configuration
@ComponentScan(basePackages = "com.nuri.memo")
class BeanConfig {...}
@Service, @Repository, @Controller, @RestController : @Component를 확장한 스테레오타입 어노테이션으로, 특정 역할을 가진 Bean을 등록할 때 사용
- Java Config 기반 등록
Java Config 방식으로 @Configuration과 @Bean을 사용하여 Bean을 등록합니다.
@Configuration
public class AppConfig {
@Bean
public MyComponent myComponent() {
return new MyComponent();
}
}
2) Spring Bean 사용 방법
- @Autowired 사용
- ApplicationContext
@Component
public class MemoService {
private final MemoRepository memoRepository;
public MemoService(ApplicationContext context) {
// 1. Bean 이름으로 가져오기(방법1)
MemoRepository memoRepository = (MemoRepository) context.getBean("memoRepository");
// 2. Bean 클래스 형식으로 가져오기(방법2)
MemoRepository memoRepository = context.getBean(MemoRepository.class);
this.memoRepository = memoRepository;
}
}
ApplicationContext는 BeanFactory 등을 상속하여 기능을 확장한 Container 입니다. BeanFactory는 'Bean'의 생성, 관계설정 등의 제어를 담당하는 IoC 객체 입니다.
'Spring' 카테고리의 다른 글
[Spring] SpringSecurity 403에러 해결 (0) | 2024.11.20 |
---|---|
[Spring] JPA(Java Persistent API) (0) | 2024.11.17 |
[Spring] 생성(Creational) 패턴 - 추상 팩토리 (0) | 2024.11.13 |
[Spring] SpringSecurity - JWT (0) | 2024.11.11 |
[Spring] JWT(Json Web Token) (0) | 2024.11.11 |