오전 12시 3분, 모니터링 화면의 주문 곡선이 누군가 도화선에 불을 붙인 듯 치솟았다. 오전 12시 7분, 첫 429가 돌아왔다 — 운송사의 라벨 API가 스로틀링을 시작했다. 오전 12시 12분에는 마켓플레이스 주문 수집 API도 간헐적으로 거부하기 시작했다. 현장에서는 십여 명의 패커가 운송 라벨을 기다리는 동안 프린터는 섬뜩한 침묵을 지켰다. IT 담당자는 작업을 재시작하면서 단체 채팅에 "당황하지 마세요"라고 입력했는데, 모두가 그가 당황하고 있다는 걸 알 수 있었다. 그날 밤 우리는 손으로 쓴 피킹 시트로 두 시간을 버텼고, 다음 날 고객센터 전화는 끊이지 않았다.

이건 엉터리 소프트웨어에 관한 이야기가 아니다. 피크 시즌이 원래 그런 것이다. 하루에 수만 번 서드파티 API를 호출하는 시스템이 하룻밤에 그 10배가 넘는 볼륨에 도달할 수 있다. 모든 서드파티 API에는 할당량이 있고, 이를 초과하면 상대방은 협상하지 않는다 — 그냥 안 된다고 한다. 주문이 들어오지 않고, 라벨이 인쇄되지 않고, 재고가 동기화되지 않으며, 남의 서버 앞에서 전체 운영이 멈춰 선다. 이 글은 이론을 건너뛴다. 피크 시즌 전에 실제로 해야 할 일을 적는다.

죽기 전까지는 아무도 읽지 않는 할당량

첫째, 호출하는 모든 서드파티 API의 할당량을 찾아 숫자를 적어 둔다. 운송사 라벨 API, 마켓플레이스 주문 수집, ERP 재고 동기화, SMS 알림 — 각각 스로틀링 방식이 다르다. 분 단위도 있고, 일 단위, 계정 단위, IP 단위도 있다. 기억에 의존하지 마라. "분당 몇 백 정도겠지"라고 생각하지 마라. 공식 문서를 열어 숫자를 복사하고 단위를 메모하라.

둘째, 계산하라. 작년 피크 시즌 스파이크 — 또는 연중 세일 같은 소규모 리허설 — 에 1.5를 곱해, 자정 그 한 시간에 몇 번의 호출을 쏠지 계산한다. 주문이 아니라 호출 횟수를 세라. 주문 한 건이 서너 번의 API 호출(요금 조회, 라벨, 추적 푸시, 재고 업데이트)을 의미할 수 있고, 이 배율은 처음 계산해 보는 대부분의 사람을 놀라게 한다. 결과를 할당량 옆에 두면 격차가 정면을 응시한다.

셋째, 할당량 증설은 일찍 신청하라. 주요 플랫폼과 운송사는 모두 피크 전 증설을 지원하지만, 절차와 대기열이 있다 — 2~3주 전이 상식이다. 숫자만 제출하지 말고 계산 근거를 첨부하라. 신청을 심사하는 엔지니어는 "할당량을 올려 주세요"보다 "피크 시간대 호출량, 지속 시간, 엔드포인트별 내역"에 훨씬 잘 반응한다. 뼈아프게 배운 게 하나 있다. 어느 해 주 운송사의 할당량은 올리고 백업 경로를 잊었다. 피크 당일 밤 주 운송사가 흔들리자 트래픽이 페일오버됐고, 백업 할당량이 순식간에 터졌다. 그 모든 준비가 수포로 돌아갔다. 실제로 호출할 모든 계정과 경로 — 백업 포함 — 를 커버하라.

피크 시즌 주문 폭주로 소포에 파묻힌 포장 스테이션

재시도는 머리 없는 닭이 되어서는 안 된다

할당량 증설이 만능은 아니다. 피크 당일 밤에는 항상 예상 밖이 일어난다. 상대 서버가 흔들리고, 패킷이 유실되고, 엔드포인트가 예고 없이 성능이 떨어진다. 재시도 로직을 어떻게 썼느냐에 따라 무사히 넘기느냐, 상대방을 쓰러뜨리는 일을 마저 돕느냐가 갈린다.

멍청한 고정 간격 재시도는 쓰지 마라. 실패한 요청이 5초마다 재시도하는 건 홍수를 벽에 다시 던지는 꼴이다 — 상대방이 숨을 돌리는 순간 다시 쓰러뜨리게 된다. 지수 백오프를 써라. 1초 기다리고, 다음엔 2초, 다음엔 4초, 배로 늘려 가면서 약간의 랜덤 지터를 섞는다. 지터를 건너뛰는 사람이 많은데 그러면 안 된다. 지터가 없으면 모든 클라이언트가 같은 순간에 재시도해서 동기화된 새 홍수가 생긴다. 지터가 있으면 재시도가 흩어진다.

