IOC (제어의 역전)란?
💡 IOC (Inversion of Control) 의 약자로 제어의 역전이라는 의미를 갖는다.
이는 객체의 생성부터 소멸까지 생명 주기의 관리를 개발자가 아닌, 외부에서 관리하는 것을 의미한다.
즉, 객체를 필요할 때 미리 생성해 놓고 꺼내서 사용하는 방식이다.
스프링(spring)에서는 다음과 같은 순서로 객체가 만들어지고 실행된다.
➡️ 객체 생성
➡️ 의존성 객체 주입 (Spring이 객체를 생성 후 주입)
➡️ 의존성 객체 호출
즉, Spring이 모든 의존성 객체를 생성해주고 주입해줌으로써,
Bean들은 싱글톤 패턴의 특징을 가지며,
제어의 흐름을 Spring이 작업하게 된다.
DI (의존성 주입)란?
💡 DI (Dependency Injection) 의 약자로
각 클래스간의 의존성을 개발자가 아닌, 외부 (컨테이너)에서 주입하는 개념이다.
즉, 객체를 직접 생성하는게 아닌, 외부에서 생성한 후 주입 시켜주는 방식이다.
DI (의존성 주입)를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.
의존 관계 주입에는 크게 4가지 방법이 있는데 예제소스로 알아보려한다.
➡️ @Component로 Bean에 등록 된 객체
@Component
@Getter @Setter
public class InjectionExample {
private String name;
private String address;
}
➡️ Setter Injection (수정자 주입)
💡 클래스의 Setter를 통해서 의존성을 주입해주는 방식이다.
변경 가능성이 있는 객체에 사용하며, @Autowired 어노테이션을 주입 할 필드 위에 명시한다.
@Component
public class InjectionExampleMain {
// 1. Setter Injection
private InjectionExample injectionExample;
@Autowired
public void setInjectionExample(InjectionExample injectionExample) {
this.injectionExample = injectionExample;
}
}
➡️ Field Injection (필드 주입)
💡 클래스에 선언된 필드에 생성된 객체를 주입해주는 방식이다.
스프링에서 제공하는 @Autowired 어노테이션을 주입 할 필드 위에 명시한다.
@Component
public class InjectionExampleMain {
// 2. Field Injection
@Autowired
private InjectionExample injectionExample;
}
➡️ Constructor Injection (생성자 주입)
💡 클래스의 생성자를 통해서 의존성을 주입하는 방식이다.
인스턴스가 생성 될 때, 1회 호출되는것이 보장된다.
필드에 final 키워드를 사용할 수 있다.
@Component
public class InjectionExampleMain {
// 3. Constructor Injection
private final InjectionExample injectionExample;
public InjectionExampleMain(InjectionExample injectionExample) {
this.injectionExample = injectionExample;
}
}
➡️ Method Injection (메서드 주입)
⚠️ 일반적으로 사용하지 않는다.
💡 일반 메서드를 통해서 의존성을 주입하는 방법이다.
@Autowired 어노테이션을 모든 메서드에서 사용이 가능하다.
@Component
public class InjectionExampleMain {
// 4. Method Injection
private InjectionExample injectionExample;
@Autowired
public void method(InjectionExample injectionExample) {
this.injectionExample = injectionExample;
}
}
아래와 같이 @RequiredArgsConstructor Lombok 라이브러리를 사용하여 더 간편하게 작성이 가능하다.
final 객체만 생성자를 포함시킨다.
@Component
@RequiredArgsConstructor
public class InjectionExampleMain {
// 3. Constructor Injection
private final InjectionExample injectionExample;
}
👌 과연 어떤 주입 방식이 좋을까?
Spring에서는 Constructor Injection (생성자 주입) 방식을 권장한다.
➡️ 객체의 불변성 (immutable)
객체가 생성되는 시점에 생성자를 호출하여 최초 1회만 주입한다.
위와 같은 특성으로 불변 객체를 보장한다.
➡️ final 키워드 사용 가능
필드에 final 키워드를 사용할 수 있다.
따라서 생성자에 값이 설정되어 있지 않다면, 컴파일 시점에서 오류가 발생한다.
➡️ 순환 참조 방지
여러 컴포넌트 간 서로 의존성이 발생할 시
필드 주입과, 수정자 주입은 빈이 생성된 후에 참조를 하기 때문에,
Application이 오류 없이 구동된다. 따라서 실제 호출이 되기전까지 문제를 알 수 없다.
하지만, 생성자를 통해 의존관계를 주입하면 Exception이 발생하게되어 문제를 알 수 있다.
DL (의존성 검색)란?
💡 DL (Dependency Lookup) 의 약자로
의존관계가 필요한 객체에서 직접 검색하는 방식이다.
의존관계는 외부 컨테이너에서 관리해서,
이를 가져올 때 스스로 컨테이너에게 요청하는 방법으로 가져온다.
일반적으로 사용되는 방법이다.
@Component
public class InjectionExampleMain {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
private InjectionExample injectionExample;
public InjectionExampleMain() { //생성자
this.injectionExample = ac.getBean(InjectionExample.class);
}
}
OUTRO
오늘은 Spring Framework의 핵심 기술들을 알아봤습니다.
위 개념들의 기본을 잘 잡아야 실력있는 개발자로 성장할 수 있습니다!
그러면 다음 포스팅에서 뵙겠습니다.
'Back-End > Spring' 카테고리의 다른 글
[Spring] 스프링 빈 (Spring Bean) 이란? (0) | 2024.04.09 |
---|---|
[Spring Boot] 스프링 부트 기초와 개념 (0) | 2024.03.28 |