IoC, DI, AOP
스프링의 핵심원리는 여러 가지 기술을 이용하여 복잡한 요소들을 스프링 프레임워크에 위임하고, 개발자는 비즈니스 로직 개발에만 집중할 수 있게 된다. 그중 가장 유명한 것은 IoC(제어의 역전), DI(의존성 주입), AOP(관점 지향 프로그래밍) 이 있다.
Bean
Bean은 컴포넌트 스캔(자동 등록 @Component) 및 수동으로 등록(@Configuration 에 직접 빈 등록)할 수 있는, Spring IoC 컨테이너가 관리하는 객체들을 말한다.
Spring이 ApplicaionContext를 띄우면 Bean으로 등록된 클래스들을 스캔하고, 빈 객체들을 직접 new 해서 메모리에 올린다.
그 이후로, 의존성 주입(DI)까지 완료하고, 초기화 작업(PostConstruct)까지 완료한다.
Bean Lifecycle (빈의 생명주기)
생성 → 주입 → 초기화 → 사용 → 소멸
생성 | Spring이 new로 객체 생성 |
의존성 주입 | 필요한 다른 Bean들을 주입 |
초기화 | @PostConstruct, InitializingBean.afterPropertiesSet() 호출 |
사용 | 실제 애플리케이션에서 사용 |
소멸 | @PreDestroy, DisposableBean.destroy() 호출 |
IoC, Inversion of Control 이란,
사용할 객체를 개발자가 직접 생성하지 않고, 객체의 생명주기를 외부(스프링 컨테이너)에게 위임하는 것을 말한다.
이때 객체의 관리를 맡기는 스프링 컨테이너를 `Spring Container` 또는 `IoC Container` 라고 한다.
이런 제어의 역전을 통해서 DI 와 AOP 가 가능해진다.
DI, Dependency Injection 이란,
`의존성을 주입한다` 는 것은 제어의 역전(IoC)의 방법 중에 하나로, 사용할 객체를 직접 생성하지 않고 외부 컨테이너가 생성한 객체를 주입받아 사용하는 것을 말한다.
따라서 스프링에서는 직접 객체를 제어하지 않고 제어권을 스프링에게로 넘긴다.
의존성을 주입하는 방법에는 세가지가 있다.
- 생성자를 통한 의존성 주입
- 필드 객체 선언을 통한 의존성 주입
- setter를 통한 의존성 주입
그러나 가장 좋은 의존성 주입 방식으로 추천되는 것은 `생성자를 통한 의존성 주입` 방식이다.
@Autowired 나 final 이 붙은 필드 생성자를 추적하는 @RequiredArgsConstructor 를 사용하면 편리하다.
(참고로 @Autowired 는 어노테이션이고, @RequiredArgsConstructor 는 Lombok 라이브러리에서 제공한다.)
AOP, Aspect-Oriented Programming 이란,
관점 지향 프로그래밍은 관점을 기준으로 묶어서 프로그래밍 하는 방식을 말한다.
어떤 기능을 볼때, 그 기능의 핵심인
비즈니스 로직(핵심 관심사(Core Concern))과
부가 로직(횡단 관심사(Cross-cutting Concern))을
구분해서 보는 것이다.
바로 AOP가 해주는 것이 패키지별로 클래스별로 공통된 부가 로직을 부여할 수 있다는 것이다.
부가 로직이라 함은, 로깅이나 트랜잭션 처리, 권한 체크 등을 말한다.
프록시의 문제점
AOP가 스프링에서 프록시처럼 앞뒤로 감싸서 동작을하는데,
프록시 객체는 외부에서 메서드 호출할 때만 가로챌 수 있다.
내부 메서드 호출은 가로채지 못한다!
@Component
public class MyService {
@Transactional
public void outer() {
inner(); // 내부 메서드 호출
}
@Transactional
public void inner() {
// 트랜잭션이 적용돼야 함
}
}
- 여기서 outer()는 프록시를 통해 가로채지만,
- inner()는 프록시를 거치지 않고 직접 호출되기 때문에 AOP 적용이 안 된다!
Spring AOP vs AspectJ
Spring AOP | 프록시 기반, 런타임에 메서드 호출을 가로챔 |
AspectJ | 바이트코드 조작 기반, 컴파일/클래스 로딩 시점에 코드에 AOP 삽입 |
JDK Proxy vs CGLIB
JDK Proxy | 인터페이스 기반 동적 프록시 |
CGLIB | 구체 클래스 기반 상속 프록시 |
Spring AOP는 프록시 기반으로 런타임에 부가기능을 삽입한다.
인터페이스가 있으면 JDK Proxy, 구체 클래스만 있으면 CGLIB을 사용해서 프록시를 생성한다.
AspectJ는 컴파일/클래스 로딩 시점에 코드 자체를 수정하는 방식이라,
더 강력하지만 세팅이 복잡해서 실무에서는 주로 Spring AOP를 사용한다.
'Framework > Spring' 카테고리의 다른 글
[SpringSecurity6.1] requestMatchers에서 오류가 나기 시작했다 (0) | 2025.04.05 |
---|---|
[SAML 2.0] IdP 와 SP 인증을 직접 구현해보자. (3) - SP 설정 : React편 (0) | 2025.01.30 |
[Spring MVC] WebMvcConfigurer로 cross-origin 설정을 해도 cors 오류가 나는 이유 (304 응답에서) (0) | 2025.01.30 |
[SAML 2.0] `SP-Initiated SSO 방식` vs `IdP-Initiated SSO 방식` (0) | 2025.01.29 |
[Servlet] ServletRegistrationBean : Spring 이 Servlet 을 다루는 방법 (0) | 2025.01.07 |