본문 바로가기
책 소개

[요약] 도메인 주도 설계로 시작하는 마이크로서비스 개발

by Devsong26 2024. 7. 16.
반응형

아마존 비즈니스 민첩성의 비밀

  • 스케일업: 기존 시스템 자체의 물리적 용량을 증가시켜 성능을 높이는 방법
  • 스케일 아웃: 기존 시스템과 용량이 같은 다수의 장비를 병행 추가해서 가용성을 높이는 방법
  • 클라우드 친화 애플리케이션: 큰 덩어리로 클라우드 환경에 올라갈 수 있게만 한 애플리케이션
  • 클라우드 네이티브 애플리케이션: 독립적으로 분리되어 배포될 수 있는 조각으로 구성된 애플리케이션을 클라우드 인프라에 가장 어울리고 효과적이라는 의미
  • 모노리스: 하나의 단위로 개발되는 일체식 애플리케이션
  • 마이크로서비스는 서버 측이 여러 개의 조각으로 구성돼 각 서비스가 별개의 인스턴스로 로딩된다.
  • 단순히 기능을 하향식 분해해서 설계해 나가는 구조적 방법론
  • 객체 단위로 모듈화하기 위한 객체지향 방법론
  • 모듈화의 단위가 기능별로 재사용할 수 있는 좀 더 큰 컴포넌트가 되는 CBD(Component Based Development)
  • 컴포넌트를 모아 비즈니스적으로 의미 있고 완결적인 서비스 단위로 모듈화하는 SOA(Service Oriented Architecture)
  • 마이크로서비스 기반으로 시스템을 개발하는 아키텍처 및 개발 방식을 마이크로서비스 아키텍처
  • SOA는 구체적이지 않고 이론적이며, 실제 비즈니스 성공 사례가 많지 않았다.
  • MSA는 클라우드 인프라 기술의 발전과 접목되어 아마존과 넷플릭스에 의해 구체화되고 비즈니스 성공 사례로 널리 공유된 바 있다.
  • 폴리글랏: 특정 서비스를 구축하는 데 사용되는 언어나 저장소를 자율적으로 선택할 수 있는 방식
  • 마이크로서비스 팀의 개발은 비즈니스의 갑작스런 트렌드 변화에 유연하게 대처해야 하고 개발뿐만 아니라 운영을 포함한 소프트웨어의 전체 생명주기를 책임져야 한다.
  • 개발과 운영을 동시에 수행하는 데브옵스
  • 빌드/배포 파이프라인은 일반적으로 '소스코드 빌드' -> '개발 환경 배포' -> '스테이징 환경 배포' -> '운영 환경 배포'로 구성된다.
  • 마이크로서비스는 데이터 일관성 문제를 해결하기 위해 두 서비스를 단일 트랜잭션으로 묶는 방법이 아닌 비동기 이벤트 처리를 통한 협업을 강조한다.
  • 결과적 일관성: 두 서비스의 데이터가 일시적으로 불일치하는 시점에 있고 일관성이 없는 상태지만 결국에는 두 데이터가 같아진다는 개념
  • 마이크로서비스가 추구하는 다른 방법은 각 트랜잭션을 분리하고 큐(Queue) 메커니즘을 이용해 보상 트랜잭션을 활용하는 방법이다.
  • 내결함성(fault tolerance): 시스템은 언제든 실패할 수 있으며, 실패해서 더는 진행할 수 없을 때도 자연스럽게 대응할 수 있도록 설계해야 함
  • 서킷 브레이커 패턴은 회로 차단기처럼 각 서비스를 모니터링하고 있다가 한 서비스가 다운되거나 실패하면 이를 호출하는 서비스의 연계를 차단하고 적절하게 대응하는 것을 말한다.

 

