본문 바로가기
Book

[독서 기록] 도메인 주도 설계로 시작하는 마이크로서비스 개발, 3장

by Renechoi 2023. 5. 30.

 

 
도메인 주도 설계로 시작하는 마이크로서비스 개발
넷플릭스, 우버, 아마존, 쿠팡 등의 대규모 인터넷 서비스를 제공하는 회사들의 애플리케이션은 어떤 구조로 만들어졌을까? 가상화되고 유연하게 변경되는 클라우드 인프라에 최적화된 애플리케이션 형태는 무엇일까? 이러한 질문의 해답이 되는 애플리케이션 형태가 바로 마이크로서비스이며, 마이크로서비스는 클라우드 환경에서 가장 진화된 애플리케이션 형태다. 이 책은 마이크로서비스 개발에 입문하고자 하는 분들을 위해 전반적인 마이크로서비스 아키텍처의 개념과 주요 패턴들을 소개하고 마이크로서비스 개발 방법으로 가장 주목받는 도메인 주도 설계를 살펴본다. 특히 도메인 주도 설계의 업무 분석 및 설계 기법인 이벤트 스토밍을 통해 업무를 빠르게 분석하고 마이크로서비스를 도출 및 설계하는 방법을 소개한다. 이 책은 초심자도 쉽게 이해할 수 있게 마이크로서비스의 전반적인 개념을 설명한 후 실제 마이크로서비스 개발을 위한 아키텍처 정의, 마이크로서비스 도출, 도메인 모델 설계, 구현, 빌드 및 배포와 같은 마이크로서비스 개발 활동들을 단계별로 알아본다.
저자
한정헌, 유해식, 최은정, 이주영
출판
위키북스
출판일
2021.04.08

 

 

 

로버트 C. 마틴은 <클린 아케틱처>에서 소프트웨어의 가치는 행위 가치와 구조 가치로 나뉘고, 소프트웨어를 정말로 부드럽게(soft) 만드는 것은 구조 가치라고 언급한 바 있다. 여기서 행위 가치는 소프트웨어의 기능을 말하며, 구조 가치는 소프트웨어 아키텍처를 말한다. 그는 토끼와 거북이의 경주를 예로 들며 가장 빨리 가는 방법은 제대로 가는 것이며, 코드와 설계의 구조를 깔끔하게 만들려는 생각을 하지 않고 기능 구현만 목적으로 삼으면 소프트웨어가 엉망이 된 상황에 대처하는 데 더 많은 비용이 든다는 점을 강조했다.

- 82p 

 

 

관심사의 분리-> 

모듈화 및 계층화도 이 같은 원칙에 기인한다. 특히 비즈니스를 표현하는 비즈니스 롲기 영역과 기술 문제를 처리하기 위한 기술 영역은 철저히 분리하는 것이 좋다. 

- 83p 

 

 

데이터베이스 중심 아케텍처란 특정 관계형 데이터베이스에 의존한 데이터 모델링을 수행한 다음 이 물리 테이블 모델을 중심에 두고 애플리케이션을 구현하기 위한 사고를 하는 방식이다. 이 같은 구조는 일반적으로 그림 3.1과 같은 모습을 띈다. 

 

 

-85 p

 

 

일반적으로 스프링 프레임워크를 활용한다면 컨트롤러, 서비스, DB I/O, DTO 로 구성되고, 데이터 처리는 SQL 매핑 프레임워크인 마이바티스를 사용한다. 이러한 구조에서 일반적으로 비즈니스 로직은 서비스에 존재해야 한다고 말하지만 서비스에 존재하게 될 로직은 흐름 제어 로직 밖에 없다. 그 밖의 비즈니스 개념과 규칙들은 앞에서 언급한 사례처럼 테이블과 SQL 질의에 존재한다.

- 85p 

 

-> 대부분의 성능을 데이터베이스에 의존 

-> 서비스의 비즈니스 개념과 규칙이 대부분 데이터베이스에 표현되기 때문에 애플리케이션은 별로 할 일이 없다 

 

 