백오프에도 상한이 필요하다. 최대 재시도 횟수와 최대 총 대기 시간, 그걸 넘기면 포기하고 성능을 낮춘다. 무한 재시도는 가장 위험한 패턴이다. 재시도 큐가 커지다 애플리케이션 서버의 메모리를 다 먹어버리는 걸 본 적이 있다 — 벤더 API가 회복되기 전에 우리 시스템이 먼저 쓰러졌다. 재시도 횟수와 타임아웃은 부하 테스트 단계에서 설정에 고정하라. 피크 당일 밤에 설정을 고치는 건 도박이다.

그리고 읽기와 쓰기는 다르게 다뤄라. 주문 수집을 재시도하는 건 싸다. 라벨 인쇄나 재고 차감을 재시도하는 건 싸지 않다 — 그러니 쓰기를 재시도하기 전에 멱등성을 확인하라. 같은 주문이 두 번 인쇄되면 운송사가 중복을 제거해 주는가, 아니면 라벨이 두 장 나오는가? 두 번 청구되는가? 평온한 화요일에는 아무도 이런 질문을 하지 않지만, 피크 당일 밤이 대신 가르쳐 줄 것이다. 돈이나 실물 상품에 닿는 모든 쓰기 호출에는 멱등성 키를 붙여라. 중복은 정산 단계에서 발견하지 마라.

정말 무너지면, 품위 있게 성능을 낮춰라

백오프와 큐는 시간을 벌어 준다. 성능 저하는 현실을 인정하는 것이다. 상대 API는 다운됐고, 창고는 멈출 수 없다. 성능 저하 계획은 피크 시즌 전에 쓰고 리허설한다 — 오전 12시 12분에 즉석에서 만드는 게 아니다.

주력 수는 "지금은 주문을 받고, 동기화는 나중에"다. 마켓플레이스 주문을 수집할 수 없나? 로컬에 캐시된 주문으로 생산하고, 백업 운송사로 라벨을 인쇄한 뒤, API가 회복되면 데이터를 채워 넣어라. 재고 동기화가 막혔나? 계속 출고하고, 차이를 기록한 뒤 손으로 정산하라. 원칙은 하나다. 생명선 — 문밖으로 나가는 화물 — 을 지켜라. 실시간이 아닌 것은 늦어도 된다.

성능 저하에는 단계가 있어야 한다. 경미: 중요하지 않은 호출을 죽여라 — SMS 알림을 피크 후 배치로 돌리고, 생명줄인 라벨 인쇄 할당량을 비워라. 중간: 느리거나 비싸더라도 백업 경로로 페일오버하라. 심각: 수동으로 가라 — 빈 라벨에 손으로 쓰고, 스프레드시트 기반 피킹. 원시적으로 들리지만, 막상 그 상황에 있으면 원시적인 계획이 죽은 화면을 바라보는 것보다 낫다. 각 단계의 트리거와 절차는 인쇄한 한 장에 담아 당직 데스크에 붙여라. 피크 당일 밤 자정에 맑은 정신으로 생각하는 사람은 없다.

그 밑에는 큐가 있다. 평소 서드파티에 직접 가던 모든 호출은 피크 중에는 먼저 로컬 큐를 거치고, 할당량 이하의 일정한 속도로 소비된다. 큐 깊이에 알림 수위선을 그어라. 선을 넘기면 경미한 성능 저하가 자동으로 발동한다. 이건 평상시에 만들어라, 피크 일주일 전이 아니라 — 큐 자체의 안정성과 모니터링은 검증에 시간이 걸린다.

2주를 남기고, 이 리스트를 점검하라

피크 전 체크리스트, 체크용으로 준비했다. 모든 서드파티 할당량 기록 완료, 피크 호출량 계산 완료, 증설 신청 제출 완료(백업 경로 포함), 재시도 정책 가동 중 — 지터 포함 지수 백오프와 엄격한 상한, 쓰기 호출 멱등성 확인 완료, 3단계 성능 저하 문서화 및 1회 리허설 완료, 평활화 큐 가동 중 및 알림 수위선 설정 완료, 당직 명단과 에스컬레이션 경로 게시 완료.

내일 당장 할 수 있는 일이 하나 있다. 시스템의 서드파티 연동 설정을 열어 각 API의 할당량 한도를 찾아 표를 만들어라. 그 한 장의 표가 피크 시즌 전날 밤에 잠을 잘 수 있는지 — 이 글의 첫머리 같은 밤을 또 겪을지 — 를 가른다.

영어판 번역본입니다. 내용이 다를 경우 영어판을 우선합니다.