# KIS 오픈API 접근 토큰 발급 SMS가 뒤죽박죽인 이유

## 현상
- 한투에서 "접근 토큰이 발급되었습니다" SMS가 **날마다 시각이 다름** (예: 04:37, 19:09, 11:50, 03:57).
- 가끔 **24시간이 지난 뒤**에 발급되기도 함 (예: 주말 다음 월요일 새벽).

## 원인 요약

### 1. 발급 시점 = "만료를 처음 감지한 프로세스가 API를 호출한 시각"
- 한투 측: 토큰은 **발급 시점부터 24시간** 유효. SMS는 **실제로 발급이 일어난 순간**에만 옴.
- 우리 쪽: **어떤 프로세스가** "만료됐다"고 **언제** 판단하느냐에 따라, 그때 `/oauth2/tokenP`를 호출하고 → 그 시각에 발급 → SMS.

### 2. 여러 봇을 동시에 돌리면 시각이 제각각이 됨
- `kis_short_ver3`, `kis_scalping_ver2`, `holding_bot`, `backtest_web`(KIS 호출 시) 등이 **각자** 토큰을 사용.
- 봇 A는 새벽 4시에 시작 → 그때 캐시가 이미 만료(또는 1시간 전 이내) → **4시대에** 발급 요청 → SMS 04:37.
- 봇 B는 저녁 7시에만 API 호출 → 그날은 7시에 만료 감지 → **7시대에** 발급 → SMS 19:09.
- 따라서 **동시에 돌리는 것**이 직접 원인이라기보다, **“만료를 처음 감지하는 시점”이 프로세스/실행 시각에 따라 달라져서** 발급 시각이 들쭉날쭉해지는 것.

### 3. 갱신 기준이 스크립트마다 다름 (불일치)
| 위치 | 만료로 보는 기준 | 비고 |
|------|------------------|------|
| `kis_token_manager.ensure_token()` | 만료 **1시간 전**까지 유효하면 재사용 | 파일 잠금 사용, 중복 발급 방지 |
| `KisTokenManager.get_token()` | 만료 **10분 전**부터 갱신 시도 | ensure_token() 호출 |
| `kis_short_ver3` 등 `KISClient._auth()` | 만료 **1분 전**까지 캐시 사용, 그 외 **직접 tokenP 호출** | **잠금 없음** → 동시 발급 가능 |

→ **같은 토큰인데** “만료”로 보는 시각이 1시간 전 / 10분 전 / 1분 전으로 나뉘고,  
또 **`_auth()`는 잠금 없이 직접 발급**하므로, “누가 먼저 API를 쓰느냐”에 따라 발급 시각이 매일 달라짐.

### 4. 24시간이 지나서 발급되는 것처럼 보이는 경우
- 토큰이 **금요일 저녁**에 만료되면, 주말에 장이 없어 봇이 API를 안 쓸 수 있음.
- **월요일 장 시작 전후**에 첫 API 호출에서 만료 감지 → 그때 새 토큰 발급 → SMS는 **월요일 새벽/아침**에 옴.
- 즉 “24시간이 지나서”가 아니라, **“다음에 API를 호출한 시각”**에 발급되는 것.

## 한투 정책 (유의사항 문구)
- "접근 토큰은 **1일 1회 발급 원칙**이며, 유효기간 내 **잦은 토큰 발급** 발생 시 이용이 제한될 수 있습니다."
- 따라서 **갱신은 만료 임박 시 한 번만** 하도록 하고, **여러 프로세스가 동시에 발급하지 않도록** 하는 것이 좋음.

## 권장 대응 (코드 반영 완료)
1. **갱신 경로 통일**  
   모든 새 토큰 발급을 `kis_token_manager.ensure_token()` **한 경로**로만 하도록 수정함.  
   - `kis_short_ver3`, `kis_short_ver2`: `KISClient._auth()`에서 캐시 없/만료 시 **직접 tokenP 호출 제거** → `ensure_token(mock)` 후 캐시 재로드.  
   - `kis_scalping_ver2`, `kis_scalping_ver1`: `_init_token()`에서 캐시 없을 때 `ensure_token()` 사용.  
   - `kis_long_ver1`: 폴백 발급을 `ensure_token()`으로 대체.  
   → 발급 시 **파일 잠금** 사용·중복 발급 방지, SMS 시각이 상대적으로 안정됨.

2. **발급 시각을 고정하고 싶다면**  
   - 매일 **정해진 시간**(예: 오전 6시)에 **한 번만**  
     `python3 kis_token_manager.py --refresh`  
     를 크론으로 실행해 두면, 그 시각에만 발급 요청이 나가서 SMS 시각이 고정됨.
   - 단, 그날 그 시간 이전에 토큰이 만료되면 그 전에 다른 봇이 먼저 호출해 발급할 수는 있음.

3. **캐시 파일**  
   - 실전: `.kis_token_cache_real.json`  
   - 모의: `.kis_token_cache_mock.json`  
   - 두 파일의 `access_token_token_expired`가 **만료 시각** (한투 서버 기준 24시간 후).  
   - SMS 시각은 “그 토큰이 **발급된** 시각”이므로, 보통 만료 시각 - 24시간 정도로 생각하면 됨.

## 참고: tail_engine / scalping_engine
- `tail_engine.py`, `scalping_engine.py`는 **백테스트 전용**이라 KIS API/토큰을 사용하지 않음.  
- SMS 발급과 무관.
