Design Patterns

마이크로 서비스패턴 - 5장. 비즈니스 로직 설계

FreeEnd 2022. 3. 19. 17:01
반응형

 

이 블로그는 마이크로서비스패턴 (길벗) 책 내용을 스터디를 위해 정리 한 내용 입니다. 

책구매는 바로가기 에서 구매 가능합니다.

 

5장은 DDD 설계의 전술적설계를 설명하는 단원이다. 전략적 설계를 통해 도출된 바운디드 컨텍스트와 도메인 모델을 기반으로 좀더 상세한 도메인 모델을 정의한다. 전술적 패턴은 단일 컨텍스트를 기반으로 적용된다. 

 

비즈니스 로직 구성패턴

비즈니스 로직 설계 : 트랜잭션 스크립트 패턴

절차적 트랜잭션 스크립트 패턴.

객체지향적 설계를 하지 않고, 하나의 트랜잭션으로 구성된 로직을 단일 함수 또는 단일 스크립트에서 처리 하는 구조를 갖는다. 예를 들어, 주문생성 -> 결제 -> 주문승인 -> 완료 순의 순서가 하나의 로직에서 처리되어야 하고, 중간에 오류가 발생하면 모두 취소된다. 

 

 트랜잭션 스크립트 패턴은 구현방법이 단순해 개발하기 쉬운 장점이 있는 반면에, 로직이 좀만 복잡해지더라도 코드가 난잡해져 유지보수 및 관리가 힘들어진다. 또, 단순히 절차적으로 로직을 개발하기 때문에 중복 코드가 많이 발생하게된다.

 

 때문에 복잡하지 않은 단순한 로직에서는 고민하지 말고 적용하는것도 나쁘지 않다.

 

 

비즈니스 로직 설계 : 도메인 모델 패턴

 도메인 모델은 객체지향 분석설계에 기반해 구현하고자 하는 도메인(비즈니스영역) 의 모델을 생성하는 패턴이다.

객체 지향적으로 설계한 비즈니스 로직은 비교적 작은 클래스가 그물망처럼 얽힌 객체모델로 구성된다. 

 

 객체지향 설계의 장점

  • 설계를 이해/관리하기 쉽다.
    각각의 함수들은 자신의 역할에만 충실하게 소규모 로직으로 구현되어 있어 쉽게 이해가 가능하며, 관리하기도 편리하다.

  • 테스트를 하기 쉽다.
    각 클래스 METHOD 는 독립적으로 수행할수 있기 때문에 단일 테스트가 가능하다.

  • 잘 알려진 설계 패턴을 응용/적용할수 있기때문에 확장성이 있다.
    각 CLASS, METHOD 별 다양한 디자인 패턴을 응용 적용할 수 있다.

 

도메인 주도설계 개요

DDD (도메인 주도 설계) 방식으로 설계하면, 설계한 서비스는 자체 도메인 모델을 가지게 된다.

  • 엔티티 : 영속적 신원을 가진 객체 (고유의 식별자), 두 엔티티가 동일해도 다른 객체이다.
  • 밸류 객체 : 여러 값을 모아놓은 객체 
  • 팩토리 : 일반 생성자로 만들기에 복잡한 객체 생성로직이 구현된 로직. (팩토리패턴 참고)
  • 리포지터리 : 엔티티를 저장하는 DB로직을 가진 객체
  • 서비스 : 비즈니스 로직을 구현한 객체

 

도메인 모델 설계 : DDD 애그리거트 패턴

애그리거트는 관련된 도메인 모델을 하나로 모은것이다. 애그리거트에 속한 객체는 유사하거나 동일한 라이프 사이클을 갖는다.

애그리거트를 사용하게 되면 연관 도메인이 묶여 도메인 모델을 이해하기가 한결 쉬워진다. 또, 코드의 복잡성이 낮아지기때문에 유지보수, 확장 변경등의 공수도 줄일 수 있고, 도메인 모델 관리에 있어서도 일관성 있게 관리 할 수 있다.

 

낙관적 락 : 어플리케이션 레벨에서, 변경하고자 하는 row의 특정값을 이용해 다른 트랜잭션의 요청을 막는 방법

비관적 락 : 트랜잭션이 시작할때 shared lock 또는 exclusive lock 을 걸고 시작하는것

 

 

 

 

불분명한 경계 문제

도메인 모델만 보고는 도메인객체의 경계를 짐작 하기 힘들다.

경계가 분명하지 않으면, 비즈니스 객체를 업데이트 할때 문제가 생길 수 있다. 

 

애그리거트는 경계가 분명하다

애그리거트 루트 (루트엔티티)

 애그리거트를 대표하는 엔티티 객체이다. 애그리거트에 속한 모든 객체가 일관된 상태를 유지하려면 애그리거트 전체를 관리할 주체가 필요한다, 루트 엔티티가 바로 그 역할을 한다. 때문에 애그리거트 내의 모든 객체는 루트 엔티티에 직/간접적으로 영향을 받는다.

 

 예를 들어, 주문건에 대한 상태가 존재할때, 애그리거트 루트가 아닌 다른 객체가 주문건의 상태나 정보를 직접 변경하게 되면, 로직적인 제한조건이나 다른 트랜잭션에 의한 상태 변경이 고려가 되지 않은채 값의 변경이 일어나게 된다. 

