슬기로운 개발생활

DDD(Domain-Driven Design) 계층구조(Layered Architecture) 알아보기

by coco3o
반응형

시작하기 앞서 도메인이 무엇인지, 도메인 주도 설계(Domain-Driven Design)란 무엇인지부터 가볍게 알고 넘어가자.

도메인이란

사전적 의미는 '영역', '집합'이다.
'실세계에서 사건이 발생하는 집합' 이라고 생각하면 쉬울 것 같다.

DDD에서 말하는 도메인은 비즈니스 도메인을 말하며, 비즈니스 도메인은 유사한 업무의 집합이다.

쇼핑몰을 예로 들면,
쇼핑몰에서는 손님들이 주문하는 도메인(Order Domain)이 있을 수 있고,
직원입장에선 옷들을 관리하는 도메인(Manage Domain)이 있을 수 있고,
결제를 담당하는 도메인(Payment Domain)이 있을 수 있다.

이렇게 여러가지 도메인들이 상호작용하며, 비즈니스 도메인별로 나누어 설계하는 것이 바로 도메인 주도 설계(이하 DDD)이다.

도메인(Domain)과 객체(Object)의 차이

객체의 의미는 아주 간단하게 말해서 현실 세계의 개념들을 프로그래밍에 반영하는 것을 말한다.

차이는 도메인과 객체를 설명하는 범위에서 나타난다.
객체는 추상화 또는 구체화할 수 있는 특정 요소만을 표현하는 반면,
도메인은 사용자가 사용하는 모든 것을 설명할 수 있다.

예를 들면,

"고양이는 사과를 먹는다."

객체의 관점에서는 "고양이"와 "사과"를 표현할 수 있고, "먹는다"는 객체가 하는 행위로 별도로 표현한다.
도메인의 관점에서는 "고양이", "사과", "먹는다", "고양이는 사과를 먹는다." 모두 각각 도메인이라고 할 수 있다.

객체는 현실 그대로를 표현하고 있고,
도메인은 위의 문장을 읽는 사용자가 바라보는 관점에 따라 각각을 구분하거나 전체라고 할 수 있다.

그렇다면, 다음과 같은 질문을 던져볼 수 있겠다.

도메인은 명확하게 정해져 있지 않고 사용자에 따라 또는 사용자가 바라보는 관점에 따라 계속 바뀔 수 있을까요?

그렇다.
도메인은 사용자가 누구인가에 따라, 어떻게 사용하냐에 따라 같은 요소라고 할지라도 계속 바뀔 수 있고, 형태가 고정되어 있지 않다.
어느 사용자가 "고양이", "사과를 먹는다" 두 가지 관점으로 바라보고 있다면, 해당 문장에서의 도메인은 2개라고 할 수 있다.

DDD의 핵심 목표

"High cohesion" , "Loosly coupling"으로 각각의 도메인은 서로 철저히 분리되고,
높은 응집력과 낮은 결합도 변경과 확장에 용이한 설계를 얻게된다.


DDD의 계층구조(Layered Architecture)

Layered Architecture는 말 그대로 계층이 나뉘어져 있는 아키텍쳐를 뜻한다.
Layered Architecture의 주된 목표는 각각의 layer는 하나의 관심사에만 집중할 수 있도록 하는 것이다.
일반적으로 3 계층 또는 4 계층으로 나누어 사용한다.

