caffeine-library / random

스터디 진행 외에 공유하고 싶은 주제에 대해 얘기합니다
0 stars 0 forks source link

DDD와 Hexagonal Architecture는 어떤 차이가 있을까요? #21

Open wooyounggggg opened 2 years ago

wooyounggggg commented 2 years ago

팀에서 Hexagonal Architecture에 관한 언급이 있어, 다시 한번 살펴보게 되었는데 개념을 다시 봐도 도메인 모듈을 보호한다는 목적의 느낌이 비슷하다는 생각이 드는 것 같습니다.

구체적으로 두 개념의 차이가 무엇인지 알고 계시다면 답변해주시면 감사하겠습니다.

binchoo commented 2 years ago

참고 글

Common Language 요구사항에 대한 DDD의 접근

건국대학교 메일이 있으시면 오라일리 컨텐츠를 항시 열람 가능하십니다.

Hexagonal Architecture 고안자 원본

육각 아키텍처 관련하여서, 인터넷에 나도는 글 보다는, 고안자 알리스테어 콕번 씨의 생각을 우선 읽는 게 좋을 듯 합니다.

Hexagonal Architecture 고안자의 강연들

목소리가 잘 안 들리는 영상도 있으니 유념 바랍니다.

이와 같이 동일한 컨텐츠를 여러분과 함께 보고, 여러분의 생각으로 한 줄 요약을 듣고 싶습니다.

DDD

Common Language

개발 팀과 비즈니스 이해관계자들은 비즈니스 가치를 창출하기 위해 소통합니다. 그러다가 비지니스에 등장하는 용어 · 역할 등에 이해의 차이가 생기면, 상호 소통과 협업이 긴밀하게 이뤄질 수 없고, 잠재적으로 시스템에 오류를 야기시키게 됩니다.

그래서 명확하게 비즈니스 엔터티를 정의하고 관계성을 찾으려는 움직임이 이어졌습니다.

"개발 & 비즈니스 담당자 간 서로를 잘 이해하고 원할히 소통하고 싶다"는 요구사항을 해소하기 위해, Common Language 라는 전술을 택할 수 있겠습니다. 실무적으로 말하자면, 잘 정의된 · 명확한 · 오해를 야기하지 않는 데이터 모델을 작성하고, 이를 중심으로 이해 당사자 간 소통을 하는 것이지요. (DB 시간에 배운 데이터 모델링의 그 데이터 모델 맞습니다.)

DDD는 이러한 공용어를 제공하는 접근법 중 하나입니다.

Common Language로서의 DDD

DDD는 '도메인 모델 속 핵심 비즈니스 개념'을 '구현'에 깊이 연결시키는 접근법으로 공용어를 제공합니다.

DDD의 핵심 원칙

  1. 프로젝트의 관심사는 도메인도메인 로직이다.
  2. 도메인 모델에 기반하여 설계한다.
  3. 도메인 전문가기술 전문가반복적으로 문제의 핵심을 함께 정제한다.

DDD의 핵심 개념

  1. Bounded Context - 도메인은 크기 때문에 여러 서브 도메인(Sub-Domain)으로 분할됩니다. 서브 도메인은 Bounded Context를 제공합니다. 데이터 모델 · 정의 · 관계의 상세 내용이 서브 도메인 하에서 정립되며, 서브 도메인을 담당하는 컴포넌튼는 이곳의 모델을 따라야하기 때문에 (영어로 bounded to 겠죠) Bounded Context를 제공한다는 이야기 입니다.

  2. Ubiquitous Language - 어디에서나 존재하는 언어? 무슨 뜻일까요.

    이는 개발 팀 & 비즈니스 팀 모두 Bounded Context 속에 국한된 언어로만 소통해야 한다는 의미로서, 코드 및 기타 모든 산출물은 모두 Bounded Context에 정의된 언어를 써야함을 말합니다. 서브 도메인에 존재하는 언어 = 어디서든 존재하는 언어, 말 그대로네요.

이 단락은 'Common Language로서의 DDD' 이므로 엔터티 · 밸류-오브젝트 · 어그리게이트 · 레포지토리 등의 개념을 등장시키지 않았습니다.

DDD에 대한 나의 요약

