튜토리얼약 5분 읽기

증권사 API 에러코드 처리 실전 — 무시하면 무인매매가 조용히 멈추는 이유

새벽 3시, 로그에는 에러코드 하나만 남아 있었다

무인 자동매매를 돌리다 보면 어느 날 로그에 낯선 에러코드 하나만 찍혀 있고, 그 뒤로 아무 일도 일어나지 않은 흔적을 보게 된다. 프로그램이 죽은 것도 아니고 재시작이 안 된 것도 아닌데, 그 시점부터 주문도 조회도 멈춰 있다. 원인을 추적해보면 대부분 하나로 좁혀진다 — 에러코드를 받긴 했는데, 그 코드에 맞는 처리 로직이 없어서 코드가 다음에 뭘 해야 할지 모른 채 가만히 있었던 것이다.

이 글은 특정 증권사의 실제 에러코드 표를 옮기지 않는다. 대신 어떤 증권사 API를 쓰든 적용할 수 있는, 에러를 분류하고 대응하는 일반화된 설계를 다룬다.

에러를 세 갈래로 나눈다 — 일시적·설정·치명적

에러코드를 하나씩 if-else로 나열하면 코드가 늘어날 때마다 무너진다. 대신 성격에 따라 세 그룹으로 나누는 편이 관리하기 쉽다.

  1. 일시적(Transient) — 네트워크 타임아웃, 서버 일시 과부하 등. 재시도로 해결될 가능성이 있다.
  2. 설정(Configuration) — 잘못된 파라미터, 권한 부족, 토큰 만료 등. 재시도해도 소용없고, 즉시 로직 점검이나 재발급이 필요하다. 토큰 만료 대응은 접근토큰 발급과 관리에서 다뤘다.
  3. 치명적(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로 나열하지 않고, "코드 → 그룹" 매핑 테이블만 유지한다는 점이다. 그룹별 처리 로직은 세 가지로 고정해두고, 새 에러코드가 나오면 매핑 테이블에 한 줄만 추가하면 된다.

로그에는 무엇을 남기고 무엇을 남기지 않을 것인가

에러 대응 로직을 만들다 보면 디버깅 편의를 위해 응답 전체를 로그에 그대로 찍고 싶은 유혹이 생긴다. 하지만 남겨야 할 것과 남기면 안 되는 것은 분리해야 한다.

자주 하는 실수 세 가지

  1. 모든 에러를 동일하게 재시도한다. 설정 오류인데 무한 재시도하면 API 호출 한도만 소진하고 문제는 그대로 남는다.
  2. 에러 그룹 없이 코드 하나하나를 하드코딩한다. 신규 에러코드가 나올 때마다 예외 케이스가 폭증해 유지보수가 어려워진다.
  3. 치명적 에러가 재시도 로직에 섞여 들어간다. 자금 관련 오류는 재시도 대상에서 명시적으로 제외해야 한다.

오늘의 정리

  1. 에러코드는 하나씩 대응하지 말고 일시적/설정/치명적 세 그룹으로 분류해 대응 로직을 단순하게 유지한다.
  2. 그룹별 대응(재시도/알림 후 중단/즉시 중단)을 고정하면 신규 에러코드가 나와도 매핑 테이블 한 줄만 추가하면 된다.
  3. 로그에는 에러코드와 대응 액션을 남기되, 인증 정보나 계좌 원문은 절대 남기지 않는다.
  4. 치명적 에러를 재시도 로직에 섞으면 안 되고, 재시도 대상에서 명시적으로 제외해야 한다.

다음 글 증권 API 레이트리밋과 재시도 설계에서는 재시도 자체를 언제, 얼마나 할지 설계하는 법을 다룬다.


이 글의 코드는 특정 증권사의 실제 에러코드나 API 응답을 담고 있지 않은 개념 설명용 의사코드입니다. 실제 연동은 반드시 해당 증권사 공식 API 문서를 기준으로 진행하시기 바랍니다. 이 글은 투자 조언이 아니며 특정 종목이나 매매기법을 추천하지 않습니다. 수익을 보장하지 않으며, 투자 손실에 대한 책임은 투자자 본인에게 있습니다.

← 전체 글 목록