글 목록

여러 당사자가 관여하는 주문의 상태 정합성: 전체 승낙과 부분 승낙의 분리

단일 주문이 여러 당사자에게 배분될 때, 파생 상태 계산 기준을 '전체 승낙'과 '부분 승낙'으로 명확히 분리하여 정산 오류를 방지한 결정과 그 대가

주재범4분 읽기

이런 종류의 시스템이면 누구나 만나는 문제가 있다. 한 건의 업무가 여러 당사자에게 분배되고, 각자가 독립적으로 진행 상황을 보고할 때, 그 합이 원본의 상태를 올바르게 반영하지 못하는 경우가 발생한다. 개별 행위의 집합으로 전체 상태를 추론할 때, 경계 조건에서 모순이 생기면 정산이나 다음 단계의 흐름이 즉시 깨진다.

우리 솔루션은 배출, 운반, 처리를 담당하는 여러 사업자가 같은 주문을 서로 다른 역할로 보며 처리하는 물류 플랫폼이다. 이 플랫폼에서 한 주문은 여러 당사자에게 배분되며, 각자의 진행 상태가 모순되면 정산 오류로 직결된다. 개별 행위의 합이 전체 상태를 결정하는 방식은 구현이 간단해 보이지만, 데이터 정합성을 보장하기 어렵다. 이 글에서는 상태를 파생 필드로 관리하면서 그 기준을 명확히 한 사례를 다룬다.

한 줄 요약: 파생 상태의 계산 기준을 '전체 승낙'과 '부분 승낙'으로 명확히 분리하여 정산 오류를 방지했으나, 상태 판정의 복잡도가 증가했다.

배경

우리 솔루션은 B2B 물류 플랫폼의 백엔드이다. 여러 사업자가 같은 주문을 서로 다른 역할로 보며, 계약 규칙에 따라 운임과 정산이 자동으로 계산된다. 주문 목록은 봉투 마스터(묶음) 단위와 낱장 단위 두 층위로 구성된다. 목록 행은 봉투 마스터이지만, 실제 상태는 낱장 분포에서 파생된다. 이 구조에서 상태 판정의 기준이 모호하면 정산 로직이 불안정해진다.

문제를 느낀 계기

기존 구조에서는 '수락'과 '대기'의 혼재 여부만 부분 승낙으로 치고, 나머지를 승낙으로 읽었다. 이 규칙은 다음과 같은 상황에서 문제를 드러냈다.

  • 수락과 대기가 섞여 있을 때만 부분 승낙으로 판정했다.
  • 대기 상태가 소진되면 승낙으로 판정했다.
  • 거절이나 취소가 섞여 있어도 승낙으로 읽었다.

이 규칙은 '효산 앞 2장 중 1승낙·1거절'과 같은 시나리오에서 모순을 일으켰다. 거절이 포함된 상태에서 승낙으로 판정하면, 정산 로직은 완료된 것으로 보고 금액을 계산한다. 하지만 실제 업무는 완료되지 않았다. 정산 오류는 즉시 발생한다.

제약

결정의 경계 조건은 다음과 같다.

  • 파생 상태는 실시간으로 계산되어야 한다.
  • 정산 로직은 상태의 명확한 구분만 요구한다.
  • 기존 API 응답 구조를 대폭 변경할 수 없다.
  • 역사적 데이터의 정산 결과도 일관되어야 한다.

선택지

대안 1: 상태 머신의 단일화

모든 상태를 상태 머신으로 관리하고, 파생 상태를 제거한다.

  • 장점: 상태 전이가 명확하고, 모순을 방지할 수 있다.
  • 단점: 기존 구조의 변경 비용이 크고, 정산 로직과 결합도가 높아진다.

대안 2: 파생 상태의 기준 강화

파생 상태의 계산 기준을 강화하여, 거절이나 취소가 섞인 경우를 명확히 구분한다.

  • 장점: 기존 구조를 유지하면서 정합성을 확보할 수 있다.
  • 단점: 상태 판정의 로직이 복잡해지고, 유지보수 비용이 증가한다.

대안 3: 이벤트 기반 상태 동기화

각 당사자의 행위를 이벤트로 발행하고, 이를 기반으로 상태를 동기화한다.

  • 장점: 비동기 처리가 가능하고, 확장성이 좋다.
  • 단점: 이벤트 순서 보장과 재시도 로직이 복잡해진다.

결정

대안 2를 선택했다. 파생 상태의 계산 기준을 '전체 승낙'과 '부분 승낙'으로 명확히 분리했다.

전체 승낙은 모든 낱장이 승낙 상태일 때만 성립한다. 부분 승낙은 승낙과 대기, 또는 승낙과 거절이 섞여 있을 때 성립한다. 이 기준은 정산 로직이 요구하는 명확한 구분을 충족한다.

[코드 예시 필요: 파생 상태 계산 로직의 핵심 조건문]

이 결정은 기존 구조를 유지하면서 정합성을 확보하는 가장 낮은 비용의 경로였다. 상태 머신의 단일화는 변경 비용이 너무 컸고, 이벤트 기반 동기화는 구현 복잡도가 높았다.

결과와 한계

얻은 것:

  • 정산 오류가 발생하지 않는다.
  • 상태 판정의 기준이 명확해졌다.

잃은 것:

  • 상태 판정의 로직이 복잡해졌다.
  • 새로운 경계 조건이 추가될 때마다 로직을 수정해야 한다.

되돌릴 조건:

  • 정산 로직의 변경이 빈번해지면 상태 머신으로 전환해야 한다.

다른 시스템에 적용할 때: 파생 상태의 기준을 명확히 분리하는 것은 정합성 확보의 기본이다. 하지만 로직이 복잡해지면 상태 머신으로 전환하는 것을 고려해야 한다.

팀에 남긴 규칙: 파생 상태의 기준은 '전체 승낙'과 '부분 승낙'으로만 구분한다.

이 결정을 다시 봐야 할 조건: 정산 로직의 변경이 빈번해지면 상태 머신으로 전환해야 한다.

이 글 공유
LinkedInThreadsX