콘텐츠로 이동

ADR-0060: 분 가격 수집을 전용 KIS 키로 분리한다 — 공유 호출 예산은 켜지 않는다

  • 상태: 제안됨
  • 날짜: 2026-10-08
  • 관련: ADR-0055(KIS 공유 호출 예산 — 이 ADR 이 대체하지 않는다) · ALPHA-1247 · ALPHA-1248 · ALPHA-1252

맥락

KIS 호출 한도는 한 계좌에 초당 18건이다. 분 가격 수집 워커(price-worker)는 iNAV 워커, 업종지수 워커, 장중 수급, 장 마감 배치와 KIS 키 하나를 나눠 쓰면서 한 번에 한 건씩 호출했다.

  • 지금 구성(매분 469종목)의 한 분 수집 소요는 장중 중앙값으로 58.8초다. 한 분 창을 겨우 채운다.
  • 대상 ETF 를 넓히면 매분 803종목을 받아야 한다. 한 키에 한 건씩 보내는 방식은 매분 약 500종목이 한계다.

ADR-0055는 한 키를 나눠 쓰는 호출자들의 합산 발신을 공유 호출 예산으로 통제하자고 제안했다. ETF 커버리지 확장의 선행 조건으로 나온 제안이다. 이후 두 번째 KIS 키를 확보했고, 2026-10-08 시험에서 두 키의 한도가 합쳐지지 않는다는 것을 확인해 방향을 바꿨다.

실측 (2026-10-08)

  • 한도는 계좌별로 따로다. 2번 키로 초당 15~18건을 40초 넘게 보내는 동안, 1번 키로 수집하던 운영 워커의 HTTP 500 은 창마다 0~2건으로 평소(0~3건)와 같았고 한 분 수집 소요도 평소와 같았다. 한도가 묶여 있었다면 두 키의 합이 초당 25~28건이라 거절이 크게 늘었을 것이다. 두 키는 계좌가 다르다.
  • 2번 키 단독: 초당 16건과 17건은 10초 동안 거절 0건이었다. 18건은 180건 중 1건이 거절됐다. 동시에 보낸 요청은 19건까지 통과했고 20건에서 1건이 거절됐다.
  • 1% 안팎의 드문 거절이 속도와 무관하게 섞여 나온다. 원인은 모른다.
  • 유량 거절은 HTTP 500 으로 온다. 동시 26건 중 2건이 HTTP 500 에 EGW00201 을 실어 왔다.

결정

  • 분 가격 워커만 2번 키 전용으로 둔다. 이 워커 말고는 2번 키를 쓰지 않는다. iNAV 워커, 업종지수 워커, 장중 수급, 장 마감 배치(가격·NAV·프로필·수급), 수동 백필은 1번 키에 남는다. 다만 price-worker 태스크 정의로 지난 날짜를 수동으로 돌리면 그 호출은 2번 키로 나간다.
  • 분 가격 워커는 동시 호출 4, 호출 간격 0.0625초(초당 16건)로 수집한다.
  • 초당 16건은 실측에서 거절이 없던 구간이다.
  • 동시 호출 4는 장중 응답이 느린 분(128~180ms)에도 초당 16건을 유지하기 위한 수다.
  • 계산으로는 469종목이 약 29초, 803종목이 약 50초다. 관측에서 빠듯하면 호출 간격을 초당 17건(약 47초)으로 올린다.
  • 토큰 캐시도 키별로 나눈다. 캐시에 든 토큰이 다른 키의 것이면 새로 발급해 덮어쓴다. 한 캐시를 두 키가 쓰면 서로 덮어쓰며 발급을 반복하고 발급 한도에 걸린다.
  • Terraform 변수 하나(minute_price_dedicated_kis_enabled)로 켜고 끈다. 켜면 워커의 키·토큰 캐시가 2번으로 바뀌고 전용 키 설정, 동시 호출 4, 호출 간격 0.0625초가 실린다. 끄면 1번 키에 한 건씩 보내는 방식으로 돌아간다. 분 가격 소스가 toss 인 환경에서는 KIS 를 쓰지 않으므로 켜도 바뀌는 것이 없다.
  • 공유 호출 예산은 켜지 않는다. 전용 키 변수와 call_budget_enabled 를 같이 켜면 plan 이 거부된다. 둘 다 켜지면 2번 키로 나가는 분 가격 호출이 1번 키의 예산을 쓴다.
  • 워커 코드는 전용 키 설정(dedicated_app_key)이 켜져 있을 때만 공유 호출 예산 없이 동시 호출을 허용한다. 전용 키 설정과 공유 호출 예산이 둘 다 꺼져 있으면 종전대로 한 번에 한 건이다.

분 가격 워커를 옮기는 이유는 바꿀 곳이 가장 적어서다. 이 워커만 자기 전용 환경변수로 키를 받는다. 나머지 레인은 여러 태스크가 같은 시크릿 참조를 공유한다.

