설계

도메인 주도 설계 첫걸음 5장.

오늘의 나1 2022. 9. 25. 14:27

5장. 간단한 비즈니스 로직 구현

간단한 비즈니스 로직을 구현할 때는 트랜잭션으로 데이터의 정합성만 신경쓰면된다.
트랜잭션 스트립트 패턴, 액티브 레코드 패턴을 사용한다. 

트랜잭션 스크립트 패턴

레코드 변경 시, 트랜잭션으로 감싸 실패했을 때에 롤백하거나 보상 절차를 타도록 해야 한다. 

단순히, 레코드를 트랜잭션으로 감싸기만 하면 된다고 생각하기 쉽지만... 의외로 신경써야할 포인트들이 있다. 

+ 앞으로 이 책에서 소개할 여러 패턴의 기본이라고 한다.

 

정합성 깨지는 경우들: 트랜잭션 스크립트 패턴을 아예 안 쓴 경우 OR 잘 못 쓴 경우

 

1. 트랜잭션없이 여러 레코드를 업데이트하는 경우

여러 레코드를 한 함수 안에서 변경하는 경우 ➡️ 트랜잭션으로 감싸서, 실패한 경우 롤백하도록 한다. 
https://github.com/vladikk/learning-ddd/blob/main/listings/05-02.cs

Users 테이블에 데이터 업데이트하고, 장애남 → VisitsLog 테이블에 로그를 업데이트 못 함. 데이터 정합성 깨짐
https://github.com/vladikk/learning-ddd/blob/main/listings/05-03.cs 

Users 테이블에 데이터 업데이트하고 장애남 → 실패 시 rollback하므로 데이터 정합성 지켜짐
  아쉬운 점: 다중 트랜잭션을 지원하지 않는 DB인 경우 사용할 수 없다. 분산 트랜잭션 환경(이후에 나옴)은 대응할 수 없다. 

 

2. 분산 트랜잭션 환경. 데이터는 변경했지만, 변경을 알리는 메시지 발행에 실패한 경우

레코드의 변경을 다른 시스템에 알리는 중에 실패한 경우 ➡️ 쉽지 않다...
https://github.com/vladikk/learning-ddd/blob/main/listings/05-04.cs#L9 

Users 테이블에 데이터 업데이트하고, 장애남 VISITS_TOPIC 메시지가 발행되지 않음. 데이터 정합성 깨짐
책에 따르면... 이렇다고 한다.
8장. CQRS 아키텍처 패턴을 사용하여 여러 저장 장치를 다루는 방법을 배운다. 또한 9장. 다른 데이터베이스에 변경사항을 커밋한 후 안정적인 메시지 발행을 가능하게 하는 아웃박스 패턴을 소개한다. 

 

3. 암시적 분산 트랜잭션 환경. 데이터 변경 후 클라이언트가 실패했다고 생각해 또 시도한 경우 😵‍💫

  • 클라이언트가 서버에 데이터 변경 요청을 보내고, 클라이언트가 죽음. 서버는 데이터를 변경했지만, 클라이언트는 알 수 없다. 
  • 서버에서 데이터 변경 후 장애가 나서 클라이언트에게 응답을 보내지 않거나 실패 응답을 보냄. 클라이언트는 실패했다고 생각한다. 
데이터 변경 후 클라이언트가 실패했다고 생각해 또 시도한 경우 ➡️ 여러 번 요청해도 원래 업데이트되어야 할 값으로 업데이트되도록 쿼리를 짠다
https://github.com/vladikk/learning-ddd/blob/main/listings/05-05.cs 

UPDATE Users SET visits=visits+1 WHERE user_id=@p1

요청할 때마다 visits가 +1 
방법1. 멱등성(idempotent)
https://github.com/vladikk/learning-ddd/blob/main/listings/05-06.cs 

UPDATE Users SET visits = @p1 WHERE user_id=@p2

여러 번 요청해도 항상 같은 값으로 업데이트 된다. 
  방법2. 낙관적 동시성 제어(optimistic concurrent control)

https://github.com/vladikk/learning-ddd/blob/main/listings/05-07.cs 

UPDATE Users SET visits=visits+1 WHERE user_id=@p1 and visits = @p2

제일 처음에만 WHERE 절 조건에 부합해서 한 번만 업데이트된다. 

 

 

 

액티브 레코드 패턴

데이터를 액티브 레코드라는 객체를 통해서 조작하는 방법. ORM 같은거...?

 

https://github.com/vladikk/learning-ddd/blob/main/listings/05-08.cs 

액티브 레코드로 데이터를 표현하고 조작한다. 

쿼리가 직접 노출되어 있지 않고, 액티브 레코드 내부에서 매핑한다?

트랜잭션 관리는 액티브 레코드가 하지 않고, 액티브 레코드 외부에서 트랜잭션 스크립트가 구현된다. 

액티브 레코드를 통해서 유효성 검사, 간단한 데이터 조작 등의 비즈니스 로직을 구현할 수도 있다.

 

언제 써?

단순한 로직인 경우. 하위지원도메인이나 일반지원도메인에 사용

핵심 하위 도메인에 쓰면 안 된다. 왜? 복잡한 비즈니스 로직이 함수 단위로 여기저기 존재하게 되어, 비즈니스 로직이 변경된다거나 리팩토링할 때, 모르고 바꾸지 못하는 경우가 생길 수 있음. 데이터 정합성이 깨지는 버그 발생하게 됨

아래 내용이 아마두 "복잡한 비즈니스 로직이 함수 단위로 여기저기 존재하게 되어, 비즈니스 로직이 변경된다거나 리팩토링할 때, 모르고 바꾸지 못하는 경우가 생길 수 있음. 데이터 정합성이 깨지는 버그 발생하게 됨"라는 뜻이지 않을까?

p.71 비즈니스 로직이 복잡할수록 트랜잭션 간에 비즈니스 로직이 중복되기 쉽고 결과저긍로 중복된 코드가 동기화되지 않을 때 일관성 없는 동작이 발생한다. 결과적으로 핵심 하위 도메인에는 트랜잭션 스크립트를 사용하면 안 된다. 핵심 하위 도메인의 비즈니스 로직이 복잡한 경우 트랜잭션 스크립트 패턴이 대처할 수 없는 문제점이 발생할 수 있다.

 

데이터의 일관성을 보장하는 것이 조금 덜 중요한 때도 있다.

데이터의 정합성도 중요하지만, 삐끗했을 때 큰 영향이 없다면 데이터 일관성을 보장하는 데 조금 덜 엄격할 수도 있다

예) 100만 개 중 하나의 레코드가 손상됐을 때, 큰 장애로 이어지지 않거나, 성과와 수익에 영향을 미치지 않는다면, 데이터가 손실되는 것에 조금 관대해도 좋다.

 

 

출처

  • 블라드 코노노프.  『도메인 주도 설계 첫걸음』. 경기 파주: 위키북스 출판, 2022

 

'설계' 카테고리의 다른 글

도메인 주도 설계 첫걸음 6장.  (1) 2022.09.25
도메인 주도 설계 첫걸음 1장. 2장.  (0) 2022.09.08