스프링을 공부하면서 의존성 주입(DI), 제어의 역전(IoC)과 같은 용어들을 자주 들을 수 있는데
실제 이를 적용하는 과정에서 정확한 의미를 알지 못하고 단순 구현에만 집중했었기 때문에
정확한 이해를 위해 두 용어를 정리하려 한다.
우선 두 가지 용어에 대해 자세히 정리하기 전 DI와 IoC의 필요성에 대해 아래 코드와 함께 설명하겠다.
A 클래스에서 B 클래스의 메서드를 사용하기 위해 사용자가 직접 객체 인스턴스를 생성하는 경우
public class A {
public static void main(String args[]) {
B b = new B();
b.start();
}
}
class B {
public void start() {
System.out.println("Hello Java");
}
}
위와 같이 new 생성자를 통해 인스턴스를 생성하면 A 클래스에서 B 클래스 내 구현된 모든 메서드를 사용할 수 있다.
그런데 A 클래스 내에서 사용되고 있는 B 클래스의 start 메서드 명이 startJava와 같이 바뀐다면 어떻게 될까?
사용자는 A 클래스에서 사용하고 있는 start 메서드명을 바뀐 B 클래스의 메서드명과 같이 변경해야 할 것이고
A 클래스뿐만 아니라 C 클래스, D클래스에서도 start 메서드를 사용하고 있다면 변경된 메서드와 같이 모든 메서드명
을 변경해야 할 것이다. 이런 식으로 사용자가 직접 객체를 호출하게 되면 객체 간의 의존성이 높아져 결합도가 높아지고
코드의 유연성이 낮아진다. 따라서 반대로 객체를 직접 호출하는 것이 아닌 외부에서 생성한 후 사용해야 하는데 의존성
주입을 통해 외부에서 객체를 생성하고 의존성을 주입함으로써 호출하는 객체 입장에서는 직접적으로 객체를 생성하거나
관리할 필요가 없어져 로직 구현에만 집중할 수 있다.
의존성 주입의 방법
A 객체에서 B 객체를 사용하고 싶을 때 앞서 설명한 바와 같이 직접 생성하는 것이 아닌 외부(IoC 컨테이너)에서
생성된 객체들을 조립 후 setter 메서드 또는 생성자를 통해 의존성을 주입할 수 있다. IoC 컨테이너를 생성하기
위해서는 AppConfig와 같은 설정 파일을 생성하여 객체에 대한 책임을 가진 별도의 설정 클래스를 생성한다.
아래 예시 코드의 클래스를 살펴보면 총 3개의 인터페이스(MemberService, OrderService, DiscountPolicy)와
3개의 구현 클래스(MemberServiceImpl, OrderServiceImpl, FixDiscountPolicy)가 있다.
사용자가 직접 인터페이스의 구현 객체를 호출하기 위해서는 클라이언트 코드 내에서 new 생성자를 통해
인스턴스를 생성했다면 AppConfig 파일에서는 이와 반대로 인터페이스에 정의되어 있는 메서드의 생성자를
통해 각 구현 객체를 반환함으로써 객체 간 의존성을 주입한다. 뿐만 아니라 반환되는 구현 객체 내 파라미터값
으로 또 다른 객체의 인스턴스도 가져올 수 있다.
@Configuration
public class AppConfig {
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
IoC 컨테이너를 통한 의존성 주입의 장점
구현 객체가 프로그램의 제어 흐름을 조종하기 때문에 각각의 객체는 자신의 로직만 실행할 수 있다.
또한 실질적으로 의존성 주입 후 호출하는 객체는 인터페이스이기 때문에 인터페이스와 구현 객체를
분리함으로써 DIP(의존 역전 원칙)을 지킬 수 있다.
Reference
- https://isoomni.tistory.com/entry/TISPRING-IOC-DI-%EC%A0%95%EC%9D%98-%EC%9E%A5%EC%A0%90
- https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard
- https://www.youtube.com/watch?v=nOHdunGzeRc
'study > spring boot' 카테고리의 다른 글
[spring boot] Jsp 적용 과정 (패키징 배포 방식 JAR에서 WAR로 변경) (0) | 2023.04.21 |
---|---|
스프링 @RestController를 통한 json 데이터 반환 (0) | 2023.04.12 |
[spring boot] 싱글톤 컨테이너(singleton container)의 기능 (0) | 2023.02.12 |
[spring boot] Port was already in use 오류 해결 방법 (0) | 2023.01.05 |
[spring boot] WebMvcCofigurer - 정적 리소스(static resource) 설정 (0) | 2022.10.04 |
댓글