본문으로 건너뛰기
뒤로

DB 저장과 Workflow 시작을 연결한다

초안아직 소유자가 검토하고 실습해 확인하지 않은 글입니다. 학습 기록이 아니라, 확인 전의 글입니다.

읽기 약 5분 · 실습 시간 별도

문서 처리 API가 요청을 DB에 저장한 다음 Temporal Workflow를 시작한다고 하자. DB commit 직후 프로세스가 종료되면 요청 행은 있는데 Workflow는 시작되지 않을 수 있다. 반대로 Workflow 시작은 성공했지만 API가 응답을 받지 못하면 다시 시작을 요청할 때 중복 여부를 판단해야 한다.

Temporal이 실행을 관리해 주더라도 애플리케이션 DB 저장과 시작 API 호출을 하나의 로컬 트랜잭션으로 묶어 주는 것은 아니다. 실행 플랫폼을 도입한 뒤에도 시스템 사이에 두 번 쓰는 문제는 남는다.

“DB 저장 후 바로 호출” 사이에도 실패한다

코드 두 줄이 붙어 있다고 하나의 원자적 작업은 아니다. 첫 줄은 애플리케이션 DB에 쓰고 다음 줄은 네트워크를 통해 Service에 요청한다. 그 사이 프로세스 종료, 네트워크 장애, Service 응답 지연이 생길 수 있다.

DB 트랜잭션을 연 채 시작 API를 호출하면 해결될까? 외부 호출이 DB commit과 같은 프로토콜로 묶인 것이 아니라면 실패 가능성이 사라지지 않는다. 오히려 DB 잠금을 오래 유지할 수 있다. 외부 성공 후 DB rollback처럼 반대 방향의 불일치도 검토해야 한다.

가상 예제에서 먼저 정할 조건은 “접수 완료로 표시한 문서는 결국 처리 시작 또는 명확한 실패 상태로 이어져야 한다”이다. 이 조건을 만족하려면 아직 전달하지 못한 요청을 다시 찾을 근거가 필요하다.

전송할 요청도 함께 저장한다

Transactional Outbox는 업무 행과 전송할 내용을 같은 로컬 DB 트랜잭션에 저장하고, 별도 전달자가 외부 시스템에 보내는 패턴이다. 이 예제에서는 문서 처리 요청과 Workflow 시작 요청을 함께 기록하는 방식으로 적용을 검토할 수 있다.

이는 메시지 전달 패턴을 Workflow 시작 요청에 적용한 설계다. Temporal에 애플리케이션 DB용 자동 Outbox가 생긴다는 의미는 아니다. 전달자 구현과 상태, 실패 처리, 중복 정책은 애플리케이션이 마련해야 한다.

개념 흐름은 다음과 같다.

  1. 같은 DB 트랜잭션에서 문서 요청과 미전달 시작 요청을 저장한다.
  2. 전달자가 미전달 요청을 읽고 안정된 Workflow ID로 시작을 요청한다.
  3. 수락 결과를 확인한 뒤 전달 완료를 기록한다.
  4. 중단 후에는 미완료 항목을 다시 확인하고 전달한다.

세 번째 단계 직전에 전달자가 종료되면 외부 시작은 성공했는데 미전달로 남을 수 있다. 따라서 Outbox만으로 중복 요청이 없어지지 않는다. 같은 요청을 다시 보낼 수 있다는 전제에서 수신 측 동작을 설계해야 한다.

Workflow ID와 업무 요청을 연결한다

전달할 때마다 새 Workflow ID를 만들면 같은 Outbox 행이 여러 Workflow를 시작할 수 있다. 업무 요청에서 안정적으로 유도한 ID를 사용하고, 이미 실행 중인 경우와 이미 종료된 경우를 어떻게 처리할지 정한다.

Temporal에는 Workflow ID의 충돌과 재사용을 다루는 정책이 있다. 사용하는 SDK 버전에서 정책 의미를 확인해야 한다. 실행 중인 같은 ID의 처리와 종료된 같은 ID의 새 실행 허용을 하나로 뭉뚱그리면 재전송 때 예상과 다른 결과가 나올 수 있다.

“이미 존재한다”는 응답을 무조건 성공으로 취급하는 것도 충분하지 않다. 정말 같은 업무 요청인지, 이전 실행은 어떤 결과로 끝났는지, 운영자가 새 처리로 다시 시작하려는 경우인지 구분한다. 같은 ID에 다른 입력을 보내는 상황은 계약 위반으로 다룰 수 있다. 종료된 실행에 대한 중복 판단에는 이력 보존 기간도 영향을 주므로, 장기 업무 중복 방지를 Service의 ID 정책만으로 영구 보장한다고 가정하지 않는다.

RejectDuplicate도 Namespace에 보존된 종료 실행을 기준으로 검사한다. 오래된 Outbox 요청을 다시 보낼 가능성이 있다면 애플리케이션의 업무 요청 원장과 중복 방지 기록을 그 재전송 가능 기간에 맞춰 유지해야 한다.

전달자 종료 위치를 바꿔 본다

대표 실패는 Workflow 시작 응답을 받은 직후, Outbox 전달 완료를 기록하기 전에 전달자를 종료하는 것이다. 재시작 후 같은 요청이 다시 전송될 때 실행이 어떻게 식별되는지 확인한다. 새 Workflow를 무조건 만들지 않고 기존 실행과 연결할 수 있는지가 검증 대상이다.

첫 번째 실패인 DB commit 직후 종료도 함께 비교한다. 이때는 미전달 행이 남아 있어 전달자가 나중에 시작할 수 있어야 한다. 두 실험의 외부 상태는 다르지만 동일한 미완료 Outbox 행으로 보일 수 있으므로 수신 측 식별 정책이 중요하다.

자료에는 업무 요청 ID, Workflow ID, Outbox 상태, 시작 시도 목록, 실제 생성된 실행 목록을 남긴다. DB 행 수만 하나라고 Workflow도 하나라고 추정하지 않는다. 반대로 시작 API 호출이 두 번 있었다고 Workflow 실행도 두 개라고 단정하지 않는다.

시작 전달과 Activity 효과는 따로 검증한다

Workflow 시작을 안정적으로 연결해도 내부 Activity의 외부 저장은 재시도될 수 있다. 따라서 결과 저장과 허용량 예약의 멱등성은 여전히 필요하다. Outbox는 전달 누락과 재전송을 다루고, 각 Activity의 업무 키는 외부 효과 중복을 다룬다.

전달자가 장기간 실패하면 요청이 DB에만 머무를 수 있다. 미전달 수와 오래된 항목을 관찰하고, 재시도 불가능한 입력은 별도 실패로 드러내는 정책도 필요하다. 실패를 무한히 숨기는 재시도는 접수된 요청을 사용자에게 설명할 수 있게 만들지 못한다.

확인 질문: 시작 요청이 성공한 뒤 전달 완료 기록이 실패하면 재전송은 왜 필요한가? 같은 Workflow ID가 존재한다는 사실만으로 동일 업무의 전달 성공을 확정할 수 있을까?

참고 자료



댓글