[영상후기] [10분 테코톡] 오찌, 야호의 DI와 IoC

박철현·2023년 4월 27일
0

영상후기

목록 보기
111/160

movie

  • IoC(Inversion of Control) : 제어의 역전
    • 제어 : 객체 생명주기나 메서드의 호출을 직접 제어(관리)한다.
      • 직접 객체를 생성하여 코드를 제어
public class A {
	private B b;
    
    public A() {
    	this.b = new B();
    }
 }
  • 제어의 역전 : 프로그램의 제어 흐름을 직접 제어하는 것이 아닌 외부에서 관리하는 것
    • 인자로 받아 주입 -> 외부에서 관리
public class A {
	private B b;
    
    public A(B b) {
    	this.b = b;
    }
}
  • IoC 왜 필요할까? 객체지향 원칙을 잘 지키기 위함

    • IoC가 없다면 각 변수에 대한 제어권이 객체 내부에 있음
      • 내부 직접 new 키워드 사용하여 생성
      • 내부 변경이 필요하다면 큰 변경이 필요함
    • 외부에서 제어를 받으며 변경에 자유로움
    • 역할과 관심을 분리해 응집도를 높이고 결합도를 낮추며, 변경에 유현한 코드를 작성할 수 있는 구조가 될 수 있기 때문
  • Hollywood Principle(할리우드 법칙) : 주도권을 빼앗기고 호출당하기를 기다리는것과 유사하여 할리우드 법칙으로 불리기도 함

  • DIP(Dependency Inversion Principle) : 의존 역전 법칙

    • 상위 모듈은 하위 모듈에 의존하지 않고 둘다 추상화에 의존
      • ex) 이탈리안 비엠트 -> 화이트빵 이어야 했음
      • 상위 모듈이 하위 모듈을 의존했던 현상
    • 고수준, 저수준 모두 추상화에 의존하여 제어 역전됨
      • (기존) 이탈리안 비엠티(고수준) -> 화이트 빵(저수준)
      • (변경) 이탈리안 비엠티(고수준) -> Bread InterFace <-> 빵들..
      • Bread : 고수준 모듈인 이탈리안 비엠티 입장에서 생성
        • 저수준이 고수준 의존하는 현상 (메뉴 -> 빵 결정)
          • 기존 : 메뉴(고수준) -> 빵(저수준) 고정
          • 변경 : 메뉴 -> Bread <- 빵(저수준)
        • 역전됨을 알 수 있음
      • 빵 : 화이트 여야 했던 종속
      • DIP 활용 : 어떤 종류의 빵이든 상관 없음


(빵의 종류가 Bread라는 상위 의존-> 역전)

  • IoC와 DIP 목적

    • 클래스 간 결합을 느슨히 하기 위함
    • 한 클래스의 변경에 따른 다른 클래스들의 영향을 최소화
    • 애플리케이션을 지속가능하고 확정성 있게 만든다
  • IoC와 DIP 모두 Principle(원칙) 이다.

    • 같은 목적을 가졌지만 아래와 같이 다름
      • IoC (제어의 역전) : 제어권 내부에서 외부로 역전
        • new 키워드로 생성하지 않고 주입받아서 넣기
      • DIP (의존 역전) : 필드가 인터페이스로 구현되어 있어 변경이 자유로움
      • 위 예시에서 이탈리안 비엠티 빵 종류
        • 화이트 Bread -> Bread로 추상화 -> 화이트 bread가 아니여도 됨
      • 고수준모듈 입장에서 만들어진 인터페이스에 저수준이 의존하게 됨(고, 저수준 모두 추상화에 의존)

  • IoC 방법 : DI(Dependency Injection - 의존성 주입), 팩토리, 템플릿 메소드 등의 방법이 있으나 영상에서는 DI설명

  • 의존성 : 클래스 간 의존 관계가 있다는 것

    • 한 클래스가 바뀔 뛰 다른 클래스가 영향을 받는다는 것
    • 의존성 주입 : 의존성을 넣어준다

주입 방법

  • 생성자 주입 : 생성자를 통해 의존성 주입
    • 필요한 의존성이 필요한 모든 생성자를 만들고, 생성자를 통해 의존성 주입
  • Setter 주입
    • 의존성을 입력받는 Setter 메서드들을 만들고 메서드를 호출해서 의존성 주입
  • Interface 주입
    • 의존성을 주입하는 메서드를 포함하는 인터페이스를 작성하고, 인터페이스를 구현하면서 의존성을 주입한다.
    • setter 주입처럼 외부에서 호출해줘야 하는 것은 비슷하나, 의존성 주입 메서드를 빠트릴 수 있는 setter와 다르게 Override를 통해 메서드 구현을 강제할 수 있는 차이가 있음