DDD는 '핵심 도메인 개념'에 기반해 공용어를 제공합니다. 저의 언어로 한 줄 표현하자면.

DDD는 Bounded Context 하의 도메인 모델 · 정의 · 관계를 식별하고, 이를 공용어로 하여 '핵심 비즈니스 개념'을 '구현'에 깊이 연결시키는 접근법이다.

품질 시나리오 - 개발 & 비즈니스 이해관계자가 서로 잘 이해하고 원할히 소통하고 싶다.

태틱 - 데이터를 Bounded Context하에서 모델링 하고 이를 공용어로 삼는다.

image

Hexagonal Architecture

고안자의 아이디어에 대한 나의 요약

맨 앞에 링크를 몇 개 드렸었는데요. 한 번 읽어주시면 좋을 듯 합니다. 알리스티어 콕번 씨는 전형적인 (UI - 서비스 - DAO) 3계층 아키텍처에 관련해서 신선한 관점을 제시했습니다.

그 내용을 제가 어떻게 이해했나면⋯

관점의 변화: 시스템을 계층형이 아닌, 내부-외부의 관점으로 바라보기.

Example① 고전적인 터미널 시스템이 있다. 여러 사람이 원형으로 빙 둘러쌓아 자기 화면을 보고 작업을 할 수 있다. 사람 A가 이 시스템의 왼편에 앉아서 "Hello"라는 문구를 입력했다. 그러자 반대편에 앉아 있던 사람 B의 화면에 "메시지가 도착했습니다: Hello" 라는 팝업 창이 전시되었다.

Example② 어떤 전형적인; UI 및 DB가 있는 시스템이 있다. 이 시스템에 A라는 유저가 "Hello"라는 문자열을 입력했고 이는 곧 DB의 테이블에 "A | Hello"라는 자료로 쓰여졌다.

image

설명

예시를 보시면 아시겠지만, 알리스티어 콕번은 시스템을 계층형이 아닌 내부-외부 구조로 바라봅니다.

시스템이 가운데에 놓이고, 이를 이용하는 녀석들이 빙 둘러 앉아 있는 대칭적 육각형을 그려내었죠. 그가 시스템을 원으로 표현하지 않고 육각형으로 표현한 데도 원본 글에 이유가 다 나옵니다.

Each face of the hexagon represents some "reason" the application is trying to talk with the outside world. This is why it is concentric hexagons and not concentric circles.

예를 들어, 데이터 퍼시스턴스를 이유로 한 면을 그려낼 수 있겠고, 외부 API 호출을 이유로 또 다른 면을 그릴 수도 있겠네요.

image

한편, 그는 시스템을 구동하는 Driving을 왼편에 그리고, 시스템에 의해 구동당하는 Driven들을 오른쪽에 배치했습니다. 각 Driving 혹은 Driven과 접하는 시스템 컴포넌트는 Ports라고 불립니다. TCP의 포트와 비슷하기 때문에 붙여진 이름이랬나...?

아무튼 Ports를 제공하는 것은 시스템입니다. 시스템 밖을 빙 둘러앉은 컴포넌트들은 반드시 시스템이 공개한 Port와 호환되는 Adapter를 가져야만 시스템과 소통할 수 있습니다.

의존성이 '외부->시스템의 포트' 방향으로 향하므로, 내부 코드는 외부의 Techincal-Specific한 요인에 영향을 받지 않습니다.

img

육각 아키텍처는 포트와 어댑터 아키텍처로도 불리지요. 관련하여 보기 좋은 그림 하나를 더 첨부합니다.

DDD와의 접점에 대한 나의 생각

Common Langugage 요구사항에 대한 DDD의 접근법이라는 주제로 앞서 단락을 전개했는데요. 같은 맥락에서 DDD와 육각 아키텍처의 관계를 생각해 보고자 합니다.

DDD의 원칙에 따르면 서브 도메인을 담당하는 컴포넌트가 사용할 언어는 Bounded Context를 벗어나지 않는 Ubiquitous Language여야 합니다. 하지만 실제 Spring Data JPA로 개발해 보면 이 원칙을 지킬 수 있었나요? 그렇지 않습니다.

계층형 아키텍처의 트레이드-오프

