본문 바로가기

Backend/Spring

[Spring] 스프링으로 변경 1) IoC, DI, 컨테이너

728x90

 

스프링에만 국한된 단어는아니다.

 

 

IoC (Conversion of Control)
제어의 역전

 

보통은 개발자가 원하는대로 객체를 생성 호출 , 호출한 객체 내에서 또 객체를 생성 호출 한다. (변경 이전의 코드를 떠올리자)

프레임워크 같은 것이 내 코드를 대신 호출해주면, 제어의 역전이 일어난 것(제어권이 뒤바뀜) 

지금 까지는 구현 객체가 스스로 필요한 객체를 생성하고 생성했다.

구현체가 프로그램의 제어 흐름을 스스로 조정했다(개발자 입장에서는 자연스러운 흐림)

 

반면에 AppConfig등장 이후, 

구현 객체는 자신의 로직을 실행하는 역할만을 담당하고(관심사의 분리)

프로그램의 제어 흐름은 이제 AppConfig가 가져가 담당한다.

 

예를들어 구현객체인 OrderServiceImpl은 필요한 인터페이스들을 호출하지만 어떤 구현객체들이 실행될지는 전혀 모른다. (자신이 의존하고있는, 필요한 구현객체를 스스로 생성/연결을 더이상 하지 않기때문)

즉, AppConfig가 OderService인터페이스(역할)의 구현체로 OrderServiceImpl이 아닌 다른 구현 객체를 생성하고, 실행하려고 할 수도 있다. 또는, OrderServiceImpl이 의존하고있는 memberRepository인터페이스(역할)을 다른 구현객체로 변경하여 실행할 수도 있다. 하지만, OrderServiceImpl은 이러한 사실도 모른체 자신이 해야하는 로직을 실행할 뿐이다.

 

 

*라이브러리 vs 프레임워크 

  • 프레임워크가 내가 작성한 코드를 제어하고, 대신 실행하면 그것은 프레임워크가 맞다. (JUnit)
    • 예 ) JUnit : JUnit으로 작성한 테스트 코드를 보자
    • 자신만의 라이프 사이클이 있으며, 내가 작성한 코드는 콜백형식처럼 불러진다. 
    •  
  • 반면에 내가 작성한 코드가 직접 제어의 흐름을 담당한다면 그것은 프레임워크가 아니라 라이브러리다.
    • ex ) xml to json 등등은 이런 기능을 하는 라이브러리를 호출하여 개발자가 직접 사용한다.

 

 

 

DI( Dependency Injection) 의존관계 주입

 

OrderServiceImpl  DiscountPolicy 인터페이스에 의존한다. 

실제 어떤 구현 객체가 사용될지는 모른다. (구현체에는 의존하지 않음)

public class OrderServiceImpl implements OrderService{


    private final MemberRepository memberRepository;// -> 오직 인터페이스만 존재 (추상화에만 의존함 DIP)
    private final DisountPolicy disountPolicy; //인터페이스 (추상)에만 의존함 (DIP)

의존관계는 

  • 정적인 클래스 의존 관계
  • 동적인 객체(인스턴스) 의존 관계 (실행 시점에 결정되는 동적인 의존관계)

둘을 분리해서 생각해야 한다.

 

 

정적인 클래스 의존관계

정적인 의존관계는 애플리케이션을 실행하지 않아도 분석 가능하다.

  • import 코드
  • 클래스 다이어그램

등을 보고 의존관계를 쉽게 파악할 수 있다.

 

 

import 코드

 

클래스 다이어그램 / 인텔리제이 내에서 자체 제공하는 방법도 있음! 

 

OrderServiceImpl  MemberRepository , DiscountPolicy 에 의존한다는 것을 알 수 있다.

그런데 이러한 클래스 의존관계 만으로는 실제 어떤 객체가 OrderServiceImpl 에 주입 될지 알 수 없다.

 

 

동적인 객체 인스턴스 의존관계

객체 다이어그램

 

 

애플리케이션 실행 시점(런타임)외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서, 클라이언트와 서버의 실제 의존관계가 연결 되는 것을 의존관계 주입(Dependency Injection)이라 한다.

객체 인스턴스를 생성하고, 그 참조값을 전달해서 연결된다.

의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고, 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다.

의존관계 주입을 사용하면 정적인 클래스 의존관계를 변경하지 않고(= 정적 클래스다이어그램에 있는 모든 클래스의 코드를 변경하지 않고), 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있다.

 

 

 

DI 컨테이너

 

IoC를 해주는 컨테이너, DI를 해주는 컨테이너!

AppConfig 처럼 객체를 생성하고, 관리하면서, 의존관계를 연결해주는 것

의존 관계 주입에 초점을 맞추어 최근에는 DI컨테이너라고 더 많이 사용(어샘블러, 오브젝트 팩토리 등)

(IoC는 조금 범용적인 느낌이 있음)

 

Spring은 DI컨테이너 역할을 제공한다. (물론 다른 오픈소스들도 많이 존재함)

즉, 우리가 괜히 AppConfig를 만들어서 하지 않아도된다는 뜻 

이제 다음 게시글에서는 순수 자바로 구현했던 DI컨테이너를 스프링의 도움을 받는 것으로 변경해보자.

728x90