의존성을 주입하는 방법을 알아봤지만, 각각의 속성들을 변경하고 싶을때는 어떻게 해야할까? DIP 이용
ex) 화이트브레드 -> 다른 빵으로 변경

  • 의존성 분리 : DIP를 이용해 의존 관계를 분리시킨다.
    • IoC 적용
public class ItalianBMT {
  WhiteBread whiteBread;
  MozzarellaCheese mozzarellaCheese;
  ChiliSauce chiliSauce;
  MayonnaiseSuace mayonnaiseSauce;
  
  public ItalianBMT(WhiteBread whiteBread, MozzarellaCheese mozzarellaCheese, ChiliSauce chiliSauce, MayonnaiseSuace mayonnaiseSauce) {
  this.whiteBread = whiteBread;
  this.mozzarellaCheese = mozzarellaCheese;
  this.chiliSauce = chiliSauce;
  this.mayonnaiseSauce = mayonnaiseSauce;
  }
}
  • DIP : 적용
public class ItalianBMT {
	Bread bread;
    Cheese cheese;
    List<Sauce> sauces;
    
    public ItalianBMT(Bread bread, Cheese cheese, List<Sauce> sauces) {
    this.bread = bread;
    this.cheese = cheese;
    this.sauces = sauces;
    }
}
  • DIP로 의존 관계를 분리할 시 각각의 속성이 변화로부터 자유로움

    • 상위계층이 하위계층에 의존하는 상황을 Interface를 이용해 반전시켜 하위계층의 구현으로부터 독립시킨다.
  • IoC와 DIP는 원칙 / DI는 IoC를 달성하는 디자인 패턴 중 하나

  • Spring DI 방법 -> 자동주입 : 스프링 빈으로 등록되면 스프링이 자동으로 생성, 필요한 의존성도 주입

  • @Autowired 어노테이션 활용 : 여기에 의존성을 주입해줘! 하는 의미

    • 필드주입 : 주입 받고자 하는 필드 위에 @Autowired
    • 테스트 등의 이유로 자동이 아닌 수동 의존성 주입을 하고 싶어도 생성자 및 setter가 없으므로 사용자가 직접 의존성을 넣어줄 수가 없음
    • 의존성이 프레임워크에 강하게 종속한다는 문제점이 있음
  • Setter주입

    • setter 메소드에 @Autowired 어노테이션 붙이면 자동으로 의존성 주입
    • 객체의 속성이 없는 빈 객체를 만들고 Setter로 의존성 주입 -> 빈 생성자 또는 빈 정적 팩토리 메서드 필요
    • final 필드 x, 의존성의 불변을 보장할 수 없음
      • java에서 final 키워드의 경우 필드 선언 또는 생성자에서만 값 지정 가능
      • Setter 주입의 경우 매개변수가 빈 생성자를 활용해 객체를 생성하고 속성을 설정하는 방식으로 객체를 주입하기 때문에 final 키워드 불가능
    • 의존성을 수정하거나 선택적으로 적용할 때 사용
  • 생성자주입

    • 객체의 최초 생성 시점에 의존성 주입
    • 생성자가 하나뿐이 없을 경우 해당 생성자에 @Autowired를 붙여주어 생략 가능
      • 필드를 final 가능, 의존성 주입이 최초 1회만 이루어 짐 -> 의존 관계 불변 가능
    • NullPointerException 방지 가능
    • 순환참조 문제 방지 : 순환참조시 종료시켜버림 ( 2.6 버전부터 나머지 방식도 방지)
  • 생성자가 여러개라면?

    • 의존성을 자동으로 주입하는데 사용할 생성자에 @Autowired
    • @Autowired가 여러 개 있을 경우 가장 많은 의존성을 주입할 수 있는 생성자 사용
    • @Autowired가 붙은 모든 생성자가 사용 불가능한 경우 또는 어떤 생성자에도 @Autowired가 없을 경우 기본 생성자를 호출
    • 기본 생성자 조차 없을 경우 컴파일 에러
    • 생성자 방식 -> 필드 방식 -> setter 방식 순으로 의존성 주입됨
  • 의존성 주입 대상이 여러 개일 때 -> 타입 검색 후 여러개라면 bean의 이름을 기준으로 의존성 주입

    -> 네이버/카카오가 구현되어 있다면, naver라는 이름보고 주입
    -> 그러나 이러면 naver만 주입됨 (수동으로 카카오 넣어줘야하는 등 번거로움)
    -> @Qualifier 어노테이션 활용(해당 빈의 구분자 지정 가능)

    -> @Primary 어노테이션 활용 -> 우선주입

    -> Qualifier와 @Primary 둘다 있다면 Qualifier가 우선순위를 가짐

  • 의존성 주입 기준 : 타입 -> Qualifier -> Primary -> 변수명

profile
비슷한 어려움을 겪는 누군가에게 도움이 되길

0개의 댓글

관련 채용 정보