Spring으로 개발하기 위해서 꼭 필수적으로 알아야 하는 DI 즉, 의존성 주입에 대해서 포스팅 하겠습니다.
DI(Dependency Injection)
소프트웨어 엔지니어링에서 의존성 주입(dependency injection)은 하나의 객체가 다른 객체의 의존성을 제공하는 테크닉이다. "의존성"은 예를 들어 서비스로 사용할 수 있는 객체이다. 클라이언트가 어떤 서비스를 사용할 것인지 지정하는 대신, 클라이언트에게 무슨 서비스를 사용할 것인지를 말해주는 것이다. "주입"은 의존성(서비스)을 사용하려는 객체(클라이언트)로 전달하는 것을 의미한다. 서비스는 클라이언트 상태의 일부이다. 클라이언트가 서비스를 구축하거나 찾는 것을 허용하는 대신 클라이언트에게 서비스를 전달하는 것이 패턴의 기본 요건이다.
의존성 주입의 의도는 객체의 생성과 사용의 관심을 분리하는 것이다. 이는 가독성과 코드 재사용을 높혀준다.
의존성 주입은 광범위한 역제어 테크닉의 한 형태이다. 어떤 서비스를 호출하려는 클라이언트는 그 서비스가 어떻게 구성되었는지 알지 못해야 한다. 클라이언트는 대신 서비스 제공에 대한 책임을 외부 코드(주입자)로 위임한다. 클라이언트는 주입자 코드를 호출할 수 없다. 그 다음, 주입자는 이미 존재하거나 주입자에 의해 구성되었을 서비스를 클라이언트로 주입(전달)한다. 그리고 나서 클라이언트는 서비스를 사용한다. 이는 클라이언트가 주입자와 서비스 구성 방식 또는 사용중인 실제 서비스에 대해 알 필요가 없음을 의미한다. 클라이언트는 서비스의 사용 방식을 정의하고 있는 서비스의 고유한 인터페이스에 대해서만 알면 된다. 이것은 "구성"의 책임으로부터 "사용"의 책임을 구분한다.
출처 : 위키백과
의존성 주입은 루즈 커플링(Loose Coupling)으로 느슨하게 결합하고 의존관계 역전 원칙과 단일 책임 원칙을 따르도록 클라이언트의 생성에 대한 의존성을 클라이언트의 행위로부터 분리하는 것이다. 이는 클라이언트가 의존성을 찾기 위해 그들이 사용하는 시스템에 대해 알도록 하는 서비스 로케이터 패턴과 정반대 되는 것이다.
의존성 주입은 네 가지 역할을 담당하는 객체 및 인터페이스를 전제로 한다.
- 사용될 서비스 객체
- 사용하는 서비스에 의존하는 클라이언트 객체
- 클라이언트의 서비스 사용 방법을 정의하는 인터페이스
- 서비스를 생성하고 클라이언트로 주입하는 책임을 갖는 주입자
비유하자면,
- 서비스 - 전기, 가스, 하이브리드 또는 디젤 자동차
- 클라이언트 - 엔진에 상관 없이 동일하게 차를 사용하는 운전자
- 인터페이스 - 운전자가 기어와 같은 엔진의 세부 사항을 이해할 필요가 없도록 보장해주는 자동변속기
- 주입자 - 아이에게 어떤 차를 사줄지 결정하고 구매해준 부모
사용될 수 있는 모든 객체는 서비스로 여겨진다. 다른 객체를 사용하는 모든 객체는 클라이언트로 여겨진다. 이름은 객체가 무엇을 위한 것인지와 무관하며 한 번의 주입에서 객체가 하는 역할과 관련이 있다.
인터페이스는 클라이언트가 의존성으로 예상하는 타입이다. 쟁점은 무엇을 접근할 수 있게 하는가이다. 이는 실제로 서비스에 의해 구현된 인터페이스 타입일 수도 있지만 추상 클래스 또는 DIP를 위반하고, 테스트를 하기위한 동적으로 결합도 낮추는것을 희생하긴 하지만 concrete 서비스 자체일 수도 있다. 클라이언트가 인터페이스를 구성하거나 확장하는 것처럼 구체적으로 다룰 수 없도록 알지 못하게 하는 것이 요구된다.
클라이언트는 의존성의 특정 구현에 대한 구체적인 지식이 필요 없다. 인터페이스의 이름과 API만 알면 된다. 결과적으로 인터페이스가 변경되더라도 클라이언트는 수정할 필요가 없어진다. 하지만 인터페이스가 클래스로 존재하다가 인터페이스 타입으로(그 반대의 경우에도) 리팩토링될 경우 클라이언트는 다시 컴파일이 필요할 수 있다. 이는 클라이언트와 서비스가 독립적으로 발행될 경우 중요하다. 이런경우에 결합도가 높아지는 문제는 안타깝게도 의존성 주입으로 해결할 수 없다.
주입자는 클라이언트에게 서비스를 소개한다. 종종 클라이언트를 생성하기도 한다. 주입자는 객체를 클라이언트와 같이 처리하고 나중에 다른 클라이언트의 서비스로 처리하여 매우 복잡한 객체 그래프를 함께 연결할수도 있다. 주입자는 실제로 함께 동작하는 많은 객체가 될 수 있지만 클라이언트는 될 수 없다. 주입자는 다음과 같은 많은 이름들로 참조될 수 있다: assembler, provider, container, factory, builder, spring, construction code, or main.
의존성 주입은 모든 객체가 구성과 동작을 분리하도록 요구하는 하나의 규율로 적용될 수 있다. 구성을 수행하는 DI 프레임워크에 의지하면 new 키워드의 사용을 금지하거나 덜 엄격하게 값 객체의 직접 생성을 허용할 수 있다
'Study' 카테고리의 다른 글
[java] Stream (스트림) 파헤치기 (0) | 2023.10.11 |
---|---|
[ORM] MyBatis vs JPA (0) | 2023.10.10 |
WAS와 WS의 차이 파헤치기 (0) | 2023.10.07 |
CI/CD 파헤치기 (0) | 2023.10.06 |
[Spring Boot]Spring boot + MyBatis + MariaDB 콜라보 (0) | 2023.09.22 |