이때문에 루트 엔티티에 있는 메서드를 호출해서 주문건에 대한 값을 변경하게 강제 하여 데이터의 일관성을 유지하게 하는 것이다.

// 배송지 값을 직접 수정하는 방식
Order order = userInfo.getOrder();
order.setAddr("address 101-1");


// 애그리거트 루트를 통해 정보를 변경하는 방식
public class Order{
	public void changeAddress(String newAddr){
		String stat = order.getStat();
		if(stat == 'BEFER_SHIPPING'){
			setAddr(newAddr);
		}
	}
}

 

때문에 애그리거트를 식별하는 일이 중요하다. DDD 설계의 핵심은 애그리거트와 경계, 그리고 루트를 식별 하는 일이다.

 

애그리거트 규칙

규칙 1. 애그리거트 루트만 참조하라

애그리거트 루트만 참조해 애그리거트를 업데이트 해야 한다.

 

규칙 2. 애그리거트간 참조는 반드시 기본키를 이용하라.

 각각의 애그리거트는 기본키를 이용해 참조 해야 한다. 기본키가 아닌 다른 정보나 레퍼런스 정보로 참조 할 경우, 다른 레퍼런스를 잘못 참조할 수 있거나, 다른 정보를 잘못 수정 할 수 있다.

 또 애그리거트 자체가 저장 단위이므로 저장 로직도 간단해진다.

 

규칙 3. 하나의 트랜잭션으로 하나의 애그리거트를 생성/수정하라.

한번에 하나의 애그리거트만 수정해야 한다. 두개이상 동시에 수정 할 경우, 트랜잭션간의 충돌이 일어나 DEAD LOCK 이 발생 할 수 있으며, LOCK 이 발생하는 데이터가 많아져 장애가 발생 할 수 있다.

 여러개의 애그리거트를 업데이트 하기 위해서는, SAGA 를 이용해 개별 서비스 별로 업데이트해야 한다.

 

애그리거트 입도

 애그리거트는 작으면 작을 수록 좋다. 단위가 작아지면 동시 처리가능한 요청 개수가 늘어나고, 확장성도 좋아진다. 

하지만 애그리거트 자체가 트랜잭션 단위기 때문에 업무의 성격 별로 크게 설계 할 수도 있다. 

 

참고 : https://private-space.tistory.com/94

 

DDD 도메인 모델의 군집, 애그리거트(Aggregate)

최범균 님의 DDD Start를 읽고 정리한 내용입니다. DDD 애그리거트(Aggregate) 테이블이 100개 이상 있는 ERD를 보고 있다고 생각해보자. 하나 하나 따라가보면 개별 테이블의 연관 관계는 알 수는 있지

private-space.tistory.com

 

 

도메인 이벤트 발행

DDD 맥락에서 도메인 이벤트는 애그리거트에 발생한 사건이다. 도메인에서 어떠한 상태가 변경됨을 나타낸다.

예를 들어, 주문에서 이벤트는 '주문됨', '주문 취소됨' 등의 상태 변경이다. 

 

변경 이벤트를 발행하는 이유

  • 코레오그래피사가에서 여러 서비스의 데이터 일관성을 유지하기 위하여.
  • 레플리카셋의 원본데이터의 변경을 알려 동기화 하기 위하여
  • 메시지 브로커를 통해 비즈니스 프로세스의 다음단계를 알리기 위하여.
  • 사용자에게 상태 변경을 알리기 위하여.
  • 어플리케이션의 정상 수행 유무를 확인 하기 위한 이벤트 모니터링을 위하여 

 

도메인 이벤트란 무엇인가?

 도메인 이벤트는 과거 분사형 동사로 명명한 클래스이다. ( ~ 됨, ~ 이루어짐 등)

이벤트에는 이벤트를 식별 할 수 있는 ID, 타임스탬프 등의 메타데이터를 포함할 수 있다. 

 

이벤트 강화

이벤트를 수신한 컨슘머는 해당 이벤트의 처리를 위해 이벤트가 발생한 정보를 필요로 한다. 예를들어 '주문됨' 이라는 이벤트가 수신 되었다면 주문 정보가 필요할 것이다. 이 주문정보를 알기 위해 이벤트가 발생한 서비스에 다시 정보를 질의 하는건 필요없는 오버헤드가 발생 될수 있다. 때문에 이벤트에 주문 데이터를 실어 보내어 다시 이벤트발생 서비스를 조회하지 않고 바로 사용할 수 있는데 이를 이벤트 강화(event enrichment) 기법이라고 한다. 

 단, 컨슘머의 요건이 바뀌면 이벤트 클래스도 바뀌어야 하는 단점이 있다.

 

 

도메인 이벤트 식별

이벤트 스토밍은 도메인 모델을 신속하게 구축할수 있는 유용한 기법이다.

  1. 이벤트 브레인스토밍
    도메인 이벤트를 모두 나열해 포스트잇에 작성하고, 시간 순서대로 나열한다.

  2. 이벤트 트리거 식별
    각각 이벤트를 일으키는 트리거를 식별한다.

  3. 애그리거트 식별
    각 커맨드 소비 후, 적절한 이벤트를 발생시키는 애그리거트를 식별해 노란색 메모지로 표시한다.
반응형