Spring 핵심 원리 기본편 (3) - SOLID 관점에서 바라 본 DI / DI, IoC, DI 컨테이너

김정욱·2021년 2월 15일
0
post-thumbnail

소개

  • 이번 글은 순수 Java를 활용한 코드임 (Spring사용 X)
  • DI와 DI컨테이너가 어떤 역할을 할 수 있는지가 핵심
  • 회원이 주문을 하는 간단한 예제로 코드를 변경할 예정
  • SOLID 5가지 관점에서 DI의 적용 전/후를 비교해서 보는것이 중요

비즈니스 요구사항

  • member의 회원가입 / 조회
  • memberBASIC / VIP 등급이 존재
  • member는 상품을 주문할 수 있음
  • DB는 아직 미정 상태
    • 자체 DB
    • JDBC
    • 외부 시스템과 연동
  • VIP member는 상품 할인이 적용 (할인 방식 미정)
    • 고정(Fix) 금액 할인
    • 일정(Rate) 비율 할인

다이어 그램

[ member ]

  • 주의할 점은 DB가 아직 정해지지 않은 상황이다
  • MemberRepository는 단순 메모리를 사용하는 MemoryMemberRepository나 DB를 사용하는 DBMemberRepository로 대체될 수 있다

[ Order & Discount ]

  • 할인 정책(Discount Policy)은 미정상태라서 대체될 수 있는 환경이다.
  • 우리는 최초에 할인 정책을 변경할 때 발생되는 DIP/OCP문제에 집중해야 한다

DI적용 전

(OrderServiceImpl.java)

  • 상단 코드에서는 할인 정책이 바뀔 때 마다 Client Code인 OrderServiceImpl을 변경해야 하는 문제점이 발생한다.
    • DIP 위배
      : 인터페이스 뿐만 아니라 직접적인 구현체까지 의존하고 있기 때문
    • OCP 위배
      : 기능을 확장하면 (할인정책을 바꾸면) Client Code를 직접 수정해야 함

(MemberServiceImpl.java)

  • 기능이 확장(DB가 변경)될 때 MemberServiceImpl 코드는 수정된다
    • OCP위배
      : DB가 변경된다면 memberRepository 생성하는 new뒤에를 직접 변경해야함
    • DIP 위배
      : 인터페이스를 의존하지만, 구현체 역시 의존

DI적용 후

(AppConfig.java) 작성

  • DI를 적용하기 전 코드는 마치 영화배우가 직접 다른 영화배우를 캐스팅 하는 것과 같은 상황이었다
  • 객체를 생성하고 관계를 관리하는 공연 관리자의 역할을 해줌으로써 배우는 어떤 상대 배우가 오든지 자신의 역할만 하면 되게 할 수 있다
  • 구현체가 아닌 인터페이스만 바라보게 한 뒤, 실제 사용되는 구현체는 생성자를 통해 의존성을 주입해주는 것!

(OrderServiceImpl.java)

  • 객체 간 의존성을 AppConfig.java에서 관리하기 때문에 interface만 생성 후 생성자를 통해 의존성을 받는 방식
  • DIP 지켜짐
    : 구현체가 아닌 인터페이스만 의존하는 관계로 변경됨
  • OCP 지켜짐
    : 기능이 확장되어도 실제 Client Code는 변경되지 않는다!
    (AppConfig 만 변경)

(MemberServiceImpl.java)

  • 이제 DB가 변경되어도 이 코드들은 변경되지 않아도 된다!
    --> AppConfig.java만 변경되면 된다!

정리

  • 구현 객체를 생성하고 연결하는 별도의 클래스(AppConfig)를 생성해서 객체 간 의존성을 관리하여 OCP / DIP 위배 문제를 해결
  • 해당 코드는 순수 Java를 사용했지만, DI의 필요성을 SOLID 5가지 관점에서 살펴볼 수 있는 예제
  • 애플리케이션 실행시점외부에서 실제 구현 객체를 생성해서 실제 의존관계가 연결 되는 것을 의존관계 주입 이라고 함
  • DI(의존관계 주입)을 해주는 역할을 DI 컨테이너라고 함

IoC / DI / DI 컨테이너

  • IoC (Inversion of Control)
    • 제어의 역전
    • 프로그램의 제어 흐름을 개발자가 아닌 프레임워크에게 넘겨 작업의 구현과 수행을 분리할 수 있는 하나의 전략
    • 오늘 예제에서는 AppConfig가 제어의 흐름을 가지고 있다!
    • 라이브러리는 IoC를 가능하게 할 수 없다
  • DI (Dependency Injection)
    • 의존관계 주입
    • 정적 클래스 의존관계 / 동적 클래스 의존관계로 분리 가능
    • 정적 클래스 의존관계
      : 코드만 보고 파악 가능한 의존관계
    • 동적 클래스 의존관계
      : 실행 시점에 실제 생성된 객체 인스턴스의 참조가 연결된 의존 관계
  • DI 컨테이너 (DI Container)
    * DI를 관리하는 컨테이너
    • IoC 컨테이너라고 부르기도 함
profile
Developer & PhotoGrapher

0개의 댓글