증권사 OpenAPI 인증 토큰 자동 갱신 설계
증권사 OpenAPI로 자동매매를 하려면, 사람이 자는 사이에도 인증이 살아 있어야 합니다. 한국투자증권(KIS) OpenAPI를 쓰며 정리한 토큰 수명 관리의 실전 노트입니다. 핵심은 "토큰은 언젠가 만료된다"를 코드가 항상 의식하게 만드는 것입니다.
⚠️ 이 글은 교육·정보 제공 목적입니다. 투자 권유가 아니며, 투자 손실 책임은 본인에게 있습니다.
두 종류의 자격증명
KIS OpenAPI는 성격이 다른 두 개의 키를 씁니다.
- access token — REST 주문·조회에 쓰는 Bearer 토큰.
client_credentials방식으로 발급하며 수명이 있습니다(약 24시간). - approval key — 실시간 시세 WebSocket 접속에 쓰는 별도 키.
이 둘을 헷갈리면 "REST는 되는데 실시간이 안 붙는" 상황을 만나게 됩니다. 용도가 완전히 다릅니다.
access token 발급
발급은 앱키·앱시크릿을 실어 토큰 엔드포인트에 POST 하는 단순한 요청입니다.
func (kis *KISClient) GetAccessToken() error {
kis.mu.Lock()
defer kis.mu.Unlock()
payload := map[string]string{
"grant_type": "client_credentials",
"appkey": kis.AppKey, // 하드코딩 금지 — 설정/환경변수에서 로드
"appsecret": kis.AppSecret,
}
// POST /oauth2/tokenP ...
kis.Authorization = "Bearer " + tokenResp.AccessToken
kis.AuthDay = time.Now().Format("20060102") // 발급 '날짜' 기록
return nil
}
여기서 앱키·앱시크릿은 절대 소스에 박아두지 않습니다. 설정 파일이나 환경변수에서 읽고, 저장할 때는 암호화하는 것이 기본입니다.
핵심: 매 요청 전에 토큰 신선도 확인
가장 중요한 패턴입니다. 모든 API 호출 직전에 토큰이 오늘 것인지 확인하고, 아니면 재발급합니다.
// 토큰이 없거나, 발급 날짜가 오늘이 아니면 재발급
if kis.Authorization == "" || kis.AuthDay != time.Now().Format("20060102") {
if err := kis.GetAccessToken(); err != nil {
return nil, err
}
}
날짜 기반 검사는 단순하지만 강력합니다. 자정을 넘겨 토큰이 만료되는 시점을, 다음 첫 요청이 자연스럽게 감지해 새로 받아옵니다. 여기에 더해, 장 시작 전(예: 08:05) 토큰을 선제적으로 한 번 갱신하는 스케줄을 두면, 개장 직후 첫 주문에서 재발급 지연이 끼어드는 것을 막을 수 있습니다.
갱신 실패는 곧 정지
토큰 재발급에 실패했는데 봇이 계속 돈다면, 그 뒤의 모든 주문·조회가 인증 오류로 줄줄이 실패합니다. 그래서 원칙은 명확합니다 — 갱신 실패 시 매매를 멈추고 즉시 알린다.
if err := kis.GetAccessToken(); err != nil {
stopTrading() // 신규 진입 차단
notify("🚨 토큰 갱신 실패 — 봇 정지: " + err.Error())
return err
}
"조용히 재시도만 반복"은 위험합니다. 인증이 깨진 상태를 사람이 모르는 채로 장이 흘러가는 게 최악입니다. 멈추고, 알리고, 사람이 개입하게 하라.
정리
- access token(REST)과 approval key(실시간)는 용도가 다른 별개 키
- 앱키·앱시크릿은 소스에 박지 말고 설정/환경변수 + 암호화
- 모든 요청 전에 날짜 기반으로 토큰 신선도 확인 후 필요 시 재발급
- 장 시작 전 선제 갱신으로 개장 직후 지연 제거
- 갱신 실패 = 매매 정지 + 알림 — 조용한 재시도 금지
인증은 화려하지 않지만, 무너지면 봇 전체가 무너집니다. 토큰 수명을 코드가 늘 의식하게 만드는 것, 그게 무인 운영의 첫 단추입니다.
댓글
댓글 쓰기