FDE Capstone: The Warehouse Got the Same Order Three Times
Average was 80ms, yet the lookup screen froze for 3 seconds
한국어 원문으로 표시합니다.
목표
모호한 고객 문장을 측정 가능한 기준표로 옮기고, 기준표를 읽어 요청을 보내고 증거와 판정을 남기는 인수 시험 실행기를 만든다. 정상 빌드만 인수하고 결함 있는 빌드는 해당 기준에서 떨어뜨려야 한다.
왜 중요한가
"빠르게" 는 평균으로도 p95 로도 잴 수 있고, p95 도 계산 방법에 따라 값이 달라진다. 무엇을 어떻게 재는지까지 합의하지 않으면 납품 뒤에 같은 숫자를 두고 다른 말을 하게 된다. 기준값을 코드에 적으면 기준이 바뀐 날 실행기가 조용히 틀린다. 판정만 있고 증거가 없는 보고서는 고객이 검증할 수 없다. 채점기는 가짜 견적 서버를 자기 포트에 띄워 꼬리가 느린·가끔 멈추거나 500 을 내는·금액이 1원 틀린·재조회가 흔들리는 빌드를 만들고, 기준값·사례표·변하는 필드 이름을 매번 바꿔 여러분의 실행기를 돌린 뒤 증거로 지표를 다시 계산해 보고서와 대조한다.
예상 60분이다. 기본 세션이 끝나기 전에 +시간으로 연장하자(최대 180분). 세션이 끝나면 /root 의 파일은 사라지니 코드는 따로 보관한다.
단계
- 고객 메일과 회의록을 읽고 합의한 기준을 /root/accept/criteria.json 에 적는다. 구매팀장의 첫 희망 숫자가 아니라 회의에서 합의한 숫자와 측정 조건을 쓴다.
- /root/accept/accept.py 가 기준표의 passes 만큼 사례표를 조회해 samples.jsonl 을 남기고, p95_ms(nearest-rank) 기준을 판정해 report.json 과 종료 코드 0·1 을 내게 한다.
- accept.py 에 error_rate 를 넣는다. 200 이 아닌 응답과 timeout_ms 안에 오지 않은 응답을 오류로 세고, 증거의 status 에 "timeout" 을 남긴다.
- accept.py 에 mismatches 를 넣는다. 1회차에서 200 을 받은 사례만 expected_total 과 비교하고 틀린 사례 id 를 mismatched_cases 로 남긴다.
- accept.py 에 rerun_diffs 를 넣는다. 1·2회차가 모두 200 인 사례를 기준표의 ignore_fields 를 뺀 본문으로 비교하고 rerun_diff_cases 를 남긴다.
- 네 기준을 함께 쓰는 기준표에서 op(<, <=, ==)를 그대로 따르고, 보고서의 observed·pass·metrics 가 증거로 다시 계산한 값과 같게 한다.
- 새로 바뀐 기준표로 후보 다섯 개(정상·느린 꼬리·가끔 500·틀린 금액·흔들리는 재조회)를 돌려 정상만 인수되는지 확인한다.
- 고객 후보 rc2 를
python3 /opt/lab/p1a-criteria/quote_server.py --port 8095 --build rc2로 띄우고, criteria.json 과 제공 사례표로 실행해 /root/accept/rc2/ 에 report.json 과 samples.jsonl 을 남긴다.
참고
- 재료: 고객 요청 /opt/lab/p1a-criteria/customer-request.md, 실행 계약 /opt/lab/p1a-criteria/CONTRACT.md, 사례표 /opt/lab/p1a-criteria/cases.csv, 가짜 서버 /opt/lab/p1a-criteria/quote_server.py
- 연습 서버: python3 /opt/lab/p1a-criteria/quote_server.py --port 18095 --build rc1 & (정상 후보). 끝나면 그 PID 만 골라 끈다.
- 직접 실행: python3 /root/accept/accept.py --criteria /root/accept/criteria.json --cases /opt/lab/p1a-criteria/cases.csv --base-url http://127.0.0.1:18095 --out /tmp/run1; echo $?
- 흔한 실수: 평균이나 statistics.quantiles 기본값으로 p95 계산하기, 예열·재시도 요청 섞기, 오류 응답을 틀린 금액으로도 세기, 변하는 필드 이름을 코드에 적기, 기준값을 코드에 적기.
- 이 서버 주소는 채점기가 쓰지 않는다. 채점기는 매번 자기 서버를 새로 띄운다.
형용사 네 개를 숫자 네 개로
고객 문장 네 개마다 metric·op·threshold·source 를 정해 /root/accept/criteria.json 에 timeout_ms·passes·ignore_fields 와 함께 적으세요.
회의록에는 처음 나온 희망 숫자와 최종 합의가 섞여 있습니다. 퍼센트는 비율(소수)로, 시간은 ms 정수로 적습니다. source 에는 그 기준이 나온 고객 문장을 적습니다.
평균이 아니라 p95 로 느린 꼬리 잡기
/root/accept/accept.py 가 사례표를 passes 번 조회해 samples.jsonl 을 남기고 p95_ms 기준을 판정하게 하세요.
요청마다 time.perf_counter 로 잰 ms 를 남기고, 모든 요청의 ms 를 정렬해 ceil(0.95 × n) 번째 값을 고릅니다. statistics.quantiles 의 기본값은 보간이라 다른 값이 나옵니다. 요청 수는 정확히 passes × 사례 수입니다.
오지 않은 응답도 오류로 세기
/root/accept/accept.py 에 error_rate 를 넣어 200 이 아닌 응답과 timeout_ms 초과를 오류로 세게 하세요.
urlopen 의 timeout 인자에 기준표의 timeout_ms 를 초 단위로 넘깁니다. HTTPError 는 상태 코드가 있는 응답이고, 시간 초과는 TimeoutError·URLError 로 옵니다. 증거의 status 에는 timeout 을 문자열로 남깁니다.
1원 틀린 금액 찾기
/root/accept/accept.py 에 mismatches 를 넣어 1회차 200 응답의 total 을 expected_total 과 비교하고 mismatched_cases 를 남기게 하세요.
CSV 의 expected_total 은 문자열이니 정수로 바꿔 비교합니다. 오류 응답은 이미 오류율로 셌으니 금액 비교에서는 뺍니다. 한 문제를 두 기준에서 이중으로 세면 어느 기준이 원인인지 흐려집니다.
두 번 조회해서 흔들리는 사례 찾기
/root/accept/accept.py 에 rerun_diffs 를 넣어 기준표의 ignore_fields 를 뺀 1·2회차 본문을 비교하고 rerun_diff_cases 를 남기게 하세요.
request_id 같은 필드 이름을 코드에 적으면 채점기가 필드 이름을 바꾸는 순간 정상 빌드가 떨어집니다. 딕셔너리에서 기준표의 필드만 빼고 비교하세요.
보고서가 증거와 같은지 스스로 맞추기
/root/accept/accept.py 가 네 기준을 기준표의 op 그대로 판정하고, report.json 의 observed·pass·metrics 가 samples.jsonl 로 다시 계산한 값과 같게 하세요.
op 는 문자열을 연산으로 바꾸는 표로 처리합니다. 오류율이 기준값과 정확히 같을 때 < 는 실패, <= 는 통과입니다. threshold 는 기준표 값을 그대로 옮기고, 증거는 요청 직후에 한 줄씩 씁니다.
바뀐 기준표로 후보 다섯 개 가르기
/root/accept/accept.py 가 새 기준값·새 사례표·새 변하는 필드 이름에서도 정상 후보만 인수하고 결함 후보는 해당 기준 하나에서만 떨어뜨리는지 확인하세요.
한 결함이 여러 기준을 동시에 떨어뜨리면 원인을 가를 수 없습니다. 기준값·필드 이름·사례를 코드에 적은 곳이 남아 있지 않은지 찾아보세요.
고객 후보 rc2 인수 판정하기
rc2 서버를 포트 8095 에 띄우고 criteria.json·제공 사례표로 실행해 /root/accept/rc2/report.json 과 /root/accept/rc2/samples.jsonl 을 남기세요.
기준표를 결과에 맞춰 고치지 마세요. 채점기는 criteria.json 이 1단계 합의와 같은지, 보고서가 증거와 같은지, 증거가 실제 rc2 응답인지 봅니다. 서버는 다 쓴 뒤 그 PID 만 골라 끕니다.