LabHub
배우기 러닝패스 코스

FDE 캡스톤: 창고가 같은 주문을 세 번 받았다 · 고객의 말을 계약으로 · 이론

로봇 공장이 볼트를 세 번 받았다

LabHub 에서 이어서 보기

한 줄 요약

FDE의 첫 산출물은 빠른 스크립트가 아니라, 고객의 말을 검사 가능한 업무 규칙으로 옮긴 계약이다.

왜 이게 필요했나

가상의 로봇 공장에서 연락이 왔다. “주문 파일을 다시 올렸더니 창고에 같은 예약이 생겼어요. 실패한 줄 알고 한 번 더 눌렀을 뿐인데요.” 고객은 중복을 없애 달라고 말한다. 그런데 무엇이 중복인가? 파일의 같은 행인가, 같은 이벤트인가, 같은 주문인가? 주문 번호는 같은데 수량이 바뀐 경우는 수정인가, 잘못된 입력인가? 이 질문에 답하지 않고 코드를 쓰면 빠르게 잘못된 자동화를 만든다.

이 코스에서 여러분은 고객과 함께 작은 연동을 납품하는 엔지니어다. Python의 함수·딕셔너리와 CSV, HTTP 요청을 읽을 수 있다고 가정한다. 아직 낯설다면 앞의 FDE 데이터·API 실습부터 진행하자. 실제 물류 사고를 재현한 것이 아니라, 합성 데이터와 가상 창고로 만든 교육 시나리오다. 실제 출고·결제·재고 이동은 없다.

어떻게 동작하나

고객 브리프를 먼저 세 가지 질문으로 나눈다. 자동화가 바꿔도 되는 것은 무엇인가? 어떤 정보를 보내도 되는가? 판단이 모호할 때 누가 결정하는가? 이번 범위는 창고의 예약까지다. 배송을 지시하거나 충돌한 수량 중 하나를 엔지니어가 고르는 것은 범위 밖이다. 메일 주소는 원본에 있지만 예약에 필요하지 않으므로 보내지 않는다.

행의 event_id는 전달 사건의 번호이고 order_id는 업무 주문의 번호다. 같은 주문이 다른 이벤트로 다시 도착해도 새로운 구매가 되지는 않는다. 반대로 SKU가 같다는 이유로 서로 다른 주문을 합치면 정상 주문을 잃는다. 따라서 이번 고객과 합의한 중복 기준은 order_id와 그 주문의 내용이다. 모든 회사에 적용되는 만능 키라는 뜻이 아니다. 분할 출고나 주문 수정이 필요한 회사라면 버전·출고 번호에 관한 계약이 먼저 필요하다.

배포된 CSV에는 데이터 행이 일곱 개 있다. 헤더를 1행으로 세면 다음과 같이 분류한다.

| 데이터 행 | 관찰 | 처리 |
| --- | --- | --- |
| 2·3·4 | 서로 다른 정상 주문 세 개 | 각각 전송 후보 |
| 5 | 4행과 같은 주문·SKU·수량, 다른 이벤트 | 재전달로 기록 |
| 6 | 수량이 two | 불량으로 보류 |
| 7·8 | 같은 주문인데 수량이 1과 3 | 두 행 모두 충돌로 보류 |

결과는 후보 3개, 재전달 1행, 보류 3행이다. 일곱 행을 일곱 번 전송하지 않는다. “중복을 없앴으니 세 개를 버렸다”도 잘못된 설명이다. 보류는 삭제가 아니라 사람의 판단을 기다리는 상태이며, 행 번호와 사유가 남아야 한다.

여기서 한 줄씩 읽고 바로 보내면 7행을 전송한 뒤 8행의 충돌을 발견한다. 이미 예약한 것을 단순히 CSV에서 빼는 것으로 취소할 수 없다. 그래서 전체 파일을 먼저 검증하고, 같은 주문의 모든 행을 모아 판단한 뒤 전송한다. 유효한 주문 번호 아래 불량 행이 하나라도 있으면 그 주문 전체를 보류한다. 잘못된 주문 번호는 보고서에 그대로 복제하지 않고 null과 행 번호로 찾게 한다.

수량은 CSV 문자 1~5만 받는다. 02나 2.0을 숫자 2로 고치면 편리해 보이지만, 그것은 고객이 허용하지 않은 입력 보정이다. 최대 100행·256KiB도 이 연습의 입력 계약이다. 더 큰 업무를 다루려면 스트리밍 검증, 배치 경계와 중복 기록 보존 기간 등을 다시 설계해야 한다.

보내도 되는 행과 보내야 하는 주문

연습으로 한 행을 더 생각해 보자. ORD-EXTRA가 ROBOT-BOLT 두 개를 주문했고, 다른 ORD-SECOND도 똑같이 볼트 두 개를 주문했다. SKU와 수량만 비교하면 같은 행처럼 보이지만 업무 주문은 두 개이므로 둘 다 후보다. 반면 ORD-EXTRA의 이벤트만 새 번호로 다시 들어오면 후보를 늘리지 않는다. 이 두 예를 나란히 적으면 “중복 제거”라는 한 단어에 숨은 서로 다른 뜻을 동료와 확인할 수 있다.

또 다른 실수는 잘못된 행을 조용히 건너뛰는 것이다. 고객이 기대한 주문이 안 보이면 실행이 끝난 뒤 파일을 다시 올릴 수 있다. 그때 정상 처리한 주문까지 반복된다. 보류 목록에 행 번호와 짧은 사유를 남기는 것은 오류 보고서 장식이 아니라 다음 업무 행동을 결정하는 정보다. 보류 행의 원문을 로그에 통째로 넣을 필요는 없다. 원본은 보존하고 보고서는 어디를 확인할지만 가리키면 된다.

구현 전에 세 문장을 써 보자. “같은 주문의 같은 내용은 한 번만 예약한다.” “충돌이나 불량이 있으면 그 주문 전체를 전송하지 않는다.” “보류 사유를 남기되 불필요한 고객 정보는 옮기지 않는다.” 각각은 후보 목록·보류 목록·실제 요청을 검사하는 테스트로 바뀐다. 고객이 이 문장에 동의하지 않는다면 코드의 세부 구현보다 계약을 먼저 고쳐야 한다.

현장에서 만나는 모습

2026-09-11에 확인한 [OpenAI FDSWE 공고](https://openai.com/careers/forward-deployed-software-engineer-seattle-seattle/)는 고객 요구 파악, 반복적인 구현, PoC와 운영 배포의 작업 범위 작성을 다룬다. [Palantir FDSE 공고](https://jobs.lever.co/palantir/ce8ca664-60dc-4f9a-8986-3c96673bcfdf)는 모호한 문제에서 설계·프로토타입·데이터 연동까지 이어가는 일을 설명한다. 이 코스는 그 업무의 일부를 작은 실습으로 옮긴 것이다. 채용 시험이나 합격 보장이 아니며, 두 공고는 미국 특정 직무의 사례이지 한국 채용시장 전체를 대표하지 않는다.

다음에 확인할 것

다음 퀴즈에서는 전송 전에 합의할 경계와 보류 기준을 구분한다. 구현에 앞서 “어떤 결과면 고객이 맞다고 확인할 수 있는가”를 한 문장으로 설명해 보자. 이 실습에서는 보류되지 않은 주문만 정확히 한 예약으로 확인되고, 나머지는 사유와 함께 남는 것이 기준이다.