국내 데이터 Open API 4개
KOSIS Open API (국가통계포털)
- API Key 발급: 1개의 Key로 KOSIS 전체 통계자료 접근 가능.
- 데이터 범위: 통계청 및 통계작성기관이 제출한 공식 집계 통계 (예: 인구, 고용, GDP, 물가지수, 주택가격지수).
- 강점: 하나의 키로 다양한 공식 통계 접근, 안정적이고 장기 시계열 제공.
- 한계: 원시 데이터 없음, 집계된 통계 수치만 가능.
한국은행 경제통계시스템 API (ECOS)
- API Key 발급: 한국은행 ECOS에서 Key 발급, 하나로 모든 통계 접근 가능.
- 데이터 범위: 한국은행이 작성·관리하는 거시경제·금융 통계 (예: 통화량, 금리, 환율, 국민계정, 국제수지).
- 강점: 신뢰성 높은 중앙은행 통계, 긴 시계열, 다양한 주기(월/분기/연간) 지원.
- 한계: 통계코드(stat_code) 숙지 필요, 제공 범위는 집계 통계에 한정됨.
금융위원회 전자공시 DART API
- API Key 발급: 금융감독원 Open DART 시스템에서 Key 신청 후 사용.
- 데이터 범위: 상장·비상장 법인의 전자공시 자료 (사업보고서, 반기·분기보고서, 주요사항보고 등).
- 강점: 기업 단위의 재무·공시 데이터에 직접 접근 가능, 상장사 과거 실적분석에 유용함.
- 한계: 기업코드(corp_code) 매핑 필요, 요청 건수 제한 존재.
공공데이터포털 API (data.go.kr)
- API Key 발급: 데이터셋(기관·서비스)별로 별도 Key 신청·승인 필요.
- 데이터 범위: 개별 부처·기관이 제공하는 원시 행정 데이터 (예: 국토교통부 아파트 실거래가, 기상청 날씨 관측자료).
- 강점: 실제 현장 일부에서 발생한 원시자료(raw data) 확보 가능.
- 한계: 기관별 승인 필요, 품질·갱신 주기 불균등.
오픈 API 4개의 Python 호출 예제
각 예제는 최소 의존성(requests, pandas 옵션)과 기본 페이지네이션, 오류 처리 포함. 키는 환경변수로 읽는다.
Public Data Portal (공공데이터포털, data.go.kr/ODcloud)
python
import os, requests, pandas as pd
SERVICE_KEY = os.environ["DATA_GO_KR_KEY"] # URL-encoded key 권장
BASE = "https://api.odcloud.kr/api/15077586/v1/centers" # 예시: 예방접종센터 공개API
# 문서: page, perPage 지원
def fetch_odcloud(page=1, per_page=1000):
params = {"page": page, "perPage": per_page, "serviceKey": SERVICE_KEY}
r = requests.get(BASE, params=params, timeout=20)
r.raise_for_status()
return r.json()
# 전체 페이지 수집
def fetch_all_odcloud(per_page=1000):
first = fetch_odcloud(1, per_page)
total = first.get("totalCount", len(first.get("data", [])))
pages = (total + per_page - 1) // per_page
data = first["data"]
for p in range(2, pages + 1):
data.extend(fetch_odcloud(p, per_page)["data"])
return pd.DataFrame(data)
df_od = fetch_all_odcloud()
print(df_od.head())
KOSIS Open API (국가통계포털, KOSIS)
python
import os, requests, pandas as pd
KOSIS_KEY = os.environ["KOSIS_KEY"]
# 편의: '사용자 통계식별자(userStatsId)'로 호출. 응답 JSON 권장.
# 예시 userStatsId는 본인 계정에서 생성한 식별자로 교체 필요.
def fetch_kosis_by_user_stats(user_stats_id, prdSe="A", start_prd="2010", end_prd="2024"):
url = "https://kosis.kr/openapi/statisticsData.do"
params = {
"method": "getList",
"apiKey": KOSIS_KEY,
"format": "json",
"jsonVD": "Y", # 가변 명칭 포함
"userStatsId": user_stats_id,
"prdSe": prdSe, # A=연간, Q=분기, M=월간
"startPrdDe": start_prd,
"endPrdDe": end_prd,
}
r = requests.get(url, params=params, timeout=30)
r.raise_for_status()
data = r.json()
if isinstance(data, dict) and data.get("errMsg"):
raise RuntimeError(data["errMsg"])
return pd.DataFrame(data)
# 사용 예: 본인 userStatsId로 교체
# df_kosis = fetch_kosis_by_user_stats("사용자ID/폴더명/통계명")
# print(df_kosis.head())
파라미터식 호출이 필요할 때(기관+표ID 방식):
python
def fetch_kosis_by_table(orgId, tblId, objL1="", objL2="", prdSe="A", start_prd="2010", end_prd="2024"):
url = "https://kosis.kr/openapi/statisticsData.do"
params = {
"method": "getList",
"apiKey": KOSIS_KEY,
"format": "json",
"jsonVD": "Y",
"orgId": orgId,
"tblId": tblId,
"objL1": objL1, # 분류코드 필요시 지정
"objL2": objL2,
"prdSe": prdSe,
"startPrdDe": start_prd,
"endPrdDe": end_prd,
}
r = requests.get(url, params=params, timeout=30)
r.raise_for_status()
data = r.json()
if isinstance(data, dict) and data.get("errMsg"):
raise RuntimeError(data["errMsg"])
return pd.DataFrame(data)
DART (전자공시, 금융감독원 Open DART)
python
import os, requests, pandas as pd
DART_KEY = os.environ["DART_API_KEY"]
# 공시 목록: 기간·종목 필터
def dart_list(bgn="20240101", end="20241231", corp_code=None, page_no=1, page_count=100):
url = "https://opendart.fss.or.kr/api/list.json"
params = {
"crtfc_key": DART_KEY,
"bgn_de": bgn,
"end_de": end,
"corp_code": corp_code, # None이면 전체
"page_no": page_no,
"page_count": page_count,
}
r = requests.get(url, params=params, timeout=20)
r.raise_for_status()
js = r.json()
if js.get("status") != "013": # 013=정상 외 오류 코드 확인
# DART는 '000'이 정상. (정상코드 확인 후 사용)
pass
return js
# 페이지네이션 수집
def dart_list_all(bgn, end, corp_code=None, page_count=100):
page = 1
rows = []
while True:
js = dart_list(bgn, end, corp_code, page, page_count)
if js.get("status") != "000":
raise RuntimeError(f"DART error {js.get('status')}: {js.get('message')}")
lst = js.get("list", [])
if not lst:
break
rows.extend(lst)
if len(lst) < page_count:
break
page += 1
return pd.DataFrame(rows)
# 예시 실행
# df_dart = dart_list_all("20240101", "20241231", corp_code=None, page_count=100)
# print(df_dart.head())
참고: 종목별 조회에는 DART의 기업코드 파일(corpCode.xml)을 사전 다운로드·파싱하여 종목명→corp_code 매핑이 필요하다.
python
# 기업코드 파일 갱신 및 파싱 예시
from zipfile import ZipFile
from io import BytesIO
import xml.etree.ElementTree as ET
def get_dart_corp_codes():
url = "https://opendart.fss.or.kr/api/corpCode.xml"
params = {"crtfc_key": DART_KEY}
r = requests.get(url, params=params, timeout=30)
r.raise_for_status()
zf = ZipFile(BytesIO(r.content))
with zf.open(zf.namelist()[0]) as f:
tree = ET.parse(f)
root = tree.getroot()
recs = []
for el in root.findall("list"):
recs.append({child.tag: child.text for child in el})
return pd.DataFrame(recs) # columns: corp_code, corp_name, stock_code, modify_date
# df_codes = get_dart_corp_codes()
# print(df_codes.query("stock_code == '005930'")) # 삼성전자 예시
Bank of Korea ECOS API (한국은행 경제통계시스템, ECOS)
python
import os, requests, pandas as pd
BOK_KEY = os.environ["BOK_ECOS_KEY"]
# 통계조회: StatisticSearch
# 형식: /api/StatisticSearch/{Key}/{format}/{lang}/{start}/{end}/{stat_code}/{cycle}/{start_time}/{end_time}/{item_code...}
def ecos_stat_search(stat_code, cycle, start_time, end_time, start_row=1, end_row=1000, lang="kr", fmt="json"):
base = "https://ecos.bok.or.kr/api/StatisticSearch"
url = f"{base}/{BOK_KEY}/{fmt}/{lang}/{start_row}/{end_row}/{stat_code}/{cycle}/{start_time}/{end_time}"
r = requests.get(url, timeout=30)
r.raise_for_status()
js = r.json()
data = js.get("StatisticSearch", [])[1:] # [0] = header
return pd.DataFrame(data)
# 예시: 소비자물가 CPI(코드 예시는 사용 전 확인 필요), 월간, 2015-01 ~ 2025-08
# df_bok = ecos_stat_search(stat_code="021Y126", cycle="M", start_time="201501", end_time="202508")
# print(df_bok.head())
추가 메모
- Authentication(인증, 인증): 모두 단순 키 방식. 요청빈도 제한 존재. 재시도와 지수 백오프 권장.
- Pagination(페이지네이션): data.go.kr은 page/perPage, DART는 page_no/page_count, ECOS는 start_row/end_row, KOSIS는 데이터량이 많으면 분할 호출.
- Encoding(인코딩): 공공데이터포털은 서비스키 URL 인코딩 필요. KOSIS 응답은 한글 키가 섞일 수 있어 DataFrame 컬럼 정리 권장.
- Formats(포맷): ECOS와 KOSIS는 json 권장. DART는 json과 xml 모두 제공.
원하는 통계 코드나 테이블 식별자(userStatsId, orgId+tblId)가 있으면 알려 주면 즉시 맞춤 예제로 바꿔 준다.