공공데이터포털 — 데이터 받기와 API 쓰기
data.go.kr에서 회원가입 → 데이터 찾기 → 파일 다운로드 → API 신청 → 인증키로 Python에서 호출하기까지, 화면 순서대로 따라가는 실습 가이드.
공공데이터포털이란
정부·공공기관이 가진 데이터를 누구나 무료로 받을 수 있게 모아둔 사이트입니다 → https://www.data.go.kr
데이터를 받는 방법은 두 가지입니다.
| 방식 | 뭘 받나 | 언제 쓰나 |
|---|---|---|
| 파일 데이터 | CSV, Excel 파일 | 한 번 받아서 분석할 때 |
| 오픈 API | 요청할 때마다 최신 데이터(JSON/XML) | 매일 바뀌는 데이터(날씨, 미세먼지 등) |
이 수업에서는 둘 다 써봅니다.
1단계: 회원가입
- data.go.kr 접속 → 오른쪽 위 회원가입
- 일반회원(개인)으로 가입 — 이메일 또는 간편 로그인
- 가입 후 로그인 상태로 다음 단계 진행
파일 다운로드는 로그인 없이도 되지만, API는 반드시 로그인해야 신청할 수 있습니다.
2단계: 데이터 찾기
검색창에 키워드를 입력합니다. 예: 미세먼지, 날씨, 버스 정류장, 아파트 실거래가
검색 결과에서 왼쪽 필터를 보세요.
- 파일데이터 — 다운로드용
- 오픈API — 프로그램에서 호출용
초보자 추천 데이터 (양이 적당하고 문서가 잘 되어 있음):
- 기상청 단기예보 조회서비스 (API)
- 한국환경공단 에어코리아 대기오염정보 (API)
- 국토교통부 아파트 매매 실거래가 (API)
- 각 지자체 "OO시 버스정류소 현황" (파일)
3단계 (파일): 다운로드해서 Pandas로 열기
- 파일데이터 상세 페이지 → 다운로드 버튼 클릭
- 대부분 CSV. 한글이 깨지면 인코딩 문제이니 아래처럼 지정
import pandas as pd
df = pd.read_csv("bus_stops.csv", encoding="cp949") # 안 되면 "utf-8" 또는 "euc-kr"
df.head()
공공데이터 CSV는 cp949(윈도우 한글) 로 저장된 경우가 많습니다.
UnicodeDecodeError가 나면 인코딩을 바꿔보세요.
4단계 (API): 활용신청하고 인증키 받기
- 오픈API 상세 페이지 → 활용신청 버튼
- 활용목적: "학습용" 또는 "수업 실습" 정도로 적고 신청
- 대부분 자동 승인(즉시). 일부는 1~2일 걸림
- 승인되면 마이페이지 → 데이터 활용 → 오픈API → 인증키 발급현황 에서 키 확인
인증키는 두 가지가 보입니다.
| 종류 | 생김새 | 언제 |
|---|---|---|
| Encoding | abc%2Bdef%3D... (%가 섞임) | URL에 직접 붙여 쓸 때 |
| Decoding | abc+def=... | Python params에 넣을 때 ← 이걸 쓰세요 |
인증키는 비밀번호와 같습니다. 코드에 그대로 쓰고 GitHub에 올리지 마세요. 아래 예제처럼 별도 변수에 두고, 제출 시에는 지우세요.
5단계 (API): 문서 읽는 법
상세 페이지의 "상세기능" 또는 "참고문서" 에 다음이 있습니다.
- 요청 주소(End Point):
http://apis.data.go.kr/기관코드/서비스명/기능명 - 요청 변수(Request Parameter): 어떤 값을 보내야 하는지
- 출력 결과(Response): 어떤 값이 돌아오는지
거의 모든 API에 공통으로 들어가는 변수:
| 변수 | 뜻 |
|---|---|
serviceKey | 내 인증키 |
pageNo | 몇 페이지 |
numOfRows | 한 페이지에 몇 건 |
dataType 또는 returnType | JSON 또는 XML — JSON으로 요청하세요 |
6단계 (API): Python으로 호출하기
예제 1 — 기상청 초단기실황 (지금 날씨)
import requests
import pandas as pd
SERVICE_KEY = "여기에 Decoding 키" # 마이페이지에서 복사
url = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst"
params = {
"serviceKey": SERVICE_KEY,
"pageNo": 1,
"numOfRows": 100,
"dataType": "JSON",
"base_date": "20260829", # 오늘 날짜 (YYYYMMDD)
"base_time": "0600", # 정시 기준 (HHMM). 10분 후부터 조회 가능
"nx": 60, # 서울 격자 X
"ny": 127, # 서울 격자 Y
}
r = requests.get(url, params=params, timeout=10)
print(r.status_code) # 200이면 성공
data = r.json()
items = data["response"]["body"]["items"]["item"]
df = pd.DataFrame(items)
print(df[["category", "obsrValue"]])
category 코드 뜻(문서에 있음): T1H 기온, RN1 1시간 강수량, REH 습도, WSD 풍속.
예제 2 — 에어코리아 시도별 미세먼지
url = "http://apis.data.go.kr/B552584/ArpltnInfoInqireSvc/getCtprvnRltmMesureDnsty"
params = {
"serviceKey": SERVICE_KEY,
"returnType": "json",
"numOfRows": 100,
"pageNo": 1,
"sidoName": "서울",
"ver": "1.0",
}
r = requests.get(url, params=params, timeout=10)
items = r.json()["response"]["body"]["items"]
df = pd.DataFrame(items)[["stationName", "dataTime", "pm10Value", "pm25Value"]]
print(df.head(10))
응답 구조 파악하는 요령
처음 보는 API는 응답이 어떻게 생겼는지 모릅니다. 이렇게 확인하세요.
import json
print(json.dumps(data, indent=2, ensure_ascii=False)[:2000]) # 앞부분만 예쁘게 출력
대부분 response → body → items → item 순서로 내려가면 실제 데이터 목록이 나옵니다.
7단계: 받은 데이터 저장하기
수집한 원본은 그대로 저장해두는 습관을 들이세요. 다음 챕터(분산 저장)와 연결됩니다.
df.to_csv("raw/air_seoul_20260829.csv", index=False, encoding="utf-8-sig")
df.to_parquet("raw/air_seoul_20260829.parquet")
자주 나는 오류
| 메시지 | 원인 | 해결 |
|---|---|---|
SERVICE_KEY_IS_NOT_REGISTERED_ERROR | 키가 틀렸거나 아직 승인 안 됨 | 키 다시 복사, 승인 상태 확인, 1시간 정도 기다리기 |
LIMITED_NUMBER_OF_SERVICE_REQUESTS_EXCEEDS_ERROR | 하루 호출 한도(보통 1,000회) 초과 | 내일 다시, 또는 numOfRows를 늘려 호출 횟수 줄이기 |
NO_DATA / 결과가 비어 있음 | 날짜·시간·지역 값이 잘못됨 | 문서의 예시 값으로 먼저 성공시킨 뒤 바꾸기 |
| 응답이 XML로 옴 | dataType=JSON을 안 넣음 | 파라미터 확인 |
한글이 ???로 보임 | 인코딩 문제 | encoding="utf-8-sig" 또는 cp949 |
%2B 같은 게 키에 들어감 | Encoding 키를 params에 넣음 | Decoding 키를 쓰기 |
연습
- 회원가입 → 에어코리아 API 활용신청 → 인증키 확인
- 예제 2를 실행해 우리 동네 시도(
sidoName)의 미세먼지를 표로 출력 - 결과를
raw/폴더에 CSV와 Parquet으로 저장 - (선택) 파일데이터 하나를 내려받아
read_csv로 열고, 한글이 제대로 보이도록 인코딩 맞추기