MSA의 이해

  • 응답성(Responsible): 사용자에게 신뢰성 있는 응답을 빠르고 적절하게 제공하는 것을 의미한다.
  • 탄력성(Resilient): 장애가 발생하거나 부분적으로 고장나더라도 시스템 전체가 고장나지 않고 빠르게 복구하는 능력을 의미한다.
  • 유연성(Elastic): 시스템의 사용량에 변화가 있더라도 균일한 응답성을 제공하는 것을 의미하며, 시스템 사용량에 비례해서 자원을 늘리거나 줄이는 능력을 말한다.
  • 메시지 기반(Message Driven): 비동기 메시지 전달을 통해 위치 투명성, 느슨한 결합, 논블로킹 통신을 지향하는 것을 의미한다.
  • 리액티브 시스템이 신뢰성 있는 응답을 빠르게 제공하고 부분적 장애가 빨리 복구되고 수요 증가에 탄력적으로 대응하기 위해서는 시스템 자체가 변화와 확장에 언제든지 대응할 수 있는 아키텍터 유연성을 갖추는 것이 필수다.
  • 메시지 기반 특성은 마이크로서비스 간의 의존성을 줄이는 중요한 특징이 된다.
  • 최근에 하나의 벤더에 의존하거나 직접 구출할 필요가 적어졌다. 왜냐하면 클라우드 환경하에서 사용되는 오픈소스 또는 오픈소스를 기반으로 한 사용 제품들이 이전의 유명 벤더의 제품군 만큼이나 품질이 높아지고 다양한 기능을 지원하면서 서로 다른 오픈소스 제품 간에도 충분한 호환성을 제공하기 때문이다.
  • MSA 외부 아키텍처: 인프라 영역과 플랫폼 영역, 애플리케이션 영역에 있는 구성요소 및 그것들의 관계를 정의하는 것
  • MSA 내부 아키텍처: 비즈니스가 실행되는 비즈니스 애플리케이션, 즉 각 마이크로서비스의 내부 구조도 정의
  • 아키텍처 스타일(또는 아키텍처 패턴): 어떤 문제 영역에 대해 여러 사람들에 의해 검증되어 정리된 유용한 해법
  • MSA 구성요소 및 패턴의 유형
    • 인프라 구성요소: 마이크로서비스를 지탱하는 하부구조 인프라를 구축하는 데 필요한 구성요소
    • 플랫폼 패턴: 인프라 위에서 마이크로서비스의 운영과 관리를 지원하는 플랫폼 차원의 패턴
    • 애플리케이션 패턴: 마이크로서비스 애플리케이션을 구성하는 데 필요한 패턴
  • 도커 컨테이너의 이점
    • 이식성: 어떠한 호스트 커널이나 플랫폼 버전에 상관없이 도커만 실행할 수 있으면 사용 가능하며 동일하게 동작된다.
    • 신속성: 크기가 작고 가볍기 때문에 빠르게 배포 가능하며, 문제 발생 시 수정할 필요 없이 새로 기동하면 된다.
    • 재사용성: 동일한 환경을 재사용해서 쉽게 설정 가능하기 때문에 개발, 테스트, 스테이징, 프로덕트 환경을 동일한 환경으로 구축하기가 쉽다.
  • 마이크로서비스 같이 독립적으로 배포되고 수정되기 위한 환경은 가상 머신보다는 컨테이너가 더 적절하다. 왜냐하면 마이크로서비스의 가변적이고 유연한 속성을 컨테이너가 쉽고 빠르게 지원할 수 있기 때문이다.
  • 컨테이너 오케스트레이션: 컨테이너가 많아지면 그에 따라 컨테이너의 자동 배치 및 복제, 장애 복구, 확장 및 축소, 컨테이너 간 통신, 로드 밸런싱 등의 컨테이너 관리를 위한 기능
  • 쿠버네티스의 주요 기능
    • 자동화된 자원 배정(Automatic binpacking): 각 컨테이너가 필요로 하는 CPU와 메모리를 쿠버네티스에 요청하면 컨테이너를 노드에 맞춰 자동으로 배치한다.
    • 셀프 치유(Self-healing): 컨테이너의 이상 유무를 점검(health check)해서 실패한 경우 자동으로 교체하고 재스케줄링한다.
    • 수평 확장(Horizontal scailing): 일정 CPU 및 메모리 사용량을 초과하면 자동으로 확장한다.
  • 서비스 유형별 대표적인 클라우드 서비스
    • IaaS(Infrastructure as a Service): 가상 머신, 스토리지, 네트워크 같은 인프라를 필요한 만큼 적시에 제공하는 서비스로서 사용자는 이러한 인프라를 이용해 개발 환경을 구성한 후 애플리케이션을 배포한다.
      ex) AWS EC2
    • CaaS(Container as a Service): 컨테이너 기반 가상화를 사용해 컨테이너를 업로드, 구성, 실행, 확장, 중지할 수 있는 서비스다. 애플리케이션을 바로 구동할 수 있는 환경을 제공한다는 점에서 PaaS와 유사하지만 다른 환경에도 이식 가능한 컨테이너 기발 가상화를 제공한다는 점이 다르다.
      ex) AWS ECS
    • PaaS(Platform as a Service): 복잡함 없이 애플리케이션을 곧바로 개발, 실행, 관리할 수 있는 플랫폼 환경을 서비스 형태로 제공한다. IaaS 위에 실제로 애플리케이션이 실행될 수 있는 미들웨어나 런타임까지 탑재된 환경이라 생각하면 이해하기 쉽다.
      ex) AWS Elastic Beanstalk
  • 데브옵스 환경이란 협의의 의미로 개발과 운영을 병행 가능하게끔 높은 품질로 소프트웨어를 빠르게 개발하도록 지원하는 빌드, 테스트, 배포를 위한 자동화 환경
  • 지속적 배포: 소스코드 저장소에서 빌드한 소스코드의 실행 파일을 실행 환경까지 자동으로 배포하는 방식을 말하며, 모든 영역을 자동화하는 것에 해당한다.
  • 빌드/배포 파이프라인: 빌드/배포되는 과정 동안 수행해야 할 태스크가 정의된 것이며, 통합 및 배포까지 이어지는 일련의 프로세스를 하나로 연계해서 자동화하고 시각화된 절차로 구축하는 것
  • Infrastructure as code: 인프라 구성을 마치 프로그래밍하는 것처럼 처리하고 소수의 인원으로 많은 컨테이너 배포 처리를 할 수 있는 것.
  • 넷플릭스 OSS에는 여러 마이크로서비스 간의 라우팅과 로드 밸런싱을 위한 줄(Zuul)과 리본(Ribbon), 모니터링을 위한 히스트릭스(Hystrix), 서비스 등을 위한 유레카(Eureka) 등이 포함돼 있다.

  • 스프링 클라우드 서비스의 연계 흐름
    • 1. 모든 마이크로서비스(스프링 클라우드 서비스를 포함한)는 인프라에 종속되지 않도록 데이터베이스, 파일 등에 저장된 환경 설정 정보를 형상관리 시스템에 연계된 'Config 서비스'에서 가져와 설정 정보를 주입한 후 클라우드 인프라의 개별 인스턴스로 로딩된다.
    • 2. 로딩과 동시에 '서비스 레지스트리'에 자신의 서비스명과 클라우드 인프라부터 할당받은 물리 주소를 매핑해서 등록한다.
    • 3. 클라이언트가 'API 게이트웨이'를 통해 마이크로서비스에 접근하고, 이때 API 게이트웨이는 적절한 라우팅 및 부하 관리를 위한 로드 밸런싱을 수행한다.
    • 4. 또한 API 게이트웨이에서 클라이언트가 마이크로서비스에 접근하기 위한 주소를 알기 위해 '서비스 레지스트리' 검색을 통해 서비스의 위치를 가져온다.
    • 5. 동시에 API 게이트웨이는 클라이언트가 각 서비스에 접근할 수 있는 권한이 있는지 '권한 서비스'와 연계해 인증/인가 처리를 수행한다.
    • 6. 이러한 모든 마이크로서비스 간의 호출 흐름은 '모니터링 서비스'와 '추적 서비스'에 의해 모니터링하고 추적된다.
  • 서비스 디스커버리 패턴은 클라이언트가 여러 개의 마이크로서비스를 호출하기 위해서 최적 경로를 찾아주는 라우팅 기능과 적절한 부하 분산을 위한 로드 밸런싱 기능을 제공한다.
  • 라우터는 최적 경로를 탐색하기 위해 서비스 명칭에 해당하는 IP 주소를 알아야 한다.

  • 그림 설명
    • 각 서비스 인스턴스가 로딩될 때 자신의 서비스 이름과 할당된 IP 주소를 레지스트리 서비스에 등록한다.
    • 그런 다음, 클라이언트가 해당 서비스 명을 호출할 때 라우터가 레지스트리 서비스를 검색해 해당 서비스의 이름과 매핑된 IP 정보를 확인한 후 호출한다.
    • 이 레지스트리 서비스는 모든 마이크로서비스의 인스턴스의 주소를 알고 있는 서비스 매핑 저장소가 된다.
    • 모든 마이크로서비스가 처음 기동할 때 위치 정보를 저장하고 서비스가 종료될 때 위치 정보가 삭제된다.

  • API 게이트웨이의 특징
    • 다양한 클라이언트가 다양한 서비스에 접근하기 위해서는 단일 진입점을 만들어 놓으면 여러모로 효율적이다.
    • 다른 유형의 클라이언트에게 서로 다른 API 조합을 제공할 수도 있고, 각 서비스에 접근할 때 필요한 인증/인가 기능을 한 번에 처리할 수도 있다.
    • 또 정상적으로 동작하던 서비스에 문제가 생겨 서비스 요청에 대한 응답 지연이 발생하면 정상적인 다른 서비스로 요청 경로를 변경하는 기능이 작동되게 할 수 있다.
    • 여러 인스턴스로 부하를 분산하는 로드 밸런싱도 수행하고, 라우팅 시 필터를 둬서 라우팅 전과 후에 각각 수행되는 선행 처리와 후행 처리, 에러 처리 등을 손쉽게 구현할 수 있다.
  • API 게이트웨이의 기능
    • 레지스트리 서비스와 연계한 동적 라우팅, 로드 밸런싱
    • 보안: 권한 서비스와 연계한 인증/인가
    • 로그 집계 서비스와 연계한 로깅. 예: API 소비자 정보, 요청/응답 데이터
    • 메트릭(Metrics). 예: 에러율, 평균/최고 지연시간, 호출 빈도 등
    • 트레이싱 서비스와 연계한 서비스 추적. 예: 트래킹 ID 기록
    • 모니터링 서비스와 연계한 장애 격리(서킷 브레이커 패턴)
  • BFF패턴은 API 게이트웨이와 같은 진입점을 하나로 두지 않고 프런트엔드의 유형에 따라 각각 두는 패턴이다. 프론트엔트를 위한 백엔드라는 의미로 BFF(Backend For Frontend)라 부른다.
  • 외부 저장소는 각 마이크로서비스의 외부 환경 설정 정보를 공동으로 저장하는 백업 저장소다.
  • 인증/인가 패턴
    • 중앙 집중식 세션 관리
      • 마이크로서비스는 각자의 서비스에 세셧ㄴ을 저장하지 않고 공유 저장소에 세션을 저장하고 모든 서비스가 동일한 사용자 데이터를 얻게 한다. 보통 레디스나 멤캐시드에 저장
    • 클라이언트 토큰
      • 세션은 중앙 서버에 저장되고 토큰은 사용자의 브라우저에 저장된다. 토큰은 사용자의 신원 정보를 가지고 있고 서버로 요청을 보낼 때 전송되기 때문에 서버에서 인가 처리를 할 수 있다.
    • API 게이트웨이를 사용한 클라이언트 토큰
      • 사용자 인증 프로세스는 토큰 인증 프로세스와 유사하다. 차이점은 API 게이트웨이가 외부 요청의 입구로 추가된다는 것이다. 또한 인증/인가를 처리하기 위한 별도의 전담 서비스를 만들어서 다른 서비스의 인증/인가 처리를 위임할 수 있다.
        이러한 서비스를 인증 서비스(Auth service)라 하는데, API 게이트웨이와 연동해서 인증/인가를 처리한다.
  • 서킷 브레이커 패턴: 서비스 상태를 항상 실시간으로 관리해서 시각화하고 모니터링할 수 있어야 하고, 특정 서비스에서 장애가 감지되면 장애가 다른 서비스로 전이되지 않게 하는 방법
  • ELK 스택은 엘라스틱서치(Elasticsearch), 로그스태시(Logstash), 키바나(Kibana)라는 세 가지 오픈소스 프로젝트를 기반으로 데이터 분석 환경을 구성한다.
    • Elasticsearch: 분산형 검색, 분선 엔진
      • 정형, 비정형, 위치 정보, 메트릭 등 원하는 방법으로 검색을 수행 * 결합 가능
    • Logstash: 로그 집합기
      • 데이터 처리 파이프라인. 다양한 소스에서 동시에 데이터를 수집해 변환한 뒤 특정 보관소로 데이터를 보냄
    • Kibana: 시각화
      • 히스토그램, 막대 그래프, 파이차트 등 표현. 위치 데이터, 시계열 분석, 그래프 관계 탐색 등 지원
  • 마이크로서비스 통신 패턴
    • 동기(Synchronous) 방식은 요청하면 바로 응답이 오는 방식을 말한다.
    • 바로 요청하면 응답이 오는 직관적인 방식이기 때문에 가장 많이 쓰이고 구현하기 쉽다. 그렇지만 호출을 받은 마이크로서비스에 장애가 발생할 경우 계속 기다리며 재호출을 하게 된다.
    • 메시지 기반의 비동기 호출은 동기 호출처럼 응답을 기다리지 않고 다음 일을 처리한다.
    • 물론 보낸 결과가 어떻게 됏는지 응답을 받지 않으므로 동기식처럼 완결성을 보장할 수는 없다.
    • 이를 보장하기 위한 메커니즘이 메시지 브로커이다.
    • 메시지를 보내는 생산자(Producer)와 메시지를 가져다가 처리하는 소비자(Consumer)가 서로 직접 접속하지 않고 메시지 브로커에 연결된다.
    • 메시지 브로커에 메시지를 전달하고 자신의 일을 처리하면 메시지 브로커가 전송을 보장하게 된다.
    • 그런데 여러 서비스에서 전달한 메시지를 처리하는 메시지 브로커 자체에 부하가 생길 수 가 있다. 이 경우 메시지 브로커는 메시지 처리 규모에 따라 확장이 가능하다.
    • 이 방식은 메시지 브로커에 의해 중계되기 때문에 서로 통신하는 서비스들이 물리적으로 동일한 시스템에 위치할 필요도 없고 서로 프로세스를 공유할 필요도 없으며, 심지어 동일한 시간대에 동시에 동작하지 않아도 된다. 따라서 서비스 요구에 따라 늘어나거나 줄어들 수 잇는 탄력성이 높은 클라우드 플랫폼 환경에서 서비스가 다운됏을 때 또는 시스템을 더 확장해야 할 때 사용할 수 있는 매우 효과적인 방법이다.
    • 이벤트 기반 아키텍처는 분산 시스템 간에 발신자가 이벤트를 생성 및 발행(publish)하고, 해당 이벤트를 필요로 하는 수신자에게 전송하면 이벤트를 구독하고(subscribe) 있던 수신자가 이벤트를 받아 처리하는 형태의 시스템 아키텍처다.
    • 이벤트는 '상태의 변화'를 의미하며, 기존의 순차적 방식의 아키텍처와 달리 특정 행동이 자동으로 순서에 따라 발생하는 것이 아닌 어떤 상태의 변경에 대한 반응으로 동작한다는 점이 차이점이다.
    • 이벤트 기반 아키텍처는 이벤트를 생산하는 모듈과 이벤트에 대응하는 모듈을 분리하고 상호 독립적으로 동작하게 함으로써 병렬 처리를 촉진한다. 이벤트 기반의 아키텍처와 비동기 통신 메커니즘을 함께 사용하는 마이크로서비스를 이벤트 기반 마이크로서비스(event-driven microservice)라고도 한다. 이벤트 메시지를 사용하면 발신자와 수신자를 장소와 시간에서 쉽게 분리할 수 있으며, 마이크로서비스가 추구하는 느슨한 결합으로 확장성, 탄력성 측면에서 이점이 많다.
  • 저장소 분리 패턴은 각 마이크로서비스의 고유한 비즈니스를 처리하기 위해 데이터를 직접 소유해야 한다는 것을 말한다.
  • 2단계 커밋은 분산 데이터베이스 환경에서 원자성(atomicity)를 보장하기 위해 분산 트랜잭션에 포함돼 있는 모든 노드가 커밋(commit)되거나 롤백(rollback)하는 메커니즘이다. 그러나 이 방법은 각 서비스에 잠금(lock in)이 걸려 발생하는 성능 문제 탓에 효율적인 방법이 아니다. 특히 각 서비스가 다른 인스턴스로 로딩되기 때문에 통제하기 어렵다.
  • 사가 패턴은 각 서비스의 로컬 트랜잭션을 순차적으로 처리하는 패턴이며 여러 개의 분산된 서비스를 하나의 트랜잭션으로 묶지 않고 각 로컬 트랜잭션과 보상 트랜잭션을 이용해 비즈니스 및 데이터의 정합성을 맞춘다.
  • 보상 트랜잭션은 어떤 서비스에서 트랜잭션 처리에 실패할 경우 그 서비스의 앞선 다른 서비스에서 처리된 트랜잭션을 되돌리게 하는 트랜잭션이다. 이를 통해 비즈니스 처리의 일관성을 유지한다.
  • 결과적 일관성이란 어떤 비즈니스 데이터의 일관성이 실시간으로 맞지 않더라도 어느 일정 시점이 됐을 때 일관성을 만족해도 되는 것이다. 결과적 일관성은 고가용성을 극대화한다. 
  • 쓰기 최적화: 이벤트 소싱 패턴
    • 저장소에 저장하는 일과 메시지를 보내는 작업이 언제나 완전하게 진행되어 함께 실행돼야 한다.
    • 이벤트 소싱이란 트랜잭션 자체를 저장하자는 전략이다. 즉 상태 변경 이벤트를 계산해서 데이터 모델로 변경하지 않고 바로 이벤트 저장소에 그대로 저장한다.
    • 처음부터 모든 트랜잭션을 처리하는 것이 부담된다면 매일 자정에 상태를 계산한 후 스냅숏으로 저장한 후 현재 상태 정보가 필요해지면 스냅숏 이후의 트랜잭션만 처리하면 된다.
    • 한 가지 중요한 점은 명령 측면과 조회 측면의 ㅓ비스가 이벤트 저장소에 대한 CRUD를 모두 처리할 필요 없이 '입력/조회(CR)'만 처리하면 된다는 것이다.

 

