Domain Driven Design (DDD), history of architecture, OOP and Hexagonal Architecture
이전에 정리했었던 내용들이 사라져서, 앞으로는 이 포스팅에 계속해서 덧붙일 예정
https://steemit.com/kr/@frontalnh/domain-driven-design
Domain Driven Design 이란 무엇인가? — Steemit
Domain Driven Design 이란 무엇인가 먼저, 도메인이란 무엇일까요 도메인의 사전적 의미는 “정보와 활동의 영역” 을 말하며, 흔히 프로그래머들에게는 어플리케이션 내의 로직들이 관여하는 정보와… by frontalnh
도메인 주도 개발
최초의 도메인 주도 개발이라는 내용을 접했을 땐, 이 복잡하게 얽혀있는 애플리케이션을 어떻게 관리하기 편하게 구성하느냐를 고민하는 주제로 생각했었다.
생소 했던 Domain 이라는 의미, 어떤 목적과 뜻으로 이렇게 생각했는지를 최초의 DDD 책을 읽고나서부터는 이해하기 힘들었었다.
하드웨어 발전이 빠른 속도로 진행되다보니, 과거에 있었던 물리적인 제약사항들이 해결되어가면서 개발언어에서도, 아키텍처에서도 변화가 생겼을 거라 생각된다.
개발언어에서도 동시성 이슈를 해결하기 위해서 블록킹 논블록킹 형태로 작성하던 형태도 하드웨어 발전으로 인해 낭비라 여겨졌고, 논블록킹 형태의 기능들이 많이 만들어졌다.
이러한 연유로 개발 언어의 방향성이 변경되었고, 모노리틱한 구조의 애플리케이션 구조도 변화가 생기지 않았나 생각 된다.
모노리틱한 구조를 변경하는 경우 DDD라는 개념을 모를때는 분산서버로 구성해야겠다고 생각했다. 분산서버 형태는 작업을 나누어서 병렬적으로 처리하고 원하는 결과를 획득하는 구조로 구성해야 되고, 각각 적당한 정도의 목적으로 나뉘어져야 한다고 생각했다.
이때, 이런 개념을 적용해서 구성했던 서버는 게임서버였고, 분산된 서버간 통신방법에 대해 고민을 하게 되었다.
(1) 최대한 적은 패킷으로 통신하는 방법은 무엇일까?
(2) 부하를 분산시키는 방법은 무엇일까?
(3) 유실되지 않고 장애가 발생되더라도 회복할 수 있는 방법으로 구성할 수 있는 것이 무엇일까?
크게 3가지로 압축해서 고민했던 것 같다.
(1) 최대한 적은 패킷 사이즈로 통신하는 방법은 gRPC를 이용해서 통신하는 것으로 정해졌었고, 내가 오기전에 이미 적용되어 있었다.
이때 내가 느낀 경험으로는 내가 과연 이런 부분까지 세밀하게 생각해본적이 없었기 때문에 놀랐었고, 무언가 엔지니어로서는 고민을 했었어야 하는 것을 느꼈다.
(2) 부하를 분산시키는 방법에 대해서는 서버 구성을 분산서버로 구성하고, LB를 이용하여 Round Robin을 할 수 있도록 구성하는 것과, Scale In, Scale Out등으로 해결할 수 있다고 생각했습니다. 이런 애플리케이션의 서버 구성과 마찬가지로, 3rd Party 로 구성한 부분들도 이런 고민을 하게 되었다.
(3) 유실되지 않고 장애가 발생되더라도 회복할 수 있는 방법으로 구성할 수 있는 것이 무엇일까? **http 통신 구간별 복구 정책을 고민하기 시작했고, 로그를 남겨서 문제가 발생될 경우 회복을 하겠다 이런 용도의 생각을 많이 했던 것 같다. 하지만 매번 번거롭고 스크립트를 작성하거나 조회해서 복구 해야 되는 복구 정책을 만들어야 하는 것이 여간 까다로운 작업이었다. Zookeeper를 이용하여 서버 모니터링을 하고, 특정 서버가 문제가 생기면 자동적으로 복구를 하는 방법등 많은 논의를 거쳤던 것 같다. 그러던 도중 **Oracle에서 Java 8의 소개를 해주는** **컨퍼런스에 참여하게 되었고, 그곳에서 Kafka를 이용해서 구성하는 내용을 알게 되었다. 이미 MQ 종류 RabbitMQ, zeroMQ의 MQ를 확인하였지만 똑부러진 해결책이 되지 못하고 있던 상태에서 Kafka는 우리가 목표로 세웠던 목적에 부합하는 기술이라 생각 되어서 고민하기 시작했다. (2)에서 고민했던 부하 분산을 효율적으로 관리할 수 있는 Cluster 구성도 가능했고, 유실되지 않고 사용할 수 있는 기술이라 판단되어 도입했다.
이러한 배경에 DDD도 포함되어 입혀진다면, 기술 언어에서 이야기 하는 OOP의 5원칙(SOLID)를 지킬 수 있고, 유지보수를 용이하게 할 수 있는 방법이 무엇인지 해소 시켜주는 규약이라 생각했다.
도메인이라는 정의를 찾아보면 문제의 영역 이라는 난해한 표현으로 이루어져있는데, 개인적으로 아래와 같이 생각한다.
도메인의 정의는 비즈니스와 연관이 있고 알맞는 크기로 이루어진 독립적인 단위
이렇게 생각하게 된 이유는 일하게 되는 조직의 구조와 유사하고 연관된 이해관계자가 곧 도메인과 밀접한 사람이고, 이런 사람들이 도메인 전문가가 된다고 생각했기 때문이다. 곧, DDD를 하게되는 순간 일정한 크기의 도메인을 나누게되고, 연관있는 사용자들과 밀접하게 논의하면서 빠르게 문제를 해결할 수 있는 방법이라고 생각했다.
이러한 이유로, 곧 작은 단위의 애플리케이션 서버(MSA)를 구성할 수 있고, 변화에 빠르게 대응할 수 있으며, 다른 도메인과는 연관성이 적어 맡은 도메인을 집중해서 발전시킬 수 있고, 맡은 도메인 지식을 쌓을 수 있다.
따라서, 이러한 조직 구조를 만드는 것에 있어서 DDD가 적합해보이고, 애자일에서 이야기하는 팀 구조와도 적합하다고 생각되었다.
아키텍처, 개발언어, 팀 구조, DDD 로 인해 좀더 발전적인 방향으로 나아갈 수 있었다.
이후 Hexagonal Architecture를 접하고나서, 개인적으로 구현 관점에서의 오랫동안 해소할 수 없던 영역에 대해서 해소 할 수 있었다.
Hexagonal Architecture의 구조를 보면 Port&Adapter 패턴을 적용하는 구성으로 예전에 특정 컬럼에서 내용을 접할 수 있었다.
(port adapter 내용이 포함된 link)
지속 가능한 소프트웨어 설계 패턴: 포트와 어댑터 아키텍처 적용하기
들어가며 헥사고날 아키텍처(Hexagonal Architecture)로 더 잘 알려져 있는 포트와 어댑터 아키텍처(Ports and Adapters Architecture)는 인터페이스나 기반 요소(infrastructure)의 변경에 영향을 받지 않는 핵심 …
앞서 oop에서 이야기 했던 solid를 지킬 수 있는 방법과 spring framework에서 애플리케이션을 개발할 때, 이미 이러한 개념들이 모두 녹일 수 있는 상태이지만 좀더 쉽게 다가갈 수 있는 방법이 헥사고날 아키텍처를 이용해서 작성하는 것이였다.
맡고 있는 서비스를 계속해서 발전시켜야하고, 발전 시키기 위해 유연하게 작성하는 방법을 고민하는 것이 바로 설계 패턴으로 인식 된다.
헥사고날 아키텍처를 이용하는 경우 또다시 구조나 코드 작성하는 방법을 각자 해석한 방법으로 바라보기 시작할 수 있는데 이런 부분에 대해서는, 개인적으로 쌓아둔 경험과 직관으로 풀어나가는 것이 좋아보인다. 왜냐하면 정답은 없고, 정답을 찾으려고 하다보면 계속해서 시간이 지나가고 답답할 수 있기 때문이다. (매번 찾을 때 마다 양식이 다른 것도 있다.)

위의 그림처럼 Domain(비즈니스 영역)으로 접근하는 곳을 input port로 제한하고, 비즈니스 로직 이후에 외부로 나가는 부분을 output port로 관리한다.
input에 해당되는 usecase는 interface로 구성되어 있고, output port에 해당되는 port 역시 인터페이스로 되어 있다. 구성되어 있는 input port와 output port들을 확인하면서 담당하고 있는 domain에서 어떤 일을 담당하는지 가시적으로 확인할 수 있다.
또한 각각의 interface는 1가지 구현체만 가질 수 있도록 만들기 때문에 단일책임원칙도 벗어나지 않게 지킬 수 있다고 생각한다. 이 두가지를 행하는 순간 이미, 인터페이스 분리 법칙, 단일책임원칙을 지키고 있는 상태가 된다. 또한 구현체를 바라보지 않기 때문에 의존성 역전의 원칙도 포함 할 수 있다고 생각한다.
이러한 이유로, 코드의 유지보수성, 확장성이 증가되고 특정 이해도를 갖지 않아도 어느정도 룰을 형성 하기 때문에
안정적인 상태로 유지될 것이라 생각된다.