※ 3계층으로 나눌 때는 표현계층(Presentation Layer - 서비스계층(Business Layer) - 영속성계층(Persistence Layer)으로 나누어 사용하곤 한다.


대표적으로 DDD에서는 아래와 같은 구조의 Layered Architecture를 가진다.

Layered Architecture를 올바르게 구현하기 위한 두 가지 중요한 규칙이 있다.

1. 위의 계층에서 아래 계층에는 접근이 가능하지만 아래에서 위로는 불가능한 것을 기본으로 한다.
2. 한 계층의 관심사와 관련된 어떤 것도 다른 계층에 배치되어서는 안된다.


계층별 설명

1. Presentation Layer (표현 계층) (Controller)

  • 사용자 요청에 대해 해석하고 응답하는 일을 책임지는 계층이다.
  • 사용자에게 UI를 제공하거나 클라이언트에 응답을 다시 보내는 역할을 하는 모든 클래스가 포함된다.
  • Client로부터 request를 받고 response를 return 하는 API 정의

2. Application Layer (응용 계층) (Service)

  • 비즈니스 로직을 정의하고 정상적으로 수행될 수 있도록 도메인 계층과 인프라스트럭쳐 계층을 연결해주는 역할을 하는 계층이다.
  • 이 계층은 많은 정보를 가지고 있지 않게 유지하는 것이 중요하며,
  • 실질적인 데이터의 상태 변화 등의 처리는 도메인 계층에서 진행할 수 있도록 위임하는 것이 중요하다.

Application Layer에 포함하는 기능들

1. 트랜잭션의 단위
2. DTO 변환
3. 엔티티 조회/저장

단순하게 말하면 Entity를 찾고(Repository), 변경 내용을 저장하는 기능(Persistence)을 호출한다.
(구현은 Infra layer)

 

4. 사용자 인증/인가

사용자가 특정 URL에 대해 권한이 있는지 정도의 인가는 presentation layer에서 하지만,
URL만으로 판단이 어렵거나, DB내의 데이터와 대조해봐야 알 수 있는 경우(데이터 존재 여부, 중복 여부 등)

 

5. 파라미터 검증

presentation layer에서도 수행할 수 있지만 주로 요청 방식에 따라 달라지는 '형식'에 대한 검증을 하고,
application layer에서는 '논리적'인 오류를 검증한다.

3. Domain Layer (도메인 계층) (Model)

  • 비즈니스 규칙, 정보에 대한 실질적인 도메인에 대한 정보를 가지고 있으며 이 모든 것을 책임지는 계층이다.
  • Entity를 활용하여 도메인 로직이 실행되며, 업무 상황을 반영하여 상태를 제어하는 역할에 집중하는 계층이다.

4. Infrastructure Layer(인프라 계층) (Repository)

  • 외부와의 통신(DB, 메시징 시스템 등)을 담당하는 계층이다.
  • 해당 계층에서 얻어온 정보를 응용 계층 또는 도메인 계층에 전달하는 것이 주 역할이다.


각각의 도메인들을 위와 같은 Layer로 철처히 분리해서 만드는 것이 DDD(Domain-Driven Design)의 핵심 설계 방식이다.


Layered Architecture 구현

Spring의 대표적인 예제 프로젝트인 Spring Pet Clinic으로 Layered Architecture를 패키지로 구성해보면 다음과 같다.
해당 프로젝트는 도메인 지향적인 것으로 추정되는 패키징을 사용하지만, 코드 구성의 두 가지 방법이 서로 어떻게 다른지 보자.

PetClinic 프로젝트는 Application Layer 즉, Service가 없고 거의 모든 것이 Controller에서 수행된다는 점을 참고하자.


Layered Architecture의 장단점

장점

  • 각 레이어를 loosely coupling 된 형태로 구축하면서, 각각 자신의 관심사에만 집중할 수 있다.
  • 핵심 비즈니스 로직을 순수하게 유지함으로써 유지보수와 확장성 측면에서 이득을 얻을 수 있다.
  • 각 레이어에 서로 다른 추상화 수준을 가진 상태와 행동을 위치시킴으로써 코드 재사용성을 높일 수 있다.

단점

  • 서비스가 커질수록 복잡도가 증가하여 확장성이 떨어진다.
  • 레이어로 분리된 관심사 외에 다른 관심사가 생길 경우 패키지 분리 및 코드 배치가 어렵다.

Layered Architecture를 사용해야 하는 경우

작고 단순하며 확장성보다는 일관성을 가져가는 것이 목표인 어플리케이션이나 웹사이트에 적합하다.
또한 단순성 및 구현 용이성으로 인해 어플리케이션 시작점으로 사용하기에 좋다.


참고 자료 :
Layered Architecture Is Good
도메인 주도 설계(Domain-Driven Design) in Real Project — 도메인
백엔드 서버 아키텍처 - Application Layer1. 개요와 기본 Variation
DDD(Domain Driven Design) - 도메인 주도 설계란? 마이크로서비스의 관점에서
DDD(domain driven development)의 계층 구조(layered architecture)에 대해서 알아보자

반응형

블로그의 정보

슬기로운 개발생활

coco3o

활동하기