티스토리 뷰

728x90
반응형

DI특정 객체가 의존할 객체나 메서드를(즉, 의존관계를) 외부에서 주입받는 디자인 패턴이다.

 

여기서 주입이란 위 그림에서 보듯이 의존성을 사용하려는 객체에게 전달하는 것이라 받아들이면 되며,

 

디자인 패턴이란 공통적인 문제에 대한 재활용 가능한 솔루션이자 컨셉이라 생각하면 편하다.

 

 

 

또한 DI는 스프링의 핵심 원칙인 IoC(제어 역전)를 구현하는 수단 중 하나인데,

 

DI의 목표가 객체의 설계와 사용이라는 관심사를 분리함으로써 느슨한 관계로 이루어진 앱을 만드는 것이기 때문이다.

 

이는 코드의 가독성과 재사용성을 크게 높여주는 효과도 가지고 있다. 

 

그렇다면 이렇게까지 주입하려는 의존성이란 무엇일까? 간략하게 알아보자.

 

Dependency

 

Dependency는 의존성, 의존관계라고 번역한다.

 

나는 처음엔 의존성이라는 단어로 배웠지만 공부를 하다 보니 의존관계라는 표현이 더 정확한 것 같다.

 

그렇다면 위 그림처럼 객체 A가 객체 B에게 의존한다는 것은 무슨 뜻일까?

 

코드 레벨에서 보기 전에 개념부터 말하자면 A가 B에게 의존하고 있다는 말은

 

의존 대상인 B가 변하면, 의존하고 있는 A도 변할 가능성이 있다는 말이다.

 

B의 구성이나 로직이 변하면 그것이 A에게도 영향을 끼칠 가능성이 있다는 말이다.

 

여기서 가능성이라는 표현은 경우에 따라 A가 변경되지 않는 경우의 수도 있다는 뜻이 된다.

 

계속해서 코드레벨에서 의존관계에 대해 살펴보자.

 

아주 간단하게 의존관계를 표현하면 아래와 같다.

 

의존하고 있는 A 클래스가 자신의 내부에 의존 대상인 B 클래스의 객체를 생성한 뒤 메서드를 호출하는 것을 확인할 수 있다.

 

이처럼 의존관계특정 객체가 자신의 내부에 대상 객체 타입의 인스턴스를 생성하고 메서드를 호출하는 식으로

 

대상 객체의 기능을 사용하는 것을 말한다.

 

또한 더 다양하고 유연한 의존성을 생성하려면 대상 객체를 인터페이스로 추상화하면 되는데,

 

이는 자바가 다중상속을 금지하고 있기 때문이다.

 

계속해서 위처럼 new 키워드를 통한 직접적인 인스턴스 생성으로 의존하는 경우를 강한 결합(Tight Coupling)이라 부른다.

 

(혹은 컴파일 시점에 의존관계가 결정되기 때문에 컴파일타임 의존성이라 부르기도 한다.)

 

강한 결합은 초기 구현이 쉽지만 B의 변경이 거의 필연적으로 A의 변경을 요구하게 되는데(이를 의존성 전이라 한다),

 

이때문에 애플리케이션의 규모가 커질수록 객체의 수정 및 유지보수가 힘들어진다는 단점이 존재한다.

 

따라서 이런 단점을 극복하면서도 객체가 의존관계를 맺을 수 있도록 돕는 테크닉이 필요해졌는데,

 

그 해결책이 바로 DI(의존관계 주입)라 할 수 있다. 계속해서 알아보자.

 

Dependency Injection(DI)

 

DI는 한 마디로 말하면 객체 간의 의존관계가 사용 객체(A) 외부에서 정해지는 방식을 말한다.

 

기존에는 객체 내부에서 직접 인스턴스를 생성하는 강한 결합을 사용했다면,

 

DI에서는 먼저 외부에 생성된 객체를 담을 그릇(이를 스프링 컨테이너, 혹은 IoC 컨테이너라 한다)

 

생성된 객체 사이의 관계를 정의할 클래스(Appconfig.class 등)를 만든다.

 

이어서 컨테이너 안에서 먼저 의존관계를 생성한 뒤, 사용 객체에게 그것을 주입하게 되는데,

 

간단하게 코드로 보면 아래와 같은 모양이 된다.

 

외부의 클래스 Injector에 의해 객체가 생성되고 의존관계가 정해진 뒤 주입되는 것을 확인할 수 있다.

 

즉, 위에서 말한 것처럼 객체 생성(구성)과 사용(동작)의 관심사가 분리되어 사용 객체가 기능의 구성을 알 필요가 없게 된다.

 

이는 결과적으로 의존 대상(B)의 변경에서 사용 객체(A)의 변경을 분리

 

B의 변경이 A의 변경을 요구하지 않게 된다.

 

이와 같이 DI를 통해 주입된 의존관계를 느슨한 결합(Loose Coupling)이라 부르며

 

코드 가독성과 재사용성(확장성)을 높여주는 동시에 객체의 수정 및 유지보수를 유연하게 해주는데,

 

더 길게 보면 Mocking 객체를 이용한 단위 테스트(Unit Test) 시에도 편의성을 제공한다.

 

추가로 강한 결합과 달리 DI는 런타임시에 의존관계가 결정되며, 이때문에 런타임 의존성이라 부르기도 한다.

 

마지막으로 DI는 위의 예처럼 생성자를 통해 주입하는 것 말고도 세 가지 방법이 더 존재하는데,

 

일반적으론 생성자를 위한 방식을 권장하고 있다.

 

구체적인 DI 방식과 방식 간의 차이는 다른 글에 정리해두었다.

 

2022.08.09 - [Development/Spring] - [Spring]Spring Framework, Spring Triangle

2022.08.12 - [Development/Spring] - [Spring]DI - 스프링 컨테이너(Container)와 빈(Bean)

2022.08.12 - [Development/Spring] - [Spring]DI - 빈 스코프(Bean Scope), 싱글톤 컨테이너

2022.08.12 - [Development/Spring] - [Spring]DI - @Component, @Configuration, @Bean, 스프링 컨테이너 구성

2022.08.12 - [Development/Spring] - [Spring]Spring DI(Dependency Injection)

 

[Spring]Spring DI(Dependency Injection)

DI(Dependency Injection, 의존성 주입)는 스프링 프레임워크의 네 가지 특징 중 하나이다. 이전 글에서 다룬 적이 있지만, 간략하게 요약하면 다음과 같다. 2022.08.09 - [개발/Spring] - [Spring]Spring Framewo..

gnidinger.tistory.com

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함