마이크로서비스 애플리케이션 아키텍처

  • 비즈니스 로직이란 보통 시스템의 목적인 비즈니스 영역의 업무 규칙, 흐름, 개념을 표현한다는 용어다.
  • 관심사의 분리란 시스템의 각 영역이 처리하는 관심사가 분리되어 잘 관리돼야 한다는 의미이고, 이 원칙은 시스템을 이해하고 변경하기 쉽게 만들어 준다.
  • 데이터베이스 중심 아키텍처란 특정 관계형 데이터베이스에 의존한 데이터 모델링을 수행한 다음 이 물리 테이블 모델을 중심에 두고 애플리케이션을 구현하기 위한 사고를 하는 방식이다. 이러한 시스템 구조에서는 저장소를 변경하려고 해도 쉽게 변경할 수가 없다. 
    왜냐하면 저장 기술과 비즈니스 로직이 끈끈하게 붙어 있기 때문에 저장소를 변경했을 때 모든 것을 다시 구현해야 한다고 판단되기 때문이다.
  • 레이어드 아키텍처
    • 티어는 물리적인 장비나 서버 컴퓨터 등의 물리층을 의미하고 레이어는 티어 내부의 논리적인 분할을 의미한다.
    • 계층은 설계자들이 복잡한 시스템을 분리할 때 흔히 사용하는 패턴 중 하나로, 애플리케이션이 내부에서 처리하는 관심사를 논리적으로 구분한다.
    • 의존성 역전 원칙은 유연성이 극대화된 시스템에서는 소스코드 의존성이 추상에 의존하며, 구체에는 의존하지 않아야 한다.
    • 개방 폐쇄의 원칙은 소프트웨어 개체는 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다는 원칙이다.
    • 애플리케이션에서는 비즈니스 로직이 핵심 영역이다. 그렇기 때문에 비즈니스 로직을 보통 고수준 영역이라고 하고, 프레젠테이션 계층 및 데이터 액세스 계층을 저수준 영역이라고 한다.

  • 헥사고날 아키텍처에서는 고수준의 비즈니스 로직을 표현하는 내부 영역과 인터페이스 처리를 담당하는 저수준의 외부 영역으로 나눈다. 내부 영역은 순수한 비즈니스 로직을 표현하는 기술 독립적인 영역이다. 외부 영역은 외부에서 들어오는 요청을 처리하는 인바운드 어댑터와 비즈니스 로직에 의해 호출되어 외부와 연계되는 아웃바운드 어댑터로 구성된다.
  • 헥사고날 아키텍처의 가장 큰 특징은 고수준의 내부 영역이 외부의 구체 어댑터에 전혀 의존하지 않게 한다는 것이다. 이를 가능하게 하는 것이 내부 영역에 구성되는 포트다.
  • 인바운드 포트는 내부 영역의 사용을 위해 표출된 API이며, 외부 영역의 인바운드 어댑터가 호출한다. 
    아웃바운드 포트는 내부 영역이 외부를 호출하는 방법을 정의한다.

  • 업무 규칙은 사업적으로 수익을 얻거나 비용을 줄일 수 있는 규칙 또는 절차를 말한다.
  • 엔티티 객체는 핵심 규칙과 데이터는 본질적으로 결합돼 있기 때문에 객체로 쉽게 만들 수 있다.
  • 유스케이스는 자동화된 시스템을 사용하는 처리 절차를 기술하고 애플리케이션에 특화된 업무 규칙을 표현하며, 엔티티 내부의 핵심 업무 규칙을 호출하며 시스템을 사용하는 흐름을 담는다.
  • 엔티티는 간단한 객체여야 하며, 프레임워크 데이터베이스 또는 기타 복잡한 것에 의존해서는 안 되고 유스케이스 객체를 통해서만 조작해야 한다.

  • 리포지토리 인터페이스는 외부 영역에서 정의하지 않고 내부 영역에서 정의하는데, 비즈니스를 처리하는 데 필요한 기본적인 저장소 처리 사항을 추상화해 정의한다.
  • 서비스 인터페이스는 외부 영역이 내부 영역에 대해 너무 많이 알지 못하게 하는 역할을 한다. 서비스 인터페이스가 ㅇ벗다면 추이 종속성이 발생할 수 있다.(정보 은닉 효과도 있다)
  • 도메인은 비즈니스 개념을 표현하고 서비스는 도메인을 활용해 시스템 흐름 처리를 수행한다.
  • 트랜잭션 스크립트 패턴은 비즈니스 개념을 표현하는 도메인 객체가 행위를 가지고 있지 않다. 따라서 모든 비즈니스 행위, 즉 무엇인가를 수행하는 책임은 서비스에 있다. 절차식 프로그래밍 방식과 같기 때문에 객체지향 지식이 없어도 일반적으로 쉽게 이해할 수 있는 구조이고 기존 데이터베이스 중심 아키텍처에 익숙하다면 더 쉽게 적응할 수 있다. 이 패턴은 비즈니스가 간단한 경우에는 쉽게 적용할 수 있다.
  • 도메인 모델 패턴은 도메인 객체가 데이터뿐만 아니라 비즈니스 행위를 가지고 있으며, 도메인 객체가 소유한 데이터는 도메인 객체가 제공하는 행위에 의해 은닉된다.
  • 도메인 객체는 각 비즈니스 개념 및 행위에 대한 책임을 수행하고, 서비스는 비즈니스 유스케이스를 구현하기 위해 서비스의 행위를 도메인 객체에 일부분 위임해서 처리한다.
  • 서비스의 책임들이 도메인으로 적절히 분산되기 때문에 서비스가 비대히지지 않고 서비스 메서드는 단순해진다. 
  • 도메인 모델 패턴의 도메인 모델은 객체지향 설계에 객체 모델이다.
  • 애그리거트 패턴은 최상위에 존재하는 루트 엔티티를 중심으로 개념의 집합을 분리한 것이다. 

  • 외부 영역은 내부 영역의 서비스 인터페이스를 사용하는 인바운드 어댑터와 내부 영역에서 선언한 아웃바운드 인터페이스를 구현하는 다양한 어댑터로 구성한다. 어댑터는 플러그인처럼 언제든지 교체되거나 확장될 수 있어야 한다.
  • API 퍼블리싱 어댑터는 REST API를 발행하는 인바운드 어댑터다.
  • API 프락시 어댑터는 다른 서비스의 API를 호출하는 아웃바운드 어댑터다.
  • OR 매핑 방식은 OR 매퍼가 런타임 시 저장소에 따라 자동으로 질의문을 생성한다.
  • 도메인 이벤트는 어떤 사건에 따른 상태의 변경 사항을 말하는데, '주문됨', '주문 취소됨' 등의 명칭을 갖는 클래스로 구현되며, 컨슈머(Consumer)에게 전달되기 위해 도메인 이벤트 발행 어댑터를 통해 발행된다.
  • 도메인 이벤트 핸들러는 외부에서 발행된 도메인 이벤트를 구독해서 내부 영역으로 전달하는 일을 수행한다.

 