티어는 물리적인 장비나 서버 컴퓨터 등의 물리층을 의미하고 레이어는 티어 내부의 논리적인 분할을 의미한다.

- 87p 

 

 

 

레이어드 아키텍처 패턴의 전형적인 유형: 프레젠테이션 > 비즈니스 로직 > 데이터 엑세스의 3계층 

- 87p 

 

 

 

레이어드 아키텍처 규칙

- 상위 계층이 하위 계층을 호출하는 단방향성을 유지한다.

- 상위 계층은 하위의 여러 계층을 모두 알 필요 없이 바로 밑의 근접 계층만 활용한다.

- 상위 계층이 하위 계층에 영향을 받지 않게 구성해야 한다.

- 하위 계층은 자신을 사용하는 상위 계층을 알지 못하게 구성해야 한다.

- 계층 간의 호출은 인터페이스를 통해 호출하는 것이 바람직하다. 

- 88p 

 

 

 

 

일반적인 레이어드 아키텍처에서 OCP가 위배되는 까닭은 모든 계층이 각기 자신이 제공하는 기능에 대한 추상적인 인터페이스를 직접 정의하고 소유하고 있는 구조이기 때문이다. 이런 구조에서는 제어 흐름이 상위 계층에서 하위 계층으로 흐르게 되고, 이에 따른 소스코드의 의존성은 제어 흐름의 방향대로 따를 수밖에 없다.

- 89p 

 

 

 

헥사고날 아키텍처는 앨리스테어 콕번이 제시한 아키텍처로서 '포트 앤드 어댑터 아키텍처(ports and adapters architecture)'라고도 한다. 그림 3.7을 통해 간단히 살펴보면 헥사고날 아키텍처에서는 고수준의 비즈니스 로직을 표현하는 내부 영역과 인터페이스 처리를 담당하는 저수준의 외부 영역으로 나눈다. 내부 영역은 순수한 비즈니스 로직을 표현하는 기술 독립적인 영역이다. 그리고 외부 영역와 연계되는 포트를 가지고 있다. 외부 영역은 외부에서 들어오는 요청을 처리하는 인바운드 어댑터(inbound adapter)와 비즈니스 로직에 의해 호출되어 외부와 연계되는 아웃바운드 어댑터(outbound adapter)로 구성된다.

 

- 91p 

 

 

헥사고날 아키텍처의 가장 큰 특징은 고수준의 내부 영역이 외부의 구체 어댑터에 전혀 의존하지 않게 한다는 것이다. 이를 가능하게 하는 것이 내부 영역에 구성되는 포트다.

- 92p 

 

 

 

클린 아키텍처 

 

 

-93p 

 

 

 

https://learn.microsoft.com/ko-kr/dotnet/architecture/microservices/multi-container-microservice-net-applications/microservice-application-design

 

 

내부 영역에서는 맨 안쪽에 도메인이 존재하고 도메인을 서비스가 감싼다. 도메인에는 핵심 비즈니스 개념과 규칙을 구현하며, 서비스에서는 도메인을 호출해서 업무를 처리하는 절차를 기술한다. 또한 외부 영역과 연계하기 위해 서비스 인터페이스를 보유한다. 서비스 인터페이스는 외부에서 내부 영역을 사용할 수 있도록 API를 제공하고 서비스가 이를 구현한다.

 

- 96p 

 

 

 

서비스와 도메인은 클린 아키텍처의 유스케이스와 엔티티의 역할과 같다. 도메인은 비즈니스 개념을 표현하고 서비스는 도메인을 활용해 시스템 흐름 처리를 수행한다. (서비스는 활동이나 행위를 처리한다. 도메인 주도 설계에선은 서비스를 도메인의 활동이나 행위를 처리하는 도메인 서비스와 사용자의 목적을 달성하게 하는 유스케이스를 처리하는 애플리케이션 서비스로 구분하기도 하는데, 여기서는 애플리케이션 서비스에 가깝다.) 

- 97p 

 

 

 

트랜잭션 스크립트 패턴

