한국투자증권 API 발급받고 첫 연동까지 — 초보 가이드
주식 자동매매를 만들어 보려고 검색하면 가장 먼저 만나는 게 한국투자증권 API입니다. 그런데 막상 시작하려면 "앱키가 뭐지? 토큰은 또 뭐야?" 하는 지점에서 막힙니다. 이 글은 신청부터 첫 시세 조회 성공까지, 딱 그 첫 걸음만 다룹니다.
⚠️ 이 글은 교육·정보 제공 목적입니다. 투자 권유가 아니며, 투자 손실 책임은 본인에게 있습니다.
0. 준비물 3가지
- 한국투자증권 계좌 — 비대면 개설 가능. 자동매매용으로 쓸 계좌입니다.
- 파이썬 3.9 이상 —
requests라이브러리만 있으면 됩니다. - 모의투자 신청 — 실전 계좌로 바로 시작하지 마세요. 모의투자는 실제 돈이 나가지 않는 연습용 환경입니다.
1. API 신청과 앱키 발급
KIS 개발자센터에서 "OpenAPI 신청"을 하면 계좌마다 두 개의 문자열을 줍니다.
- APP KEY — 내 프로그램의 아이디에 해당
- APP SECRET — 그 아이디의 비밀번호에 해당
여기서 초보자가 가장 많이 하는 실수가 있습니다. 이 두 값을 코드에 그대로 적어두는 것입니다. 깃허브에 올리는 순간 남이 내 계좌 API를 쓸 수 있습니다. 반드시 별도 설정 파일이나 환경변수로 빼세요.
import os
# 환경변수에서 읽기 (코드에 직접 쓰지 않기)
APP_KEY = os.environ["KIS_APP_KEY"]
APP_SECRET = os.environ["KIS_APP_SECRET"]
ACCOUNT_NO = os.environ["KIS_ACCOUNT_NO"] # 8자리-2자리 형식
# 모의투자 서버 주소 (실전과 주소가 다릅니다)
BASE_URL = "https://openapivts.koreainvestment.com:29443"
모의투자와 실전은 도메인 주소부터 다릅니다. 연습 중인데 실전 주소를 쓰면 인증이 통과되지 않습니다. 반대로 실전 주소에 모의 키를 넣어도 마찬가지입니다.
2. 접근 토큰(Access Token) 받기
앱키만으로는 시세를 조회할 수 없습니다. 앱키를 내밀고 출입증을 하나 받아야 하는데, 그게 접근 토큰입니다. 유효기간은 약 24시간입니다.
import requests
def get_access_token():
url = f"{BASE_URL}/oauth2/tokenP"
body = {
"grant_type": "client_credentials",
"appkey": APP_KEY,
"appsecret": APP_SECRET,
}
res = requests.post(url, json=body, timeout=10)
res.raise_for_status() # HTTP 오류면 여기서 예외 발생
return res.json()["access_token"]
token = get_access_token()
print("토큰 앞 10자리:", token[:10]) # 전체를 로그에 찍지 마세요
토큰 전체를 콘솔이나 로그 파일에 출력하는 습관은 위험합니다. 확인용이라면 앞 몇 자리만 찍으세요.
또 하나 — 토큰 발급은 하루에 호출할 수 있는 횟수 제한이 있습니다. 코드를 실행할 때마다 새로 받으면 금방 막힙니다. 받은 토큰은 파일에 저장해 두고, 날짜가 바뀌었을 때만 다시 받는 게 정석입니다.
import json, datetime, pathlib
CACHE = pathlib.Path("token_cache.json") # .gitignore에 추가할 것
def load_token():
today = datetime.date.today().isoformat()
if CACHE.exists():
data = json.loads(CACHE.read_text())
if data.get("date") == today:
return data["token"] # 오늘 받은 토큰 재사용
token = get_access_token()
CACHE.write_text(json.dumps({"date": today, "token": token}))
return token
3. 첫 시세 조회 — 삼성전자 현재가
이제 출입증을 들고 실제 데이터를 요청합니다. KIS API는 tr_id라는 값으로 "어떤 기능을 부를지"를 구분합니다. 기능마다 이 값이 다르고, 모의/실전도 다른 경우가 있어 문서 확인이 필수입니다.
def get_price(token, code="005930"): # 005930 = 삼성전자
url = f"{BASE_URL}/uapi/domestic-stock/v1/quotations/inquire-price"
headers = {
"authorization": f"Bearer {token}",
"appkey": APP_KEY,
"appsecret": APP_SECRET,
"tr_id": "FHKST01010100", # 주식 현재가 시세
}
params = {
"FID_COND_MRKT_DIV_CODE": "J", # J = 주식
"FID_INPUT_ISCD": code,
}
res = requests.get(url, headers=headers, params=params, timeout=10)
res.raise_for_status()
out = res.json()["output"]
return {
"종목명": out["hts_kor_isnm"],
"현재가": int(out["stck_prpr"]),
"등락률": float(out["prdy_ctrt"]),
}
print(get_price(load_token()))
# {'종목명': '삼성전자', '현재가': 71000, '등락률': 0.85}
여기까지 출력이 나왔다면 연동은 성공입니다. 나머지는 전부 이 패턴의 반복입니다 — URL 바꾸고, tr_id 바꾸고, 파라미터 바꾸기.
4. 처음에 꼭 만나는 오류 3가지
- EGW00123 / 유효하지 않은 토큰 — 토큰이 만료됐거나, 모의 토큰을 실전 주소에 쓴 경우입니다. 주소와 키의 짝을 먼저 확인하세요.
- tr_id 오류 — 기능은 맞는데 모의투자용 tr_id를 쓰지 않은 경우가 흔합니다. 일부 tr_id는 앞자리가 다릅니다.
- 초당 호출 제한 초과 — 반복문으로 종목 100개를 쉬지 않고 돌리면 막힙니다. 호출 사이에
time.sleep(0.2)정도를 넣어 간격을 두세요.
5. 다음 단계
첫 조회가 되면 자연스럽게 이어지는 순서가 있습니다.
- 여러 종목을 반복 조회하고 결과를 CSV로 저장하기
- 저장한 데이터로 이동평균 같은 지표 계산해 보기
- 조건이 맞을 때 주문 대신 로그만 남기는 모의 실행 만들기
- 충분히 검증한 뒤에야 모의투자 주문 API 붙이기
3번을 건너뛰고 바로 주문 코드를 붙이는 게 초보자의 가장 비싼 실수입니다. 주문은 마지막에 붙이세요.
정리
- 앱키·앱시크릿은 환경변수로. 코드에 박지 않기
- 모의와 실전은 주소·tr_id가 다름 — 짝을 맞출 것
- 토큰은 24시간짜리 출입증, 캐시해서 재사용
- 첫 목표는 "현재가 출력 성공" 하나면 충분
- 주문 API는 가장 마지막에
API 연동은 어렵다기보다 낯설 뿐입니다. 현재가 하나 찍히는 순간부터는 그냥 평범한 HTTP 프로그래밍입니다.
댓글
댓글 쓰기