64만 건 백필을 라이브 뒤에 세우는 장치 셋
2020~2025 공시 아카이브를 채우려면 외부 API 일일 한도와 LLM 처리량 안에서 몇 달을 돌려야 한다. 수집과 분석을 떼고, 아카이브를 신규 공시 뒤에 세우고, 한도 오류에 전 워커를 멈추는 장치를 만들었다. 완료 예상은 닷새 사이 네 번 바뀌었다
공시 요약 서비스는 지금 들어오는 공시만 요약하고 있어서 2020년부터의 과거가 통째로 비어 있었다. 2025년 한 해만 12만 건이고 2020년까지 합치면 64만 건인데, 공시 API가 하루에 허용하는 호출 수와 LLM이 삼킬 수 있는 양이 둘 다 천장이라 채우는 데 몇 달이 걸리는 일이다. 그동안 오늘 들어온 공시가 뒤로 밀리면 안 된다는 게 조건이었다.
하려던 것
2025년 공시 모두 백필하고 싶은데 준비해줘. 그리고 주가는 어떻게 된 거야? 안 보이는데.
공시 요약 서비스의 과거를 채우는 일이다. 주가는 버그가 아니었다. 공시 다음 날 종가가 그다음 날 오후에 올라오는 설계였다. 시세는 같은 날 2020년부터 따로 채웠다. 46분, 393만 행.
공시는 규모가 달랐다. 상장사 공시 목록을 실측하니 20202025년 합계 648,594건이었다. 2025년만 120,381건. 천장이 둘이었다. 공시 API 일일 한도와 LLM 처리량. 에이전트의 진단은 “몇 달짜리 상시 작업, 천천히 계속이 유일한 방법”이었다. 그리고 진짜 제약은 디스크였다. 프로젝트 넷이 나눠 쓰는 5GB 볼륨이 67% 차 있었다. 20202024년은 볼륨 증설 뒤로 미루고 2025년만 진행했다.
어떻게 시켰나
“천천히 LLM이 계속 돌게 할 수 있을까.” 이 한 줄에서 장치 셋이 나왔다.
수집과 분석을 뗀다. 64만 건을 한 번에 큐에 넣으면 API 한도를 그 자리에서 넘긴다. 목록만 먼저 적재하고, 별도 명령이 하루치씩 분석 큐에 넣는다.
아카이브를 라이브 뒤에 세운다. 큐는 created_at 오름차순으로 집는데 백필 행이 신규 공시보다 앞선다. 그대로 두면 64만 건이 먼저 처리되고 오늘 공시가 몇 달 밀린다. 접수일 30일 초과를 정렬 첫 키로 뒤에 보냈다.
한도 오류에 전 워커를 멈춘다. 한도 초과가 일반 실패로 흘러 재시도 3회를 소진하고 영구 실패가 되고 있었다. 한도는 계정 단위라 행별로 다시 넣어 봐야 busy loop다. 전용 오류로 분리해 재시도 횟수를 보존한 채 되돌리고 워커 전체를 30분 정지시킨다.
어디서 막혔나
리뷰 6라운드에서 33건이 붙었다. 세 장치가 다섯이 됐다. 하루치 페이싱을 행 수가 아니라 API 호출 수로 바꿨다. 정기보고서는 재무 API 4회에 원문 폴백 1회라 최대 5콜이다. 큐잉 시점 추정은 재시도를 못 세서 실제 호출을 하루 단위로 계수해 DB에 남기고, 예산을 넘으면 아카이브만 안 집고 라이브는 계속 가게 했다.
봇의 반박 하나가 정확했다. 한도 오류가 다른 호스트의 뷰어 폴백 성공에 덮여 정지가 영영 안 걸린다. 과거 공시일수록 뷰어가 잘 떠서 백필에서 정확히 터지는 조합이었다. 그리고 머지 5분 뒤에 프로덕션이 replica 2개라는 걸 처음 알았다. 리뷰 내내 이론으로만 다루던 시나리오였다.
완료 예상은 계속 틀렸다. 문서엔 17일이라고 썼다. 첫 회차 7,730건이 하루에 다 소화되자 14일. 다음 날 내가 API 대시보드 스크린샷을 올렸더니 일일 한도가 가정의 두 배인 40,000이었다. 자체 카운터 11,196과 대시보드 11,704가 5% 안에서 맞았다. 병목은 LLM이 아니라 예산이었다. 예산을 25,000으로 올리니 4~5일.
어떻게 풀었나
이틀 뒤 회차 시작 직후 실패가 37에서 736으로 뛰었다. 10분간 완료 0, 실패 466. 드립을 즉시 멈췄다. LLM 서버가 죽어 있었고 마지막 정상 완료는 이틀 전 오후였다. 정기보고서가 재무 API 5콜을 먼저 쓰고 LLM 제출에서 죽어서 하루치 API 호출 만 건이 헛돌았다. 스케줄러에 LLM 헬스 게이트가 없었다.
DGX 살아 있는지 확인 좀. 집 인터넷이 나갔었어.
원인은 집 인터넷이었다. 수집은 클라우드 쪽이라 누락 0이었고, 실패 1,812건을 다시 넣어 회복했다. 실효 하루 18,000건, 완료 예상 9월 5일. 닷새 사이 네 번째 숫자다.
배운 점
- 백필은 수집과 분석을 뗀다. 목록 적재는 37분, 분석은 며칠이다. 둘을 묶으면 한도를 첫날에 다 쓴다.
- 아카이브는 정렬 키로 라이브 뒤에 세운다. 상태별 우선순위 안에서만 뒤로 보내면 실패 재시도가 승격돼 앞에 선다. 정렬 첫 키여야 한다.
- 계정 단위 한도는 행 단위로 못 막는다. 전 워커 정지가 답이다. 폴백 성공이 한도 오류를 덮지 않게 오류를 먼저 전파한다.
- 페이싱은 행 수가 아니라 실제 호출 수로 센다. 추정치와 실측치를 매일 대조하니 5% 안에서 맞았고, 그 대조가 한도 가정이 틀렸음을 알려 줬다.
- 다운스트림 헬스 게이트 없이 드립을 돌리지 않는다. LLM이 죽은 하루 동안 API 예산 만 건이 사라졌다.