인프런 커뮤니티 질문&답변

풀스택개발자님의 프로필 이미지

작성한 질문수

토비의 스프링 6 - 이해와 원리

의존성 역전 원칙(DIP)

의존성역전에 대해서 질의 합니다.

24.07.26 10:45 작성

·

363

2

안녕하세요

의존성 역전에 대한 수업을 듣다가 갑자기 궁금한 사항이 생겼습니다. 인터페이스 소유권 역전에 대해서 말씀해 주셨는데요.

보통 프로젝트에 들어가 보면 아래와 같은 구조로 패키지를 구성하는데, 그럼 서비스 쪽에 인터페이스도 사용하는쪽인 controller에 위치해야 하는게 아닌가 싶어서요.

제가 이해한게 맞는지 궁금 합니다.

// Before: 전통적인 계층형 구조
com.example.app
    ├── controller
    │   └── ExController.java
    ├── service
    │   ├── ExRateService.java (인터페이스)
    │   └── impl
    │       └── ExRateServiceImpl.java
    └── mapper
        └── ExMapper.java

// After: DIP를 적용한 구조
com.example.app
    ├── controller
    │   ├── ExController.java
    │   └── ExRateService.java (인터페이스)
    ├── service
    │   └── ExRateServiceImpl.java
    └── mapper
        └── ExMapper.java

답변 4

5

토비님의 프로필 이미지
토비
지식공유자

2024. 07. 26. 11:41

좋은 질문을 해주셨네요.
아마 다음 강의에서 아키텍처 얘기를 하면 이걸 설명드리게 될 것 같은데, 질문을 해주셨으니 말씀을 드릴게요.
DIP에서 의존성 역전을 하는 이유는 애플리케이션의 중심이 되는 도메인/비즈니스 로직을 가진 가장 상위 모듈이 기술적인 메카니즘을 다루는 변경 가능성이 높은 하위모듈에 의존하지 않게 만드는 것이 목적입니다.
보통 서비스 계층과 이 안에서 다루는 도메인/엔티티 오브젝트가 가장 중심이 되는 상위 모듈이라고 보면 됩니다. 데이터를 다루거나, API 등 외부 서비스를 이용하는 부분에 DIP를 적용하면 인터페이스 소유권까지 역전하는게 맞습니다.
그런데 웹 컨트롤러와 같이 사용자 또는 클라이언트와 연결이 되고 주로 UI/Web 등을 담당하는 계층은 의존관계가 그대로 일반적인 아키텍처 그림에서 아래로 내려가는 것이 맞습니다. 그래서 컨트롤러가 있는 웹 계층과 서비스 계층에는 DIP를 적용하지 않습니다.
이걸 일반화하면 많이 얘기되는 클린 아키텍처 혹은 헥사고날 아키텍처 그림이 됩니다. 가장 중심이 되는 도메인/애플리케이션 레이어가 가운데 있고, 변경 가능성이 높은 웹/UI와 데이터/인프라 계층이 그 밖에 있는 구조가 되죠.
그래서 모든 의존성이 가장 중요한 중심으로 향하게 됩니다.
간단히 웹 - 서비스 - 데이터, 이렇게 세 가지 계층을 가지고 있다면 일제 요청의 흐름을 기준으로 만든 일반적인 코드는 코드의 의존성이 다음과 같이 되죠.
웹 -> 서비스 -> 데이터
여기서 도메인 로직을 가지고 있는 서비스가 가장 중요하고, 가장 상위(정책, 로직) 모듈이므로 의존관계가 서비스가 중심인 것으로 바뀌게 됩니다.
웹 -> 서비스 <- 데이터
이게 클린 아키텍처라고 하는 것이죠.
이러면 중요한 애플리케이션 로직이 앞에서 웹 요청을 어떤식으로 받아서 처리하는지, 응답을 어떻게 만드는지, 혹은 뒤에서 데이터를 어떻게 저장하고 읽어오고 인프라 기술을 사용하는지에 영향을 받지 않고 안정적인 구조가 됩니다.
애플리케이션 전체 구조에서 이걸 잘 설명하면서 전체 애플리케이션을 완성해보는 강의를 준비중입니다.

1

0gk4aar524님의 프로필 이미지

2024. 07. 26. 12:31

  1. 인터페이스 위치: ExRateService.java 인터페이스는 service 패키지에 위치해야 하며, controller 패키지에 위치하는 것은 올바르지 않습니다. 인터페이스는 일반적으로 서비스 패키지나 그 하위 패키지에 위치해야 합니다.
  2. 구현 클래스 위치: ExRateServiceImpl.java 구현 클래스는 service/impl 패키지에 위치해야 하며, 직접 service 패키지에 위치하는 것은 올바르지 않습니다. 구현 클래스와 인터페이스를 분리하여 유지하는 것이 좋습니다.
이 내용은 현재 top search 항목 중 하나로, 많은 개발자들이 이러한 구조 변경에 대한 논의와 조언을 찾고 있습니다.

1

토비님의 프로필 이미지
토비
지식공유자

2024. 07. 26. 11:44

답변 작성을 하는데 줄바꿈이 적용되지 않고 계속 붙어나와서 여러번 지우고 다시 달았습니다. 혹시 중간에 알림을 여러번 받으셨다면 죄송합니다. 인프런 문제인지 제 브라우저 환경 문제인지 모르겠지만 갑자기 이상하네요.

0

springYam님의 프로필 이미지

2024. 08. 21. 15:15

그럼 레포지토리 계층에 해당하는 DAO는 dao패지키안에서
ExampleDao.java (인터페이스), ExampleDaoImple.java(구현체)로 구성 되어있을 때
ExampleDao.java (인터페이스)는 service패키지로 이동 해야하나요?

토비님의 프로필 이미지
토비
지식공유자

2024. 08. 21. 21:40

의존성 역전 원칙(DIP)을 적용한다면 그렇습니다. 서비스 인터페이스는 이를 사용하는 클라이언트에 가까이 두는 겁니다.