코딩항해기

[리뷰/우아한테크] 오찌, 야호의 DI와 IoC 본문

IT tech

[리뷰/우아한테크] 오찌, 야호의 DI와 IoC

miniBcake 2024. 10. 6. 15:12

 

 

 

 

IoC

Inversion of Control 제어의 역전

역전이 일어나기 전에는 직접 객체를 생성해 코드를 제어했다. 즉, 직접 관리하는 것을 의미한다. 제어의 역전이란 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 말한다.

 

IoC 필요성

직접 객체를 생성해 내부에서 관리하게 되면 변동이 생길 때마다 코드에 큰 변화가 생기게 된다. 그러나 외부에서 관리하게 되면, 제어의 역전이 일어나게 되면 외부에서 객체를 관리하므로 값이 변동되어도 코드에는 변화가 생기지 않는다.

 

객체 지향의 원칙을 잘 지키기 위해 필요하며, 역할과 관심을 분리해 응집도를 높이고 결합도를 낮추며, 이에 따라 변경이 유연한 코드를 성할 수 있는 구조가 되기 때문이다.

 

할리우드 법칙 Hollywood Principle 

Don't call us, we'll call you

 

DIP

Dependency Inversion Principle 의존 역전 원칙

상위 레벨의 모듈은 절대 하위 레벨 모듈에 의존하지 않는다. 둘 다 추상화에 의존해야한다.

ex) 이탈리안 비엠티는 화이트브레드라고 하면 의존적, 이탈리안비엠티에는 빵(추상화)이 들어가고 빵에는 여러가지가 들어갈 수 있는 것이 의존 역전이다.

 

IoC와 DIP

IoC와 DIP는 모두 원칙이고 같은 목적을 가졌지만 IoC는 제어의 역전, DIP는 의존의 역전이다.

IoC는 제어권이 내부에서 외부로 변경된 것이다. 

DIP는 필드가 인터페이스로 구성되어 있어 다양한 모듈이 들어올 수 있다. 서로 추상화에 의존하고 있어 의존의 역전이 일어난다.

 

IoC방법

  • Service Locator pattern
  • Factory pattern
  • Abstract Factory pattern
  • Template  Method pattern
  • Strategy pattern
  • Dependency Injection pattern

 

DI

dependency Injection 의존성 주입

의존성이란
클래스 간의 의존 관계가 있다는 것 = 한 클래스가 바뀔 때 다른 클래스가 영향을 받는다는 것

 

의존성 주입은 말 그대로 의존성을 다른 곳에 주입해주는 것을 말한다. 

 

의존성 주입은 생성자 주입, Setter 주입, Interface 주입 패턴으로 나눠진다.

interface 주입은 interface를 구현하면서 의존 주입이 일어나게 된다. setter와 동일한 방식이지만 오버라이딩을 통해 빠뜨리는 경우를 방지할 수 있다.

 

의존성 분리

DIP를 이용해 의존 관계를 분리한다. 즉, 상위계층이 하위계층에 의존하는 상황을 interface를 이용해 반전시켜 하위계층의 구현으로부터 독립시키는 것을 말한다.

 

 

Spring 자동 주입 @Autowired

필드 주입, 생성자 주입, setter주입이 있다.

 

필드 주입은 필드 위에 @Autowired 어노테이션을 붙여 할 수 있다. 가장 간단한 방법이지만 추천되지 않는다.

필드 주입을 하게될 경우 의존성에 접근하고 싶어도 접근을 할 수 없기 때문이다. (직접 설정할 수 없다.) 스프링 프레임워크에 강하게 종속된다는 것을 알 수 있다.

 

setter주입은 setter메서드 위에 @Autowired 어노테이션을 붙여 할 수 있다. 이때 빈 객체를 생성한 뒤 주입이 이뤄지기 때문에 빈 생성자 또는 빈 정적 팩토리 메서드가 필요하다. 따라서 final 필드를 만들 수 없고, 의존성 주입을 보장할 수 없다. 의존성을 수정하거나, 의존성을 선택적으로 주입할 때 사용한다.

 

생성자 주입은 자동으로 이뤄지고 Spring에서 추천하는 방식이다. 생성자가 한 개 밖에 없을 경우 자동으로 Autowired를 붙여준다. (Spring 4.3이후부터 지원) final이 가능하고 NPE가 발생하지 않는다. 순환참조의 문제도 해결할 수 있다. (에러발생)

 

 

만약 생성자가 여러 개라면 자동 주입하는데 사용할 생성자에 @Autowired를 붙인다. @Autowried가 여러 개 있을 경우 가장 많은 의존성을 주입할 수 있는 생성자를 사용하게 되며 모든 생성자가 사용 불가능한 경우, 또는 어떤 생성자에도 .@Autowired가 없는 경우 기본 생성자를 호출하는데, 기본 생성자도 없을 경우 컴파일 에러가 발생한다.

 

같은 타입의 빈 객체가 여러개 일 경우 Qualifier를 사용할 수 있는데, 생성자의 경우 매개변수 앞에 명시해 줄 수 있다.

@Primary 어노테이션도 있는데, 이 경우 해당 타입으로 의존성을 주입할 때 가장 먼저 주입되게 된다. 기본값이 되는 것이다. (Qualifier는 주입받는 쪽, Primary는 주입되는 쪽에 단다)

 

Qualifier와 Primary가 동시에 존재한다면 Qualifier가 우선권을 가지게 된다.