마이크로서비스와 애자일 개발 프로세스

  • 전략적 설계는 도메인 전문가 및 기술팀이 함께 모여 유비쿼터스 언어를 통해 도메인 지식을 공유 및 이해하고, 이를 기준으로 개념과 경계를 식별해 바운디드 컨텍스트로 정의하고 경계의 관계를 컨텍스트 맵으로 정의하는 활동이다.
  • 전술적 설계는 식별된 바운디드 컨텍스트 내의 도메인 개념인 도메인 모델을 구성하는 유용한 모델링 구성요소들을 설명한다.
  • 스크럼 팀: 스프린트가 진행되는 팀을 스크럼 팀이라고 한다.
  • 스크럼 미팅: 스크럼 팀은 매일 아침 각자의 자리에 서서 짧게 진행되는 스탠드업 미팅을 통해 각자의 일을 투명하게 공유한다.
  • 스프린트 계획 수립: 시스템의 모든 요구사항은 제품 백로그에 담긴다. 그 다음 일정에 맞게 스프린트를 몇 번 수행할 것인가가 결정된다. 보통 스프린트는 1~4주의 기간이다. 스프린트 횟수가 결정되면 제품 백로그에 담긴 백로그를 각 스프린트에 적절히 배분한다. 스프린트가 종료되면 백로그 완료 일감을 기준으로 팀의 생산성이 결정된다. 이를 속도로라고 부른다.
  • 시연: 초기에 정의한 백로그가 모두 구현되고 그 요건을 만족하는지 확인하는 자리다.
  • 회고: 팀원들이 자기 스스로를 돌아보는 과정이다.
  • 아키텍처 정의: 마이크로서비스 외부/내부 아키텍처를 정의하는 공정이다.
  • 마이크로서비스 도출: 본격적인 마이크로서비스 개발로 들어가기 위한 스크럼 팀이 개발한 전체 마이크로서비스들을 파악하는 작업이다.
  • 컨텍스트 맵: 식별된 마이크로서비스와 그것들 간의 의존관계를 보여준다.
  • 빌드 및 배포
    • 소스코드 리포지토리 구성
    • 통합 빌드 잡(Build Job) 구성: 리포지토리에 존재하는 소스코드를 통합한 후 컴파일 및 테스트해서 바이너리를 만드는 활동을 자동화한다.
    • 컨테이너 생성 파일 작성: 배포 환경을 컨테이너 환경으로 구성할 경우 운영체제와 WAS와 빌드된 애플리케이션을 묶어서 컨테이너 이미지를 생성하는 스크립트를 작성할 수 있다.
    • 배포 스크립트 작성: 자동으로 배포하는 스크립트를 작성하는 활동이다.

 

