4계층 구조에서의 의존 관계 - 2-7-team/user-service GitHub Wiki

기존 3계층 방식

기존 3계층 방식은

Presentation -> Service -> Repository 로 이루어져 있는데 각각

presentation은 controller와 같은 외부 클라이언트와의 요청, 응답을 처리합니다.

Service의 경우에는 비즈니스 로직을 수행하며, db 정보 필요 시 repository에 요청하여 사용합니다.

Respository는 db와 연결되어 실제 crud를 수행합니다.

이 방식의 단점은

외부 기술과 같은 ex) jwt나 kafka 와 같은 기술을 사용할 때, 서비스가 이를 직접적으로 호출함으로써 서비스가 외부기술에 종속된다는 단점이 존재합니다.

따라서 서비스를 외부기술로부터 격리하기 위해, 별도의 infrastructure 계층을 두어 외부기술은 infrastructure에, 서비스는 로직에만 집중하도록 하여 4계층 구조가 사용됩니다.

4계층에서의 고수준 계층과 저수준 계층

고수준 계층은 어떤 기능을 제공하는 계층이고, 저수준은 그것의 기능을 구현한 계층입니다.

그렇게 되면 고수준 계층에서 해당 기능을 제대로 사용하기 위해서는, 저수준 계층을 의존하게 되는 현상이 발생하게 됩니다.

이렇게 되면, 비즈니스 로직이 특정한 기술에 종속된다는 문제가 존재합니다.

따라서 고수준 모듈은 저수준을 의존하지 않고, 본연의 기능에만 집중하는 것이 좋습니다.

따라서 이를 DIP(의존 관계 역전)을 통해 저수준이 고수준 계층을 바라보게 해야합니다.

USER-SERVICE에서는 DIP를 다음과 같은 방식으로 구현했습니다:

  1. Domain 계층UserRepository 인터페이스를 정의 → UserService는 해당 인터페이스만 바라보도록 설정

  2. Infrastructure 계층UserRepositoryImpl 구현체 작성 → 도메인 인터페이스를 구현하면서 실제 동작 처리

  3. UserRepositoryImplJPA 또는 QueryDSL 같은 외부 기술을 직접 참조하여 → 실제 구현을 담당하는 기술 스택을 분리

장점

도메인 계층에서 추상화를 통해 실제 서비스는 어떤 repository를 사용하느냐에 초점을 맞추지 않고, repository를 사용한다에만 초점을 맞출 수 있습니다.

도메인 계층에서는 어떤 유저정보가 저장된다는 사실이 중요하고 어떤 기술을 사용했느냐는 알고 있을 필요가 없습니다.

또한 구현 기술이 변경되어도 Service는 변경되지 않는다는 장점도 존재합니다.

따라서 서비스는 로직 자체에만 집중을 하고, 그것을 구현하는 구현체, 구현 기술을 infrastructre에 두는 것이 좋습니다.

결론

  • Domain은 인터페이스를 정의
  • Infrastructure는 Domain의 인터페이스를 구현
  • Application의 service는 Domain의 인터페이스를 사용만