한국 금융 데이터 API 생태계 총정리
마이데이터, 증권사 Open API, DART, pykrx 등 한국 금융 데이터 수집 방법 총정리
토스와 뱅크샐러드는 어떻게 모든 금융 데이터를 볼 수 있을까? 그리고 개인 개발자는 왜 그렇게 할 수 없을까?
한국 금융 데이터 생태계 구조
한국에서 금융 데이터에 접근하는 경로는 크게 네 가지로 나뉜다.
┌─────────────────────────────────────────────────────────┐
│ 정부/규제 기관 │
│ 금융위원회 ─── 금융감독원 ─── 금융보안원 ─── 금융결제원 │
└───────────┬──────────────────┬──────────────────┬────────┘
│ │ │
┌───────▼───────┐ ┌──────▼──────┐ ┌───────▼───────┐
│ 마이데이터 API │ │ 오픈뱅킹 API │ │ 증권사 Open API│
│ (사업자 허가) │ │ (사업자 등록) │ │ (개인 사용 가능)│
└───────┬───────┘ └──────┬──────┘ └───────┬───────┘
│ │ │
┌───────▼───────┐ ┌──────▼──────┐ ┌───────▼───────┐
│ 토스, 뱅크샐러드│ │ 핀테크 앱 │ │ 개인 투자자 │
│ 카카오페이 등 │ │ 페이 서비스 │ │ 알고리즘 트레이더│
└───────────────┘ └─────────────┘ └───────────────┘
│
┌───────▼───────┐
│ CODEF (중개) │ ← 스크래핑+API 하이브리드
└───────────────┘각 경로별 접근 가능성을 요약하면 다음과 같다.
| 방법 | 접근성 | 데이터 범위 | 비용 | 개인 사용 |
|---|---|---|---|---|
| 마이데이터 API | 매우 낮음 (허가 필요) | 전 금융기관 | 자본금 5억+ | 불가 |
| 오픈뱅킹 API | 낮음 (사업자 필요) | 은행 계좌만 | 사용료 + 심사비용 | 불가 |
| 증권사 Open API | 높음 (계좌만 필요) | 해당 증권사 계좌 | 무료 | 가능 |
| CODEF API (데모) | 중간 (회원가입) | 은행/카드/증권/보험 | 3개월 무료 | 가능 |
| pykrx | 매우 높음 | 시세 데이터만 | 무료 | 가능 |
마이데이터(MyData) 제도
법적 근거
마이데이터는 신용정보의 이용 및 보호에 관한 법률 (개정 신용정보법, 2020.08 시행)에 근거한다. 제22조의9(본인신용정보관리업)이 핵심 조항이다.
- 금융위원회가 허가를 심사한다
- 금융감독원이 감독한다
- 금융보안원이 기술 표준(API 규격)을 제정하고 테스트베드를 운영한다
조회 가능 데이터
마이데이터 사업자가 되면 접근할 수 있는 데이터 범위는 상당히 넓다.
| 업권 | 주요 조회 데이터 |
|---|---|
| 은행 | 예적금 계좌 잔액/거래내역, 대출 잔액/금리/상환정보 |
| 카드 | 카드 결제내역, 청구금액, 포인트/리워드 현황 |
| 증권(금융투자) | 주식 보유수량/매입금액/평가금액, 펀드 투자원금/잔액 |
| 보험 | 보험 주계약/특약, 보험료 납입내역, 해지환급금 |
| 전자금융 | 전자금융 계좌정보 |
| 할부금융/캐피탈 | 할부금융 잔액, 리스 정보 |
| 통신 | 통신요금, 멤버십 포인트 |
| P2P | P2P 투자/대출 정보 |
API 표준 스펙
| 항목 | 사양 |
|---|---|
| 통신 방식 | REST API (HTTPS) |
| 보안 | TLS 1.3 이상, 상호인증(mTLS) |
| 데이터 형식 | JSON |
| 인증 | OAuth 2.0 기반 통합인증 |
| URI 구조 | <base_path>/<version>/<industry>/<resource> |
| URI 예시 | /v1/bank/accounts, /v1/card/bills, /v1/invest/accounts |
| 테스트베드 | https://developers.mydatakorea.org |
마이데이터 2.0 (2025.06 시행)
2025년 6월 시행된 마이데이터 2.0의 핵심 변경사항이다.
| 항목 | 기존 (1.0) | 변경 (2.0) |
|---|---|---|
| 동의 방식 | 금융기관별 개별 인증/동의 | 한 번의 동의로 전체 자산 일괄 조회 |
| 조회 방식 | 이용자가 기관 일일이 선택 | 전체 자동 수집, 원치 않는 기관만 제외 (옵트아웃) |
| 기관 수 제한 | 한번에 최대 50개 기관 | 제한 없음 |
| 이용 채널 | 모바일 앱만 | 영업점 대면 채널도 가능 |
| 이용 연령 | 만 19세 이상 | 만 14세 이상 |
| 가입 유효기간 | 1년 | 1~5년 선택 가능 |
| 참여 사업자 | 제한적 | 27개 사업자 참여 |
개인 개발자는 왜 사용할 수 없는가
결론: 개인 개발자는 마이데이터 API를 직접 사용할 수 없다.
마이데이터 사업자 허가 요건을 보면 이유가 명확하다.
- 최소 자본금: 5억원
- 물적 설비: 정보처리/통신 설비 구축 필요 (클라우드 허용)
- 주요 출자자 건전성: 금융위원회 심사
- 사업계획 타당성: 금융위원회 심사
- 정보보호: 충분한 정보보호 담당자 권장
- 허가 주체: 금융위원회
- 감독 기관: 금융감독원
개인이나 소규모 스타트업이 진입하기에는 자본금, 규제 준수 비용 등 장벽이 매우 높다. 토스, 뱅크샐러드, 카카오페이 같은 서비스가 전 금융기관 데이터를 통합 조회할 수 있는 이유는 마이데이터 사업자 허가를 취득한 법인이기 때문이다.
오픈뱅킹(Open Banking)
개요
| 항목 | 내용 |
|---|---|
| 운영 주체 | 금융결제원 (KFTC) |
| 목적 | 하나의 앱에서 모든 은행 계좌를 조회/이체 |
| 참가 기관 | 은행 + 제2금융권 |
| 개발자 사이트 | https://developers.kftc.or.kr/dev |
조회 가능 데이터
| 기능 | 설명 |
|---|---|
| 잔액 조회 | 본인 계좌의 잔액 및 출금가능금액 |
| 거래내역 조회 | 본인 계좌의 거래내역 (페이지당 최대 25건) |
| 계좌 실명 조회 | 출금이체 계좌의 정상여부 및 실명 확인 |
| 수취인 조회 | 입금이체 시 수취계좌의 입금가능여부 |
| 출금/입금 이체 | 등록된 계좌에서 출금/입금 |
접근 절차
- 오픈뱅킹 사업 참여 자격 확인
- 이용기관 등록 신청
- 테스트베드에서 API 연동 검증
- 보안 심사 통과
- 정식 서비스 개시 심사 통과
- 실거래 환경 API 사용 개시
결론: 개인 사용 불가. 최소 개인사업자 이상이 필요하며, 보안 심사가 매우 엄격하다.
증권사 Open API
개인 개발자에게 가장 현실적인 선택지다. 계좌만 있으면 무료로 사용할 수 있다.
REST API 제공 증권사 (크로스플랫폼)
| 증권사 | API 명칭 | 출시 시기 | 개발자 사이트 |
|---|---|---|---|
| 한국투자증권 | KIS Developers | 2022.04 | https://apiportal.koreainvestment.com |
| 키움증권 | 키움 REST API | 2025.03 | https://openapi.kiwoom.com |
| LS증권 | LS Open API | — | https://openapi.ls-sec.co.kr |
레거시 API 제공 증권사 (Windows 전용)
| 증권사 | API 명칭 | 유형 | 요청 제한 |
|---|---|---|---|
| 키움증권 | Open API+ | OCX | 초당 5회, 시간당 1,000회 |
| 대신증권 | 크레온 API (Creon) | COM | 초당 약 4회 |
| LS증권 (구 이베스트) | Xing API | COM/DLL | 초당 10회 |
상세 비교
| 항목 | 한국투자증권 | 키움증권 (REST) | LS증권 | 대신증권 |
|---|---|---|---|---|
| API 방식 | REST | REST | REST | COM (Windows) |
| OS 지원 | macOS/Linux/Windows | macOS/Linux/Windows | macOS/Linux/Windows | Windows 전용 |
| 국내주식 | O | O | O | O |
| 해외주식 | O | O | O | O |
| 실시간 시세 | WebSocket | 지원 | 지원 | 지원 |
| 모의투자 | O | O | O | O |
| Python 라이브러리 | python-kis, pykis | kiwoom-rest-api | ls-openapi | 공식 없음 |
| 문서화 | 우수 | 양호 | 양호 | 양호 |
| 커뮤니티 | 활발 | 대형 (점유율 1위) | 보통 | 보통 |
REST API가 없는 주요 증권사
다음 증권사들은 Open API를 제공하지 않거나 일반 트레이딩 API가 없다.
- 미래에셋증권: Open API 미제공
- 삼성증권: Open API 미제공
- NH투자증권: Open API 미제공
- 신한투자증권: 마이데이터 API만 제공
키움증권 REST API (2025.03 출시)
키움증권이 2025년 3월 REST API를 출시하면서 한국투자증권과 함께 크로스플랫폼(macOS, Linux, Windows)을 지원하게 되었다. 국내 주식시장 점유율 1위 증권사라 사용자 기반이 넓다는 장점이 있다. 기존 OCX 방식의 Open API+도 병행 운영한다.
외부 데이터 소스
증권사 API 외에도 시세, 공시, 뉴스 등 다양한 금융 데이터를 수집할 수 있는 소스가 있다.
데이터 소스 비교
| 소스 | 대상 시장 | 데이터 유형 | 인증 | 무료 한도 | 추천도 |
|---|---|---|---|---|---|
| DART API | 한국 | 공시정보 | API Key | 일 10,000건 | 매우 높음 |
| KIND (크롤링) | 한국 | 거래소 공시 | 없음 | 제한 없음 | 보통 |
| 네이버 증권 (크롤링) | 한국 | 종목뉴스 | 없음 | 비공식 | 보통 |
| Finnhub API | 미국 | 뉴스 + 감성분석 | API Key | 60콜/분 | 매우 높음 |
| yfinance | 미국 | 뉴스/시세 | 없음 | 비공식 | 낮음 |
| KIS API 거래량순위 | 한국/미국 | 거래량 순위 | OAuth2 | 초당 20건 | 매우 높음 |
DART API (금융감독원 전자공시)
DART는 한국 상장기업 공시 정보를 제공하는 공식 API다.
| 항목 | 값 |
|---|---|
| 기본 URL | https://opendart.fss.or.kr/api/ |
| 인증 | Query Parameter crtfc_key |
| 응답 형식 | JSON / XML |
| Rate Limit | 일 10,000건 (개인) |
| API Key 발급 | https://opendart.fss.or.kr 회원가입 후 인증키 신청 |
주요 엔드포인트
# 공시목록 조회 (핵심)
GET /api/list.json?crtfc_key={key}&corp_code=00126380&bgn_de=20260201
# 기업개황 조회
GET /api/company.json?crtfc_key={key}&corp_code=00126380
# 고유번호 다운로드 (종목코드 매핑)
GET /api/corpCode.xml?crtfc_key={key}
# 단일회사 재무제표
GET /api/fnlttSinglAcnt.json?crtfc_key={key}&corp_code=00126380공시목록 주요 파라미터
| 파라미터 | 설명 | 예시 |
|---|---|---|
corp_code | 고유번호 (8자리) | 00126380 (삼성전자) |
bgn_de / end_de | 시작일 / 종료일 | 20260201 / 20260219 |
pblntf_ty | 공시유형 | A:정기공시, B:주요사항, C:발행공시, D:지분공시 |
corp_cls | 법인구분 | Y:유가, K:코스닥 |
corp_code미지정 시 검색 기간은 최대 3개월로 제한된다.
Python 구현
import aiohttp
DART_BASE_URL = "https://opendart.fss.or.kr/api"
async def fetch_dart_disclosures(
api_key: str,
corp_code: str | None = None,
bgn_de: str = "",
end_de: str = "",
pblntf_ty: str = "",
page_count: int = 100,
) -> dict:
"""DART 공시목록 조회."""
params = {
"crtfc_key": api_key,
"page_count": str(page_count),
}
if corp_code:
params["corp_code"] = corp_code
if bgn_de:
params["bgn_de"] = bgn_de
if end_de:
params["end_de"] = end_de
if pblntf_ty:
params["pblntf_ty"] = pblntf_ty
async with aiohttp.ClientSession() as session:
async with session.get(
f"{DART_BASE_URL}/list.json", params=params
) as resp:
resp.raise_for_status()
data = await resp.json()
if data.get("status") != "000":
raise Exception(f"DART API Error: {data.get('message')}")
return dataPython 라이브러리로는 dart-fss와 OpenDartReader가 있다.
Finnhub API (미국 뉴스 + 감성분석)
미국 주식 뉴스와 감성분석을 제공하는 API로, 무료 티어에서 60콜/분을 지원한다.
| 항목 | 값 |
|---|---|
| 기본 URL | https://finnhub.io/api/v1/ |
| 인증 | Header X-Finnhub-Token 또는 Query token= |
| 무료 Rate Limit | 60 API 콜/분 (내부 30콜/초 제한) |
| API Key 발급 | https://finnhub.io 회원가입 |
핵심 엔드포인트
Company News — 종목별 뉴스:
GET /api/v1/company-news?symbol=AAPL&from=2026-02-01&to=2026-02-19&token={key}응답에는 headline, summary, source, url, datetime 등이 포함된다.
News Sentiment — 감성분석:
GET /api/v1/news-sentiment?symbol=AAPL&token={key}{
"symbol": "AAPL",
"companyNewsScore": 0.75,
"sectorAverageNewsScore": 0.52,
"sentiment": {
"bullishPercent": 0.82,
"bearishPercent": 0.18
},
"buzz": {
"articlesInLastWeek": 45,
"weeklyAverage": 30.5,
"buzz": 1.47
}
}| 필드 | 설명 |
|---|---|
companyNewsScore | 종합 뉴스 점수 (0~1) |
bullishPercent | 긍정 뉴스 비율 |
bearishPercent | 부정 뉴스 비율 |
buzz.buzz | 버즈 비율 (현재/평균) — 1.0 이상이면 평소보다 화제 |
Python 구현
import aiohttp
from datetime import datetime, timedelta
FINNHUB_BASE_URL = "https://finnhub.io/api/v1"
async def fetch_company_news(
api_key: str,
symbol: str,
days: int = 7,
) -> list[dict]:
"""Finnhub 종목별 뉴스 조회."""
end_date = datetime.now().strftime("%Y-%m-%d")
start_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
async with aiohttp.ClientSession() as session:
async with session.get(
f"{FINNHUB_BASE_URL}/company-news",
params={
"symbol": symbol,
"from": start_date,
"to": end_date,
"token": api_key,
},
) as resp:
resp.raise_for_status()
return await resp.json()
async def fetch_news_sentiment(api_key: str, symbol: str) -> dict:
"""Finnhub 뉴스 감성분석 조회."""
async with aiohttp.ClientSession() as session:
async with session.get(
f"{FINNHUB_BASE_URL}/news-sentiment",
params={"symbol": symbol, "token": api_key},
) as resp:
resp.raise_for_status()
return await resp.json()무료 티어 사용 전략
- 60콜/분 = 초당 1건 페이스
- 10종목 뉴스 + 감성분석 = 20콜 (1분 내 충분)
- 10분 주기로 종목 30개를 스캔하면 31콜/10분으로 여유롭다
- 유료 업그레이드는 월 $49.99 (Market Data Basic)
네이버 증권 (웹 크롤링)
네이버 증권은 공식 API를 제공하지 않으므로 웹 크롤링이 필요하다. 네이버 뉴스 RSS는 2020년 10월 서비스가 종료되었다.
import aiohttp
from bs4 import BeautifulSoup
async def fetch_naver_stock_news(stock_code: str, page: int = 1) -> list[dict]:
"""네이버 증권 종목뉴스 크롤링."""
url = (
f"https://finance.naver.com/item/news_news.naver"
f"?code={stock_code}&page={page}"
)
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36",
}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as resp:
html = await resp.text()
soup = BeautifulSoup(html, "html.parser")
results = []
rows = soup.select("table.type2 tbody tr")
for row in rows:
title_td = row.select_one("td.title")
date_td = row.select_one("td.date")
if title_td and title_td.a:
results.append({
"title": title_td.a.get_text(strip=True),
"url": "https://finance.naver.com" + title_td.a["href"],
"date": date_td.get_text(strip=True) if date_td else "",
})
return results주의: User-Agent 설정 필수, 요청 간 0.5~1초 딜레이 권장, HTML 구조 변경 시 파싱 코드 업데이트 필요.
yfinance
yfinance는 비공식 라이브러리로, 가격/재무 데이터 조회에는 유용하지만 뉴스 기능의 신뢰성은 낮다. 2024년 3월부터 종목 관련 뉴스가 아닌 Yahoo Finance 메인 페이지 뉴스를 반환하는 이슈가 보고되었다 (GitHub Issue #1956). 뉴스 데이터는 Finnhub을 주력으로 사용하는 것을 권장한다.
KIS API 거래량 순위
한국투자증권 API에서 제공하는 거래량 순위 조회. 국내/해외 모두 최대 30건을 반환한다.
| 시장 | tr_id | 엔드포인트 |
|---|---|---|
| 국내 | FHPST01710000 | /uapi/domestic-stock/v1/quotations/volume-rank |
| 해외 | HHDFS76310010 | /uapi/overseas-stock/v1/ranking/trade-vol |
async def get_domestic_volume_ranking(
client: "KISClient",
market: str = "0000", # 0000:전체, 0001:코스피, 1001:코스닥
sort_by: str = "0", # 0:평균거래량, 3:거래금액순
) -> list[dict]:
"""국내주식 거래량순위 조회."""
data = await client.get(
path="/uapi/domestic-stock/v1/quotations/volume-rank",
tr_id="FHPST01710000",
params={
"FID_COND_MRKT_DIV_CODE": "J",
"FID_COND_SCR_DIV_CODE": "20171",
"FID_INPUT_ISCD": market,
"FID_DIV_CLS_CODE": "0",
"FID_BLNG_CLS_CODE": sort_by,
"FID_TRGT_CLS_CODE": "111111111",
"FID_TRGT_EXLS_CLS_CODE": "000000",
"FID_INPUT_PRICE_1": "",
"FID_INPUT_PRICE_2": "",
"FID_VOL_CNT": "",
"FID_INPUT_DATE_1": "",
},
)
items = data.get("output", [])
return [
{
"rank": int(item.get("data_rank", 0)),
"code": item.get("mksc_shrn_iscd", "").strip(),
"name": item.get("hts_kor_isnm", ""),
"price": int(item.get("stck_prpr", 0)),
"change_rate": float(item.get("prdy_ctrt", 0)),
"volume": int(item.get("acml_vol", 0)),
"trade_amount": int(item.get("acml_tr_pbmn", 0)),
}
for item in items
if item.get("mksc_shrn_iscd", "").strip()
]개인 개발자를 위한 현실적 대안
CODEF API
CODEF는 스크래핑 + API 하이브리드 방식으로 은행/카드/증권/보험 데이터를 조회할 수 있는 중개 플랫폼이다.
| 구분 | 데모 | 정식 |
|---|---|---|
| 기간 | 3개월 | 무제한 |
| 일 호출 | 100회 | 무제한 |
| 비용 | 무료 | 월 구독 (건당 과금) |
| 사업자 | 불필요 | 필요 |
from easycodefpy import Codef
codef = Codef()
codef.public_key = "YOUR_PUBLIC_KEY"
# 은행 보유 계좌 조회
result = codef.request_product(
"/v1/kr/bank/p/account/account-list",
service_type=0,
param={
"organization": "0004", # KB국민은행
"loginType": "0",
"id": "user_id",
"password": "encrypted_password"
}
)주의: CODEF는 사용자의 인터넷뱅킹 ID/PW가 필요하다. 보안상 본인 계정만 사용해야 한다.
pykrx
시세/차트 데이터만 필요하다면 pykrx가 가장 간단하다. KRX 거래소 데이터를 스크래핑하며, 계좌 없이 무료로 사용할 수 있다. FinanceDataReader도 비슷한 역할을 한다.
추천 전략
단기 (현재):
- KIS API를 기본으로 사용한다 (이미 구현된 경우)
- pykrx, FinanceDataReader로 시세 데이터를 보완한다
- DART API로 공시 정보를 수집한다
- Finnhub으로 해외 뉴스/감성분석을 수집한다
중기 (확장 시):
- 키움 REST API를 추가하여 멀티 증권사 연동을 구현한다
- BrokerInterface 추상화로 여러 증권사를 통합한다
class BrokerInterface(ABC):
@abstractmethod
async def get_balance(self) -> Balance: ...
@abstractmethod
async def get_positions(self) -> list[Position]: ...
@abstractmethod
async def place_order(self, order: Order) -> OrderResult: ...
class KISBroker(BrokerInterface): ...
class KiwoomBroker(BrokerInterface): ...
class LSBroker(BrokerInterface): ...
class BrokerAggregator:
"""여러 증권사 계좌 통합 조회."""
def __init__(self, brokers: list[BrokerInterface]):
self.brokers = brokers
async def get_total_portfolio(self) -> Portfolio:
results = await asyncio.gather(
*[b.get_positions() for b in self.brokers]
)
return self._merge_positions(results)장기 (사업화 시):
- 마이데이터 사업자 허가: 법인 설립 + 자본금 5억 + 허가 취득
- 또는 CODEF 정식 서비스: 사업자 등록 후 월 구독
데이터 수집 설계
┌─────────────────────────────────────────────────────┐
│ Data Collector │
├─────────────────────────────────────────────────────┤
│ │
│ [10분 주기] │
│ ├── KIS 거래량순위 (국내) │
│ └── KIS 거래량순위 (해외) │
│ │
│ [5분 주기 - 장중] │
│ ├── DART 공시목록 │
│ └── Finnhub Company News │
│ │
│ [1시간 주기] │
│ ├── Finnhub News Sentiment │
│ └── 네이버 증권 뉴스 │
│ │
│ [이벤트 트리거] │
│ └── 거래량 급증 종목 감지 시 │
│ ├── DART 해당 종목 공시 조회 │
│ ├── Finnhub 해당 종목 뉴스 + 감성분석 │
│ └── 네이버 해당 종목 뉴스 크롤링 │
│ │
└─────────────────────────────────────────────────────┘월 운영 비용
| 항목 | 비용 |
|---|---|
| KIS API | 무료 |
| DART API | 무료 |
| Finnhub (Free) | 무료 |
| 네이버 증권 (크롤링) | 무료 |
| pykrx | 무료 |
| 합계 | 무료 |
한국 금융 데이터 API 생태계는 마이데이터와 오픈뱅킹이라는 제도적 인프라가 구축되어 있지만, 개인 개발자에게는 높은 진입 장벽이 존재한다. 현실적으로는 증권사 Open API + 외부 데이터 소스(DART, Finnhub, pykrx) 조합이 가장 효과적이며, 전부 무료로 구성할 수 있다.