마이크로 서비스 설계

  • 역할별로 모듈화된다는 말은 각 역할이 분명한, 응집성 있고 서로 의존성이 낮은 모듈들이 모여 마이크로서비스를 이루고, 이 마이크로서비스는 다른 마이크로서비스와 의존성이 낮아야 한다는 의미다.
  • 업무 기능 분해는 업무 흐름에 따라 업무를 최상위에서 하위까지 대, 중, 소의 크기로 분리하고 수행하는 일들을 체계적으로 정렬한다.
  • 마이크로서비스의 크기는 코드의 크기처럼 양적(Quantity)으로 판단할 것이 아니라 전체 업무 맥락에서 질적(Quality)으로 판단해야 한다.
  • 질적 판단 요소는 자율적으로 수행 가능한 업무의 단위, 개념의 일관성이나 기능의 응집성 등을 말하며, 이는 비즈니스 도메인이나 조직의 성숙도에 따라 상대적이다.
  • 클라우드와 마이크로서비스 아키텍처 적용을 통해 얻을 수 있는 장점인 독립적 개선과 배포, 장애 격리, 장애 발생 시 빠른 재실행을 가능하게 하려면 마이크로 서비스를 응집성 있게 식별하는 것이 매우 중요하다.
  • 많은 개념들이 하나로 엮인 복잡한 비즈니스 도메인을 논리적으로 구분되는 여러 개의 하위 영역을오 분리해야 한다는 뜻으로, 이렇게 분리된 하위 도메인을 서브 도메인이라고 한다.
  • 서브도메인: 중요도에 따라 핵심 서브도메인, 지원 서브도메인, 일반 서브도메인의 세 가지 유형으로 나뉜다.
  • 핵심 서브도메인: 다른 경쟁자와 차별화를 만들 비즈니스 영역이기 때문에 기업의 프로젝트 목록에서 높은 우선순위를 갖는 영역이자 소프트웨어 개발에서 전략적으로 가장 큰 투자가 필요한 영역을 말한다.
  • 지원 서브도메인: 비즈니스에 필수적이지만 핵심은 아닌 부분으로 볼 수 있다. 그러나 핵심 도메인을 성공시키기 위해서는 반드시 필요한 영역으로, 핵심 서브도메인 다음으로 중요한 영역이다.
  • 일반 서브도메인은 비즈니스적으로 특화된 부분은 아니지만 전체 비즈니스 솔루션에는 필요한 부분으로, 기존 제품을 구매해서 대체할 수 있다.
  • 바운디드 컨텍스트: 도메인의 주요 개념을 정의하고 도메인 간의 경계를 식별
  • 유비쿼터스 언어: 특정 도메인에서 해당 도메인에서의 의도를 명확히 반영하고 도메인의 핵심 개념을 잘 전달할 수 있는 언어
  • 도메인 모델: 특정 비즈니스 맥락에서 통용되는 개념들의 관계를 잘 정의한 모형
  • 바운디드 컨텍스트: 이곳에서 사용하는 언어와 저곳에서 사용하는 언어와 개념이 상이한 이 경계가 바로 도메인의 경계
  • 도메인 모델은 도메인과 관련된 업무를 수행하는 제품 책임자, 도메인 전문가, 개발자를 비롯한 모든 구성원들이 업무를 이해하는 기본 모형이 된다.
  • 하나의 큰 도메인을 여러 개의 바운디드 컨텍스트로 식별하면 비즈니스 수행을 위해 여러 개의 컨텍스트가 연계해야 하는 경우가 발생한다. 이러한 컨텍스트 간의 의존관계를 DDD에서 컨텍스트 매핑이라고 한다.
  • 시스템을 구성하는 컨텍스트 간의 매핑 관계를 표시하는 다이어그램을 컨텍스트 맵이라고 한다.
  • 공유 커널: 바운디드 컨텍스트 사이에 공통적인 모델을 공유하는 관계
  • 준수자(Confirmist)는 소비자와 공급자와 유사하지만 상류 팀이 하류 팀의 요구를 지원하지 앟거나 못하는 경우 사용한다.
  • 충돌 방지 계층(ACL: Anti-Corruption Layer)는 하류 팀이 상류 팀의 모델에 영향을 받을 때 하류 팀의 고유 모델을 지키기 위한 번역 계층을 만드는 것이다. 즉, 상류 모델의 변경 없이 하위 모델과 통합하기 위해 데이터를 변환하는 메커니즘을 구현한 것이라 할 수 있다.
  • 공개 호스트 서비스(OHS; Open Host Service): 바운디드 컨텍스트에 대한 접근을 제공하는 프로토콜이나 인터페이스를 정의한다.
  • 발행된 언어(PL; Published Language): 하류의 컨텍스트가 상류 컨텍스트가 제공하는 기능을 사용하게 하기 위한 간단한 사용과 번역을 가능케 하는 문서화된 정보 교환 언어다.
  • 컨텍스트 맵: 하나의 큰 도메인을 여러 개의 바운디드 컨텍스트로 식별하고 이들 간의 관계를 표현한 그림
  • 핵심 서브도메인에 포함되는 컨텍스트는 일반 서브도메인과 지원 서브도메인에 속하는 컨텍스트를 사용하고, 지원 서브도메인에 포함된 컨텍스트는 일반 서브도메인의 컨텍스트들을 사용한다.
  • 이벤트 스토밍: 이벤트 중심으로 이해관계자들이 모여 브레인 스토밍하는 워크숍을 의미한다.
  • 이벤트 스토밍은 모든 이해관계자가 모여 서로가 가지고 있는 각 관점을 논의하며, 그 차이점을 이해하고 공유할 수 있다는 점에서 기존 방법론에서 장기간 단절하며 수행했던 요구사항, 프로세스 모델링, 설계를 진행하는 과정을 뛰어넘는 민첩성과 효율성을 보여준다.
  • 이벤트 스토밍 워크숍은 다양한 이해관계자의 지식을 공유하고 새롭게 도출된 아이디어를 표현하기 위한 목적으로 진행한다.
  • 이벤트 스토밍은 현실 세계의 도메인을 다양한 의미의 스티커로 표현한다.
  • REST API 성숙도
    • 레벨 0은 REST API의 메커니즘을 전혀 사용하지 않고 전통적인 원격 프로시저 호출(Remote Procedure Call) 방식으로 HTTP프로토콜만 사용한 것이다.
    • 레벨 1은 URI에 개별적인 자원을 표현하는 것이다.
    • 레벨 2은 서비스의 기능을 처리하기 위해 약속된 HTTP 메서드들을 사용하는 것이다.
    • 레벨 3은 특정 요청을 하게 되면 반환값에 기대했던 결과에 덧붙여 추가로 사용자가 그 다음에 무엇을 할 수 있는지와 그것을 하기 위해 다룰 수 있는 URI 값을 보내준다.
  • 엔티티는 다른 엔티티와 구별할 수 있는 식별자를 가진 도메인의 실체 개념을 표현하는 객체다.
  • 식별자는 고유하되 엔티티의 속성 및 상태는 계속 변할 수 있다.
  • 값 객체는 각 속성이 개별적으로 변화하지 않는 개념적 완전성을 모델링한다. 따라서 값 객체는 속성과 속성의 합에 의해 전체 개념이 부여되며, 개별 속성이 별개로 수정되지 않고 전체 객체가 한 번에 생성되거나 삭제되는 객체다. 엔티티와 같이 식별자의 차이에 따라 구별되지 않고 속성과 속성으로 이뤄진 값의 비교에 의해 동일함이 결정된다.
  • 표준 타입은 대상의 타입을 나타내는 서술적 객체다.
  • 도메인의 비즈니스 로직 처리가 특정 엔티티나 값 객체에 속하지 않을 때 단독 객체를 만들어서 처리하게 되는데 이를 도메인 서비스라 하며 도메인 로직을 처리할 때 엔티티나 값 객체와 함께 특정 작업을 처리하고 상태를 본인이 가지고 있지 않고 엔티티나 값 객체에 전달한다.
  • 도메인 이벤트는 DDD 및 이벤트 스토밍에서 말하는 도메인 이벤트의 구현 객체다.
반응형