약 7분 읽기
REFramework를 처음 배울 때는 상태 이름부터 외운다. Initialization, Get Transaction Data, Process Transaction, End Process. 트랜잭션이 무엇인지는 교재로도 이해할 수 있다. 그런데 트랜잭션을 왜 그렇게까지 잘게 나누는지는, 프로세스 여러 개가 큐로 이어진 운영 환경에서 한 번 장애를 겪어봐야 몸에 들어온다.
이 글은 그 장애 하나에 대한 기록이다. PDF 두 개가 중간 단계에서 실패했고, 다시 돌리려다 “중복 Queue 존재”라는 메시지를 만났다. 그 메시지가 왜 나왔는지 따라가다 보면 REFramework의 트랜잭션 구조가 왜 그렇게 생겼는지가 보인다.

프로세스 네 개가 큐 하나로 이어져 있다
문제의 업무는 메일로 들어오는 발주서 PDF를 ERP에 입력하는 일이다. 한 프로세스가 다 하지 않고, 네 개로 나눠 큐로 넘긴다.
A Dispatcher 메일의 PDF 다운로드 → 큐 적재 (메일은 대기 폴더로) │ 큐 아이템 Reference = 수신일시_발신자_첨부순번__메일 고유 ID ▼ B DU Performer PDF에서 필드 추출 (신뢰도 미달 → Action Center 검증) ▼ C Performer 1 PO 리스트 엑셀 작성 + 메일 발송 ▼ D Performer 2 ERP에 실제 입력
A는 Dispatcher다. 메일함에서 PDF를 내려받고, 처리할 일을 큐 아이템으로 하나씩 등록한다. 메일은 대기 폴더로 옮겨서 다시 읽지 않게 한다. B부터 D까지는 Performer다. 큐에서 아이템을 하나씩 꺼내 자기 몫만 처리하고 다음 단계로 넘긴다. B는 Document Understanding으로 PDF에서 필드를 뽑는데, 추출 신뢰도가 기준에 못 미치면 Action Center에 사람이 확인할 검증 태스크를 만든다.
이렇게 나눈 이유는 실패를 한 단계 안에 가두기 위해서다. B에서 실패해도 A가 이미 해둔 일(메일 정리, 큐 등록)은 그대로 남는다. 다시 할 일은 B부터다.
6월 13일 새벽에 일어난 일
2026-06-13 05:05 A 성공 PDF 2개 큐 적재
2026-06-13 05:26 B 실패 필수항목 추출 실패 (첫 번째 PDF)
2026-06-13 05:30 B 실패 같은 원인 (두 번째 PDF)
이후 C, D 미실행 — 큐 아이템 Failed
2026-06-24 15:53 A 재실행 → "중복 Queue 존재"로 거부
A는 정상으로 끝났다. PDF 두 개가 큐에 들어갔다. 그런데 B가 첫 번째 PDF에서 필수항목을 뽑지 못하고 실패했고, 4분 뒤 두 번째 PDF도 같은 이유로 실패했다. 큐 아이템이 Failed가 되면서 C와 D는 아예 돌지 않았다. ERP에는 아무것도 들어가지 않았으니, 잘못된 데이터가 입력되는 사고는 없었다. 대신 그 발주 건이 통째로 멈췄다.
11일 뒤에 이 건을 다시 처리하려고 A를 다시 실행했다. 결과는 “중복 Queue 존재”였다.
중복으로 막힌 건 버그가 아니라 설계였다
처음엔 오류처럼 보였지만, 원인을 보니 의도된 동작이었다. A는 큐 아이템을 만들 때 Reference를 이렇게 만든다.
- 메일 수신 일시
- 보낸 사람
- 첨부 순번
- 메일 고유 ID
이 네 가지를 이어 붙이면 메일과 첨부마다 유일한 값이 된다. 큐에서 Reference 중복을 막아두면, 같은 메일을 두 번 읽어도 큐 아이템은 한 번만 생긴다. 메일함 확인이 겹치거나 A가 중간에 재시작돼도 같은 발주서가 ERP에 두 번 들어가지 않는다. 그러니 같은 메일로 A를 다시 돌리면 막히는 게 맞다.
REFramework가 Get Transaction Data와 Process Transaction을 나누는 이유도 같은 맥락이다. “무엇을 처리할지”를 정하는 일과 “그걸 처리하는 일”을 분리해두면, 처리가 실패해도 처리할 대상 목록은 흔들리지 않는다. 다시 할 때는 목록을 새로 만들 게 아니라, 실패한 항목만 다시 처리하면 된다.
그래서 실제로 한 일
A를 다시 돌리는 대신 큐를 열어 해당 발주 건의 큐 아이템을 찾았다. Reference로 검색하니 두 개가 “새로 만들기(New)” 상태로 다시 들어가 있었다. 재처리할 준비가 이미 되어 있었다는 뜻이다. A를 다시 돌릴 필요가 처음부터 없었던 셈이다.
- B의 다음 실행을 기다린다. B가 New 상태 아이템을 자동으로 가져간다.
- 같은 PDF라 다시 신뢰도 미달이 날 가능성이 높다. 그러면 이번에는 바로 실패하지 않고 Action Center에 검증 태스크가 생기는지 본다.
- 태스크가 생기면 사람이 필드값을 확인하고 고쳐서 승인한다.
- 승인되면 C와 D가 이어서 자동으로 처리한다.
결국 이 건은 사람이 한 번 들여다봐야 끝나는 건이었다. 자동화가 실패한 게 아니라, 자동으로 처리할 수 없는 문서를 사람에게 넘기는 단계가 제 역할을 한 것이다.
Reference를 만들 때 지키는 것
이번 일로 Reference 설계 기준도 정리했다.
- 원본에서 나오는 값으로 만든다: 처리한 시각처럼 실행할 때마다 바뀌는 값을 넣으면, 같은 메일이 두 번 들어와도 서로 다른 아이템이 된다. 수신 일시나 메일 고유 ID처럼 원본에 붙어 있는 값을 써야 중복을 막을 수 있다.
- 업무 한 건 단위로 만든다: 메일 하나에 PDF가 두 개면 발주서도 두 건이다. 첨부 순번을 넣어야 두 번째 PDF가 첫 번째의 중복으로 오인되지 않는다.
- 길이를 확인한다: Reference는 최대 128자다. 보낸 사람 주소나 메일 ID가 길면 넘칠 수 있어서, 이어 붙인 뒤 길이를 검사한다.
- 큐에서 유일성을 강제한다: 큐 설정의 고유 Reference 강제 옵션을 켜둬야 코드가 실수해도 큐가 막아준다.
Business 예외와 System 예외를 나누는 기준
이 장애를 REFramework의 예외 구분에 대입해보면 정리가 된다. REFramework는 실패를 두 종류로 나눈다.
- Business Rule Exception: 데이터나 업무 규칙 때문에 처리할 수 없는 경우다. 필수항목이 없는 PDF가 여기 해당한다. 다시 시도해도 결과가 같으니 재시도하지 않는다.
- System Exception: 프로그램이나 시스템 쪽 문제다. 화면이 늦게 떴거나, 연결이 잠깐 끊긴 경우다. 다시 하면 될 수 있으니 설정값(MaxRetryNumber)만큼 재시도한다.
B의 실패는 성격상 Business 쪽에 가까웠다. 같은 PDF를 같은 모델로 다시 읽어도 결과는 같다. 이런 실패를 System 예외로 처리하면 의미 없는 재시도만 쌓인다. 큐를 쓰는 구조라면 재시도는 Orchestrator 큐의 자동 재시도에 맡기고, 프로세스 안에서는 “다시 하면 될 실패”와 “사람이 봐야 할 실패”를 정확히 갈라 던지는 게 더 중요하다.
처음 REFramework를 배울 때는 상태 이름과 전환 조건을 외우는 데 시간을 썼다. 운영을 해보니 정작 중요한 건 두 가지였다. 큐 아이템 하나가 업무 한 건과 정확히 일치하는가, 그리고 실패했을 때 어디서부터 다시 하면 되는가.