트랜잭션 스크립트 패턴에서는 비즈니스 갠며을 표현하는 도메인 객체가 그림 3.11의 우측과 같이 행위를 가지고 있지 않다. 따라서 모든 비즈니스 행위, 즉 무엇인가를 수행하는 책임은 서비스에 있다. 서비스가 비즈니스 절차에 따라 절차적으로 도메인 객체를 이용해 모든 처리를 수행한다. 이런 방식에서는 시간이 지남에 따라 서비스가 비대해지고 도메인 객체는 점점 정보 묶음의 역할만 수행하게 될 뿐이다.

 

또한 서비스는 유스케이스 처리의 단위이고 대부분의 비즈니스 로직 처리가 서비스에서 이뤄지므로 비슷한 유스케이스의 경우 서비스에 중복되는 코드가 계속 생겨날 수 있다.

 

 

- 98p 

 

 

트랜잭션 스크립트 패턴은 절차식 프로그래밍 방식과 같기 때문에 객체지향 지식이 없어도 일반적으로 쉽게 이해할 수 있는 구조이고 기존 데이터베이스 중심 아키텍처에 익숙하다면 더 쉽게 적응할 수 있다. 

- 99p 

 

 

 

도메인 모델 패턴은 도메인 객체가 데이터뿐만 아니라 비즈니스 행위를 가지고 있으며, 도메인 객체가 소유한 데이터는 도메인 객체가 제공하는 행위에 의해 은닉된다.

 

도메인 객체는 각 비즈니스 개념 및 행위에 대한 책임을 수행하고, 서비스는 비즈니스 유스케이스를 구현하기 위해 서비스의 행위를 도메인 객체에 일부분 위임해서 처리한다. 

 

서비스의 책임들이 모데인으로 적절히 분산되기 때문에 서비스가 비대해지지 않고 서비스 메서드는 단순해진다. 도메인 모델 패턴의 도메인 모델은 객체지향 설계의 객체 모델이다. 거대한 서비스 클래스 대신 각기 적절한 책임을 가진 여러 클래스로 구성되므로 이해하기 쉽고 관리 및 테스트하기 쉽다. 여기서 더 진화해서 도메인 주도 설계의 애그리거트(Aggregate) 패턴을 적용할 수 있는 구조다.

 

- 99p 

 

 

 

최상위에 존재하는 엔티티(Root Entity)를 중심으로 갠며의 집합을 분리한 것이 애그리거트 패턴이다.

- 100p 

 

 

 

 

 

애그리거트 패턴에서는 이처럼 애그리거트를 한 단위로 일관되게 처리하기 위해 다음과 같은 규칙을 부여한다.

- 애그리거트 루트만 참조한다.

- 애그리거트 내 상세 클래스를 바로 참조하지 않고 루트를 통해 참조해야 한다. 수정할 때도 마찬가지다.

- 애그리거트 간의 참조는 객체를 직접 참조하는 대신 기본 키를 사용한다. 

- 기본 키를 사용하면 느슨하게 연관되고 수정이 필요하지 않은 애그리거트를 함께 수정하는 실수를 방지한다.

- 하나의 트랜잭션으로 하나의 애그리거트만 생성 및 수정한다. 

 

-101p 

 

 

 

외부 영역 - 세부사항 

 

- API 퍼블리싱 어댑터 

- API 프락시 어댑터 

- 저장소 처리 어댑터 (SQL vs. OR) 

- 도메인 이벤트 발행 어댑터 : 도메인 이벤트는 어떤 사건에 따른 상태의 변경 사항을 말하는데, '주문됨', '주문 취소됨' 등의 명칭을 갖는 클래스로 구현되며, 컨슈머에게 전달 되기 위해 도메인 이벤트 발행 어댑터를 통해 발행된다. 애그리거트 패턴을 적용할 경우 도메인 이벤트는 애그리거트에서 발생한 사건이 된다. 

- 도메인 이벤트 핸들러

 

- 102 ~ 104p 

 

 

가장 빨리 가는 방법은 제대로 가는 것이다. 처음에는 오래 걸리고 힘들고 불편하겠지만 꼼수를 쓰지 않고 원칙을 준수하는 것이 길게 보면 가장 빠른 법이다.

 -105p 

 

 

 

 

 

반응형