대안

  • 공유 호출 예산을 켠다(ADR-0055) — 한 키의 한도를 호출자끼리 나누는 길이다. 두 키의 한도가 따로임을 확인한 뒤에는 레인을 키로 가르는 쪽을 택했다. 레인을 키로 가르면 조정할 상대가 없다.
  • 다른 레인을 2번 키로 옮긴다 — 분 가격 워커 말고는 여러 태스크가 같은 시크릿 참조를 공유하고 있어 바꿀 곳이 더 많다.
  • 아래는 하지 않기로 한 것이다.
  • 멀티시세 감시 — 멀티시세는 현재가 스냅샷이라 분봉(시가·고가·저가·종가·거래량)을 주지 않는다. 지금 분 수집과 판정은 분봉을 기준으로 한다.
  • 구성종목 수집 주기 변경 — 전용 키의 초당 16건이면 803종목을 매분 받을 수 있어(계산 약 50초) 수집 구조를 바꿀 필요가 없어졌다.
  • 한 워커가 두 키를 섞어 쓰는 것.

결과

  • 대상 ETF 를 넓힌 뒤에는 키 전환만 되돌릴 수 없다. 되돌리면 1번 키에 한 건씩 보내는 방식이고, 그 방식은 매분 약 500종목이 한계다. 목록도 같이 줄여야 한다.
  • 배포는 분 세션이 없는 시간에만 한다. 워커 둘이 같은 키로 동시에 호출하면 합산 발신이 계좌 한도를 넘을 수 있다 (초당 16건이 둘이면 32건). 배포 방식(새 태스크를 먼저 띄우고 옛 태스크를 내린다)은 바꾸지 않았다. 새 워커는 세션 fence 를 얻기 전에는 호출하지 않으므로 정상 교체에서는 겹치지 않는다고 판단했다. 코드를 읽고 내린 판단이고, 겹침을 실제로 만들어 재 보지는 않았다. 장중에 price-worker 태스크 정의로 수동 실행을 같이 돌리는 것도 같은 이유로 피한다.
  • 2번 시크릿은 Terraform 밖에서 등록했다. Terraform 은 이름(<name>/kis/oauth-2)으로 조회만 한다. 변수를 켠 환경에 그 시크릿이 없으면 plan 이 실패한다. 2번 토큰 캐시(SSM 파라미터)도 Terraform 이 만들지 않고 워커가 쓴다.
  • 유량 거절은 err_http_500 으로 본다. 창 요약 로그의 kis_EGW00201 은 본문으로 오는 거절만 센다. HTTP 500 으로 오는 거절은 운반 계층이 재시도할 뿐 이 수에 잡히지 않는다.
  • 실패했을 때의 동작
상황 동작 대응
2번 키의 드문 유량 거절(HTTP 500) 그 호출만 1초 뒤 재시도한다(이후 2초, 4초) 없음(기존 동작)
유량 거절이 이어짐 호출마다 재시도를 다 쓰고 실패한다. 종목당 약 7초가 들어 그 분의 수집이 크게 늦어진다. "5종목 연속이면 중단" 판정은 본문으로 오는 거절만 세므로 HTTP 500 으로 오는 거절에는 걸리지 않는다 호출 간격을 늘린다
HTTP 500 이 60초에 20건 이상 워커가 연결 재사용을 스스로 끈다. 호출당 시간이 늘어난다 원인을 본 뒤 워커를 재시작한다
2번 시크릿 읽기 권한 누락 워커가 기동하지 못한다 Terraform 변수를 끈다
2번 토큰 캐시 권한 누락 워커는 뜬다. 캐시를 읽고 쓰지 못해 기동할 때마다 토큰을 새로 발급한다(쓰기 실패는 경고 로그) 태스크 역할 정책에 2번 캐시를 넣는다
2번 키 자체의 장애 분 가격 수집이 선다 Terraform 변수를 끈다
  • 전환 뒤 관측 기준(3~5거래일): 한 분 수집 소요 중앙 35초 이하, 55초 초과 5% 이하, HTTP 500 이 호출의 1% 이하 (err_http_500 ÷ attempts), keep_alive_off 없음.
  • iNAV 워커의 호출 간격 단축(0.5초 → 0.25초)은 이 전환 뒤에 올린다. 전환 전에 올리면 분 가격이 남아 있는 1번 키의 설정상 발신 합이 수급 시간대에 초당 20.5건이 된다.
  • 한 분 수집 소요(약 29초, 약 50초)는 계산값이다. 전환 뒤 관측으로 확인한다.

ADR-0055 와의 관계

  • 대체하지 않는다. 분 가격 레인만 다른 길을 택한 것이다. 공유 호출 예산의 코드와 스키마는 그대로 있고, 기본값도 꺼짐이다.
  • ADR-0055 의 "기본 비활성" 문단은 "call_budget_enabled=false 이고 분봉 동시 요청은 1이다. 꺼져 있으면 terraform 은 동시 요청 변수를 싣지 않는다"고 적는다. 전용 키 변수를 켠 환경에서는 공유 호출 예산이 꺼진 채로 동시 요청 4가 실린다. 전용 키 변수가 꺼진 환경에서는 그 문단이 그대로 맞다.