FDE 캡스톤: 창고가 같은 주문을 세 번 받았다 · 구현하고 검증하고 넘기기 · 이론
초록불 대신 넘겨줄 근거를 만든다
한 줄 요약
인계는 성공 스크린샷이 아니라, 어떤 코드와 입력으로 무엇을 검증했고 무엇이 남았는지 전달하는 일이다.
왜 이게 필요했나
개발자는 “잘 됩니다”라고 말하고 고객은 “어제 파일을 다시 올려도요?”라고 묻는다. 둘은 서로 다른 성공을 말하고 있다. 개발자는 정상 요청 한 번을 봤고 고객은 다음 담당자가 반복 실행해도 업무가 망가지지 않는지를 묻는다. 좋은 인수 기준은 이 차이를 코드 작성 전에 드러내고, 마지막에 같은 기준으로 다시 확인하게 한다.
어떻게 동작하나
먼저 계획 모드와 전송 모드를 분리한다. 기본 실행은 HTTP 요청을 전혀 보내지 않고, 원본의 해시와 전송 후보·재전달·보류를 JSON으로 남긴다. --send를 명시해야 예약과 조회를 시작한다. “실제로 바꾸는 동작”을 눈에 보이는 선택으로 만드는 것이다. 계획 파일이 존재한다고 전송까지 완료됐다고 해석해서는 안 된다.
전송 보고서에는 준비한 각 주문의 status·attempts·reservation_id를 기록한다. attempts는 POST만 센다. 원장 조회 GET이나 CSV의 재전달 행 수를 더하지 않는다. 보류 행이 있거나 결과를 확인하지 못했다면 종료 코드 2를 반환한다. 이 코드는 프로그램 충돌이 아니라 처리 결과에 검토할 항목이 남았다는 뜻이다. 모니터링이나 다음 자동화가 모든 비제로 코드를 무작정 재실행하면 보류와 장애가 다시 섞인다.
실습 평가기는 여러분의 성공 문구를 믿는 대신, 별도의 창고 API를 띄우고 실제 HTTP 요청 수와 SQLite 원장을 보고 보고서를 대조한다. 입력의 주문 번호·SKU·수량 일부도 바꾼다. 제공된 CSV의 정답만 하드코딩하면 다른 입력에서 드러난다. 채점용 자료나 원장을 직접 고치는 것이 아니라 공개된 CLI와 HTTP 계약을 구현해야 한다.
| 검사 | 확인하려는 질문 |
| --- | --- |
| plan | 전송 없이 전체 입력을 분류했는가? |
| send | 정상 서버에서 후보만 예약하고 결과를 조회했는가? |
| chaos | 저장 전 503과 저장 후 응답 유실을 모두 처리했는가? |
| repeat | 같은 원장으로 서버를 재시작하고 재실행해도 중복이 없는가? |
| drift | 기존 주문 내용이 바뀌었을 때 409를 우회하지 않는가? |
| outage | 지속 503에서 네 번 뒤 멈추고 미확인으로 남기는가? |
마지막 단계에서는 이 여섯 검사를 실행한 인계 문서를 만든다. implementation_sha256은 검증한 sync.py를, fixture_sha256은 배포된 샘플 CSV를 가리킨다. 해시 자체는 품질 점수가 아니다. 검증 뒤 파일이 바뀌었는지 구분하는 표식이다. 주석만 바꾸더라도 파일의 바이트가 바뀌었으므로 문서를 다시 생성한다.
verified_cases에는 실행한 사례를, unresolved에는 불량 수량과 충돌 주문의 판단이 남았음을 적는다. decision은 review_only다. 교육용 시험이 통과했다고 고객의 운영 승인을 대신할 수 없기 때문이다. limits에는 합성 단일 창고 실험이라는 점과 운영 승인에 해당하지 않는다는 점을 남긴다. 최종 채점도 문서의 문자열만 검사하지 않고 현재 코드로 검사를 다시 실행한다.
현장에서 만나는 모습
다음 담당자는 실패한 주문 번호만으로는 충분하지 않을 수 있다. 어느 입력의 몇 행인지, 이미 확정한 예약이 있는지, 어떤 경우에 재전송을 멈췄는지 알아야 한다. 그렇다고 원본 전체와 고객 메일을 로그에 복사할 필요는 없다. 이 과제에서는 검증된 주문 ID·행 번호·짧은 사유만 사용한다. 합성 자료라도 불필요한 개인정보를 옮기지 않는 습관을 연습한다.
이 평가기는 실습 컨테이너에서 실행되는 정확성 검사이지, 같은 권한의 악의적인 프로그램을 격리하는 별도 보안 시스템은 아니다. 여섯 사례도 모든 장애를 대표하지 않는다. 검증을 통과한 범위와 실제 운영에 필요한 추가 검토를 분리해서 적는 것이 신뢰할 수 있는 인계다.
다음 담당자의 첫 행동까지 생각하기
인계를 받은 사람이 “일단 전부 다시 돌리면 되겠네”라고 이해한다면 문서가 부족한 것이다. 보류 사유 invalid_quantity는 원본 담당자에게 허용된 정수 수량을 확인할 일이고, conflicting_order는 어느 내용이 승인된 주문인지 업무 담당자에게 물을 일이다. 이 두 판단은 엔지니어가 행 순서나 더 작은 수량을 보고 추측하지 않는다. 수정 파일을 받으면 원본을 덮어쓰지 않고 별도 입력으로 계획 모드를 실행해 후보와 보류의 변화를 확인한다.
이미 예약된 주문의 수량이 바뀌었다면 더 주의해야 한다. 이번 API는 예약 생성과 조회만 제공하며 수정·취소 절차를 제공하지 않는다. 새 키로 변경 수량을 밀어 넣는 대신, 기존 예약과 변경 요청을 제시하고 고객과 변경 절차를 합의해야 한다. “검증 통과”와 “이번 변경을 실행할 권한이 있다”를 나누는 작은 연습이다. 최종 문서는 그 판단을 완료했다고 주장하지 않도록 review_only를 유지한다.
미확인 상태의 대응도 다르다. 원본 수량을 고치는 것이 아니라, 같은 업무 식별자로 상대편의 결과를 확인하고 기존 키를 보존해야 한다. 개인 메일 주소를 새 로그로 퍼뜨리지 않고도 해당 주문과 입력 해시로 맥락을 전달할 수 있다. 이 코스가 끝난 뒤 자신의 프로그램을 다른 사람에게 설명한다면, 정상 성공의 실행 방법뿐 아니라 언제 멈추고 무엇을 물어봐야 하는지까지 말해 보자.
다음 실습에서 할 것
scope.json으로 요구를 고정하고 sync.py를 계획→정상 전송→재시도 순서로 완성한다. 재시작·내용 변경·지속 장애를 확인한 다음 handoff.json을 만든다. 예상 80분이므로 기본 60분 세션이 끝나기 전에 +시간으로 연장하자. 최대 180분이며 세션 종료 시 파일은 사라진다. 완성 코드는 종료 전에 개인 작업 공간에 별도로 보관한다.