계층형 아키텍처는 레이어 별로 관심사를 분리하고, 인접한 계층끼리 인터페이스를 통해 협력하도록 하여, 시스템을 단순하게 구성할 수 있게 합니다. 계층형 아키텍처의 특이사항은, 상위 레이어가 하위 레이어를 의존한다는 점입니다.

따라서 도메인 로직과 엔터티는 하위 레이어에 놓인 DB-특화된 코드에 의존하므로 오염될 수 밖에 없으며, 이는 도메인 개발에 집중할 수 없게 만듭니다.

image

Entity 혹은 Service 레이어에 놓인 자바 클래스 코드를 열어 보십시오. Repository 레이어의 인터페이스 (findAll() 처럼)에 의존할 뿐만 아니라 JPA 명세 라이브러리를 마구 가져와서 어노테이션을 덕지덕지 붙이고 있습니다.

public class Singer implements Serializable { //
    @ManyToMany
    @JoinTable(name = "singer_instrument",
               joinColums = @JoinColumn(name = "singer_id"),
               inverseJoinColumns = @JoinColumn(name = "instrument_id"))
    public Set<Instrument> getInstruments() {
        return this.instruments;
    }
}

DDD의 Common Language 준수에 있어 육각 아키텍처의 적합성

육각 아키텍처는 외부와의 상호작용에 있어서 항상 내부 중심적인 시나리오를 구성합니다.

따라서 육각 아키텍처 내부에 도메인과 도메인 로직을 두면 도메인이 외부에 침해받지 않습니다. DDD의 Unbiquitous Language 사용 원칙을 달성하는 데 도움을 주기 위해, 자연스레 육각 아키텍처 채택이 발생했을 것이라 생각해 봅니다.

구현 경험 공유

육각 아키텍처를 사용한 프로젝트 구현 경험을 공유합니다. https://github.com/binchoo/PaimonGanyu/tree/master/PaimonGanyu

제시한 깃허브는 카카오톡 챗봇 프로젝트인데요. 전반적인 코드 베이스가 육각 아키텍처를 기반해 구현되었습니다.

image

추신

"나의 생각 · 요약"이라고 덧붙이는 것들은, 자료를 보며 소화한 내용을 본인의 언어로 제시함을 의미합니다.

어디 교과서에서 발췌해 온 내용이 아니기 때문에 공신력이 없으므로, 유념하시어 크로스 체크하시는 것이 좋을 듯 합니다.

혹은 그에 관해 의견을 덧붙여 주신다면 기쁘겠습니다.

wooyounggggg commented 2 years ago

제가 DDD는 무엇인가?라고 질문할 때 머릿속에 그려지던 피상적인 이미지가 사실은 육각형 아키텍처에 가까운 모습이었던 것 같네요.

댓글을 남기는 시점에서는 아직 첨부해주신 글들은 읽어보지 못해서 생각이 완전히 정리되진 않았지만, DDD와 Hexagonal Architecture를 아래와 같이 이해할 수 있었습니다.

DDD

도메인 이해 관계자들이 모두 참여할 수 있으며, 동시에 구현에 동떨어지지 않는 도메인 중심의 프로젝트 진행 지침

Hexagonal Architecture

도메인 모듈을 보호하기 위한 설계 방법 중 하나로, 특히 개발의 관점에서 프로젝트를 도메인 중심적으로 풀어나가기 위한 설계 방법

정도로 정리가 되는 것 같습니다. 첨부된 글도 읽어보고, 생각 정리가 조금 더 되면 댓글에 추가적으로 내용 남기도록 하겠습니다.

wooyounggggg commented 2 years ago

Netflix - Ready for changes with Hexagonal Architecture

넷플릭스에서 Hexagonal Architecture 적용기를 올려주어, 글을 공유합니다.

Anti-corruption Layer(손상 방지 계층)

DDD 서적에서 Anti-corruption Layer를 언급합니다. 해당 내용을 읽을 당시에는 알지 못 했는데, Hexagonal Architecture를 이해하고 보니, Port와 Adapter를 타고 Application Service를 거쳐 도메인 내부로 진입하기 직전까지가 Anti-corruption Layer의 모습 중 하나라고 이해할 수 있었습니다.