본문 바로가기

카테고리 없음

레이어드 아키텍처 (Layered Architecture) feat. DDD

*상위 문서: 코드 리뷰: 불완전한 객체에서 나타난 문제들

A. 레이어드 아키텍처(Layered Architecture) 란 

    레이어드 아키텍처는 소프트웨어 시스템을 여러개의 “논리적인 계층”으로 나누어 사용하는 설계 방법 입니다. 논리적으로 계층을 나누는 것은 ‘관심사의 분리’(Separation of Concerns)를 달성하기 위함으로 이를 통해 각 계층의 책임 범위를 제한합니다. 이러한 조치는 각 계층의 응집도를 높이고 서로간 결합도는 낮추어 계층간 일관성 있는 책임과 역할을 확실히 하여 유지보수와 변경에 유연한 소프트웨어를 설계할 수 있습니다. 

 

    관심사를 계층별로 분리를 하였지만, 소프트웨어가 응답을 하기 위해서는 각 계층 간의 협력이 필요합니다. 레이어드 아키텍처에서는 협력을 하면서도 계층간 응집도를 낮추기 위하여 명확한 의존성의 방향을 제시합니다. 레이어드 아키텍처에서는 의존성의 방향(dependency direction)이 위에서 아래로(top to bottom)만 향하는 ‘단방향 의존성’을 기본으로 합니다. (Johnny Willer
여기서 유저와 가장 가까운 쪽이 위층으로 프레젠테이션 계층이 되고 하드웨어와 가까운 가장 아래층은 데이터 계층 입니다. 의존의 방향에 따라 상위 계층은 아래의 계층에 대해서만 의존해야 합니다. 이를 통해 하위 계층은 상위 계층의 구현을 몰라도 되고 각 계층의 의존 범위도 한정되어 계층 안에서 변경이 쉬워지고 모킹과 스터빙을 통한 테스트도 쉽게 합니다. 

 

실무 예시. (출처: Mark Richards)

 

 

    레이어드 아키텍처는 두가지 스타일이 있습니다. 하나는 바로 아래의 계층에게만 의존하도록 하는 Strict Layering(Linear Layering)이 있고 모든 아래 계층에 대해서 의존을 허락하는 Loose Layering(Acyclic Layering)이 있습니다. (Science Direct) 레이어드 아키텍처를 Loose Layering 방식으로 모든 아래 계층을 다 열어서 쓸수도 있겠지만 레이어 별로 opened layer로 둘지 closed layered로 둘지 레이어간의 격리수준(layers of isolation)을 정해서 사용할 수 있습니다. (Mark Richards) 하지만 레이어간 격리수준을 열어줄수록 상위 계층은 더 많은 하위계층에 의존을 하게 되어 하위계층의 변경에 더욱 민감하게 되어 고민이 필요한 부분입니다. 혹시 레이어를 열어 줄 경우 적절한 문서화가 꼭 필요합니다. (도둑탈을 쓴 애쉬님)

 

왼쪽 : 한 단계씩만 허용 / 오른쪽: 건너 뛰는 경우 (출처: Mark Richards)

 

B. 레이어드 아키텍처의 계층 

 

출처: Arho Huttunen

 

레이어드 아키텍처를 나누는 기준이 정해져 있지는 않지만 크게 3계층으로 나뉘고 경우에 따라 세분화를 하면 4-5 계층 까지 나눌수도 있습니다. 

 

1. Presentation Layer (UI - User Interface Layer)

  • 사용자와 상호작용하는 HTTP등의 요청을 받고 응답을 하는 API 역할을 합니다.
  • 컨트롤러를 통해 사용자의 요청을 받고 요청에 알맞는 포맷의 View(HTML, JSON등)를 내려 줍니다.
  • Exception이나 Error 발생시 400,500 응답을 처리합니다. 

2. Business Layer

  • Application Layer
    • 실제 비즈니스 로직보다도 추상화된 각 도메인의 기능들을 이용하여 도메인간 협업을 조직(orchestrate) 합니다.
    • 데이터 베이스와 직접 상호작용하기 보다는 도메인 레이어의 도메인의 상호작용을 돕습니다.
    • 문제 1: 도메인 서비스가 너무 많은 책임을 가지게 되는 경우 Application Layer로 협업하고 도메인을 나누는 것이 권장됩니다.(Solomon Maeng님, Johnny Willer)
    • 문제 2:  도메인이 아닌 Application 계층에 너무 집중시 도메인을 제대로 사용 못하고 빈약한 도메인 모델(Anemic Domain Model)을 사용하는 안티패턴이 생길 수 있습니다. (Martin Fowler, John Mikael Lindbakk, Microsoft
    • 문제 1,2 관련해서 더 자세히 보려면 'DDD관점에서의 레이어드 아키텍처' 참조.
    • DDD 1: 애그리거트 루트 또는 외부 시스템과의 협력을 조율하여 하나의 사용자 요청의 시작에서 끝인 유스케이스를 구현합니다.
    • DDD 2: 각 애그리거트의 트랜잭션을 시작하고 관리합니다.
  • Domain Layer
    • 핵심 비즈니스 로직을 다룹니다.  
    • 데이터 유효성 검증, 엔티티 간 관계 표현(도메인 모델링), 비지니스 규칙을 구현. 
    • 도메인 모델링을 통해 각 도메인의 책임을 확실히 하고 경계를 확실히 하여 느슨한 결합을 만들어 낼 수 있습니다.
    • DDD 1: 도메인 모델링을 통해 바운디드 컨택스트들 또는 바운디드 컨텍스트 내부의 엔티티들 간의 경계를 확실히 합니다. 
    • DDD 2: 애그리거트 루트를 통해 각 애그리거트의 트랜잭션 일관성을 관리 받습니다. 
    • DDD 3: 엔티티 또는 경우에 따라 도메인 서비스에 유스케이스에 사용될 비즈니스 로직을 구현합니다. 
    • DDD4: 애그리거트 루트를 기준으로 '도메인 리포지토리'를 생성합니다. (애그리거트 루트당 하나, 도메인 리포지토리 != 인프라의 리포지토리)

3. Infrastructure Layer

  • Persistence Layer:
    • 데이터를 어떻게 접근하고 영속화 할지에 대한 로직을 다룹니다. (DAO, Repository)
    • 영속화된 데이터를 가져와서 도메인 레이어에 맞게 가공을 해서 보내 줄 수 있습니다.
    • 또한 도메인 레이어에서 받은 엔티티를 데이터 저장소의 포맷에 맞게 바꾸어 영속화 시킵니다. (RedisTemplate, MyBatis, JPA 등) 
  • Database Layer:
    • 실제 데이터 베이스가 있는 계층 입니다. 

C. 레이어드 아키텍처 도입시 주의점

  1. 복잡성 증가:
    • 단순한 프로젝트의 경우 복잡성을 오히려 추가 시켜 관리가 어려워 질 수 있습니다.
  2. 러닝커브:
    • 아키텍처가 익숙하지 않고 어떤 코드가 어느 계층에 들어갈지 헷갈려서 러닝커브가 있을 수 있습니다.
  3. 오버헤드:
    • 레이어드 아키텍처를 사용하면 여러 계층을 통하여 통신하기에 과정에서 오버헤드가 발생할 수 있습니다.

 

D. 레이어드 아키텍처와 혼동되는 개념들

*이어보기: 레이어드 아키텍처가 아닌 것

 

E. DDD에서 사용되는 레이어드 아키텍처

 

*이어보기: DDD관점에서의 레이어드 아키텍처

 

 

출처

Layered Architecture by Science Direct

Layered Architecture and Service Based Development - Why not use it by Johnny Willer

Software Architecture Patterns by Mark Richards

도둑탈을 쓴 애쉬님의 [소프트웨어 아키텍처] 레이어드 아키텍처(Layered Architecture)란?

Solomon Maeng님의 Layered Architecture Deep Dive

Hudi님의 계층화 아키텍처(Layered Architecture)

Hexagonal Architecture Explained by Arho Huttunen 

 

Anemic Domain Models by John Mikael Lindbakk

Anemic Domain Model by Martin Fowler

DDD지향 마이크로 서비스 디자인 by Microsoft