FDE 캡스톤: 창고가 같은 주문을 세 번 받았다 · 구현하고 검증하고 넘기기 · 실습
창고가 같은 주문을 세 번 받았다
목표
고객의 합성 주문 CSV를 검증하고 가상 창고에 예약하는 Python CLI를 구현한다.
같은 파일 재실행과 응답 유실에도 예약을 중복 생성하지 않고, 미해결 항목을 인계한다.
왜 중요한가
API 호출 성공과 고객 업무 완료는 다르다. 응답을 못 받았다고 무조건 재전송하면 이미 저장한 주문을 다시 만들 수 있다.
반대로 재시도를 전부 막으면 저장 전에 실패한 정상 주문을 잃는다. 이번 실습은 입력 계약·멱등 키·영속 원장·재시도 상한을 함께 다룬다.
실제 출고·결제·고객 정보가 없는 가상의 로봇 부품 창고다. 상대편 원장 파일을 직접 읽거나 고치지 않고 HTTP 계약으로만 연동한다.
예상 80분이다. 기본 60분 세션이 끝나기 전에 +시간으로 연장하자(최대 180분).
세션이 끝나면 /root/handoff의 파일은 사라진다. 필요한 코드는 종료 전에 개인 작업 공간에 따로 보관하자.
재료와 실행 계약
- 고객 브리프: /opt/data/handoff-brief.md
- CLI·보고서·인계 문서 계약: /opt/data/handoff-program-contract.md
- 합성 주문: /opt/data/handoff-orders.csv
- 시작 코드: /opt/data/handoff-sync-starter.py
- 실행 평가기: /opt/lab/handoff/evaluate.py
먼저 브리프와 실행 계약을 읽는다. 입력은 최대 256KiB·100행, 수량은 문자 1~5다.
보류되지 않은 주문만 API 본문 order_id·sku·quantity로 준비한다. 메일은 전송·로그·보고서에서 제외한다.
평가기에는 프로그램 경로와 plan/send/chaos/repeat/drift/outage 중 검사 이름을 전달한다.
예: python3 /opt/lab/handoff/evaluate.py /root/handoff/sync.py plan
평가기가 격리된 임시 자료와 서버를 만들고 종료하므로 별도 서버를 먼저 띄울 필요가 없다.
평가 데이터는 주문 번호·SKU·수량 일부가 달라진다. 제공 CSV의 결과를 하드코딩하지 않는다.
단계
1. /root/handoff를 만들고 시작 코드를 sync.py로 복사한다. scope.json에 업무 warehouse-reservation, 업무 키 order_id, send_pii=false, max_attempts=4, retryable_statuses=[503], conflict_policy=hold_order, approval=review_only를 기록한다. JSON의 키 이름은 workflow·business_key·send_pii·max_attempts·retryable_statuses·conflict_policy·approval이다.
2. sync.py에 전체 CSV 검증과 계획 보고서를 구현한다. 기본 모드는 HTTP 요청 0회, outcomes는 빈 배열이다. 동일 주문의 불량·충돌은 주문 전체 보류, 동일 내용은 첫 행만 후보이며 나머지는 duplicates다. plan 검사로 확인한다.
3. sync.py의 --send 분기를 구현한다. 정상 서버에서 후보만 POST하고 GET /orders/<주문 번호>로 정확히 한 예약과 내용·ID를 확인한다. 보고서 일곱 필드와 outcomes 네 필드, 종료 코드 0/2는 실행 계약을 따른다. send 검사로 실제 원장과 대조한다.
4. sync.py에서 요청별 1초 제한, 같은 주문 키, 503·연결 오류 최대 네 번 시도와 0.1초 간격을 구현한다. 저장 전 503과 저장 후 응답 유실을 모두 처리하도록 chaos 검사를 통과시킨다. 4xx는 재시도하지 않는다.
5. sync.py가 다음 실행에서도 같은 업무 키를 사용하도록 확인한다. repeat 검사는 같은 원장으로 서버를 재시작하고 같은 입력을 다시 실행한다. 신규 예약이 늘거나 ID가 바뀌면 실행마다 달라지는 키와 재시도 분기를 고친다.
6. sync.py가 이미 예약한 주문의 변경 수량을 새 키로 우회하지 않도록 구현한다. drift 검사는 두 번째 실행에서 일부 수량을 바꾼다. 409는 POST 한 번으로 멈추고 rejected·null로 남기며 기존 예약을 유지해야 한다.
7. sync.py가 지속 503에서 주문별 POST 네 번 뒤 멈추고 unconfirmed·null을 기록하도록 확인한다. outage 검사를 실행한다. 조회로 확인하지 못한 결과도 성공으로 표시하지 않는다.
8. 현재 구현으로 여섯 검사를 모두 실행해 handoff.json을 만든다. 평가기의 receipt 모드를 사용해 구현·샘플 해시, 사례 목록, review_only 결정, 미해결 불량 수량·충돌 주문과 실험의 한계를 남긴다. 최종 채점은 scope.json·sync.py·handoff.json을 함께 읽고 실행을 다시 검증한다.
참고
- 계획 모드 자체 실행 예: python3 /root/handoff/sync.py --input /opt/data/handoff-orders.csv --base-url http://127.0.0.1:8031 --report /root/handoff/plan.json
- 위 계획 모드는 서버에 접속하지 않는다. 직접 --send를 시험하려면 브리프의 가상 API 기동 명령을 먼저 사용한다.
- 인계 생성: python3 /opt/lab/handoff/evaluate.py /root/handoff/sync.py receipt > /root/handoff/handoff.json
- 구현이 바뀌면 인계 문서도 다시 검증·생성한다. 해시만 바꾸지 않는다.
- 검증 성공은 운영 승인이 아니다. 단일 합성 창고이며, 같은 UID의 악의적인 프로그램을 막는 별도 보안 경계도 아니다.
단계 8개
- 고객의 말에서 작업 범위 고정
- 보내기 전에 일곱 행 분류
- 정상 예약을 조회로 확인
- 저장 전 실패와 응답 유실 복구
- 다음 담당자가 같은 파일 재실행
- 바뀐 수량을 새 주문으로 숨기지 않기
- 창고가 계속 아플 때 멈추기
- 실행 근거와 미해결 항목 인계