증권사 API 에러코드 처리 실전 — 무시하면 무인매매가 조용히 멈추는 이유
새벽 3시, 로그에는 에러코드 하나만 남아 있었다
무인 자동매매를 돌리다 보면 어느 날 로그에 낯선 에러코드 하나만 찍혀 있고, 그 뒤로 아무 일도 일어나지 않은 흔적을 보게 된다. 프로그램이 죽은 것도 아니고 재시작이 안 된 것도 아닌데, 그 시점부터 주문도 조회도 멈춰 있다. 원인을 추적해보면 대부분 하나로 좁혀진다 — 에러코드를 받긴 했는데, 그 코드에 맞는 처리 로직이 없어서 코드가 다음에 뭘 해야 할지 모른 채 가만히 있었던 것이다.
이 글은 특정 증권사의 실제 에러코드 표를 옮기지 않는다. 대신 어떤 증권사 API를 쓰든 적용할 수 있는, 에러를 분류하고 대응하는 일반화된 설계를 다룬다.
에러를 세 갈래로 나눈다 — 일시적·설정·치명적
에러코드를 하나씩 if-else로 나열하면 코드가 늘어날 때마다 무너진다. 대신 성격에 따라 세 그룹으로 나누는 편이 관리하기 쉽다.
- 일시적(Transient) — 네트워크 타임아웃, 서버 일시 과부하 등. 재시도로 해결될 가능성이 있다.
- 설정(Configuration) — 잘못된 파라미터, 권한 부족, 토큰 만료 등. 재시도해도 소용없고, 즉시 로직 점검이나 재발급이 필요하다. 토큰 만료 대응은 접근토큰 발급과 관리에서 다뤘다.
- 치명적(Fatal) — 계좌 상태 이상, 자금 부족으로 인한 주문 거부 등. 재시도 대상이 아니며 즉시 중단하고 알림을 보내야 한다.
에러코드 대응을 표 대신 매핑 함수로 만든다
python 코드 보기
def classify_error(code: str) -> str:
if code in TRANSIENT_CODES:
return "retry"
if code in CONFIG_CODES:
return "fix_and_alert"
return "fatal_stop"
def handle_response(response):
if response.is_success:
return response.data
action = classify_error(response.error_code)
if action == "retry":
return retry_with_backoff(response.request)
elif action == "fix_and_alert":
notify("설정 오류 감지 - 즉시 확인 필요")
raise ConfigError(response.error_code)
else:
notify("치명적 오류 - 매매 중단")
raise FatalTradingError(response.error_code)여기서 중요한 건 코드 하나하나를 case로 나열하지 않고, "코드 → 그룹" 매핑 테이블만 유지한다는 점이다. 그룹별 처리 로직은 세 가지로 고정해두고, 새 에러코드가 나오면 매핑 테이블에 한 줄만 추가하면 된다.
로그에는 무엇을 남기고 무엇을 남기지 않을 것인가
에러 대응 로직을 만들다 보면 디버깅 편의를 위해 응답 전체를 로그에 그대로 찍고 싶은 유혹이 생긴다. 하지만 남겨야 할 것과 남기면 안 되는 것은 분리해야 한다.
- 남길 것: 에러코드, 발생 시각, 어떤 종류의 요청이었는지(주문/조회 등), 어떤 대응 액션을 취했는지.
- 남기지 않을 것: 인증 토큰, API 키, 계좌번호 원문 같은 민감정보. 이 정보가 로그 파일에 그대로 남으면 그 자체로 새로운 보안 위험이 된다.
자주 하는 실수 세 가지
- 모든 에러를 동일하게 재시도한다. 설정 오류인데 무한 재시도하면 API 호출 한도만 소진하고 문제는 그대로 남는다.
- 에러 그룹 없이 코드 하나하나를 하드코딩한다. 신규 에러코드가 나올 때마다 예외 케이스가 폭증해 유지보수가 어려워진다.
- 치명적 에러가 재시도 로직에 섞여 들어간다. 자금 관련 오류는 재시도 대상에서 명시적으로 제외해야 한다.
오늘의 정리
- 에러코드는 하나씩 대응하지 말고 일시적/설정/치명적 세 그룹으로 분류해 대응 로직을 단순하게 유지한다.
- 그룹별 대응(재시도/알림 후 중단/즉시 중단)을 고정하면 신규 에러코드가 나와도 매핑 테이블 한 줄만 추가하면 된다.
- 로그에는 에러코드와 대응 액션을 남기되, 인증 정보나 계좌 원문은 절대 남기지 않는다.
- 치명적 에러를 재시도 로직에 섞으면 안 되고, 재시도 대상에서 명시적으로 제외해야 한다.
다음 글 증권 API 레이트리밋과 재시도 설계에서는 재시도 자체를 언제, 얼마나 할지 설계하는 법을 다룬다.
이 글의 코드는 특정 증권사의 실제 에러코드나 API 응답을 담고 있지 않은 개념 설명용 의사코드입니다. 실제 연동은 반드시 해당 증권사 공식 API 문서를 기준으로 진행하시기 바랍니다. 이 글은 투자 조언이 아니며 특정 종목이나 매매기법을 추천하지 않습니다. 수익을 보장하지 않으며, 투자 손실에 대한 책임은 투자자 본인에게 있습니다.