파이썬 requests와 json 모듈 완벽 가이드: REST API 호출부터 데이터 정제까지
파이썬 requests 모듈과 json 라이브러리를 활용하여 REST API 데이터를 호출하고 파싱하는 방법, GET/POST 요청, 상태 코드 예외 처리(raise_for_status), 타임아웃 설정 및 JSONDecodeError 트러블슈팅을 완벽 정리합니다.
현대 웹 개발과 자동화 프로젝트에서 외부 서비스와의 데이터 통신은 대부분 REST API를 통해 이루어집니다. 날씨 정보, 주가 데이터, 공공데이터포털의 행정 데이터 조회부터 사내 시스템 연동까지 모든 과정이 HTTP 통신과 JSON 데이터 파싱을 기반으로 동작합니다.
파이썬 표준 라이브러리에도 urllib 모듈이 포함되어 있지만, 문법이 복잡하고 직관적이지 못해 실무에서는 사실상의 표준(De facto standard)인 requests 라이브러리를 사용합니다. requests 모듈을 이용한 GET/POST 요청 방식, 응답 데이터의 JSON 정제, 네트워크 지연에 대비한 타임아웃(Timeout) 설정 및 에러 방어 코드 작성법을 체계적으로 정리합니다.
1. 파이썬 requests 라이브러리 설치 및 기본 구조
requests는 외부 라이브러리이므로 작업 중인 가상환경(.venv)에 먼저 설치해야 합니다.
pip install requests
HTTP 프로토콜의 주요 요청 메서드는 용도에 따라 구분됩니다.
- GET: 서버로부터 데이터를 조회하거나 가져올 때 사용 (URL에 파라미터 노출)
- POST: 서버에 새로운 데이터를 생성하거나 민감한 정보(로그인, 대용량 페이로드)를 전송할 때 사용
- PUT / PATCH: 서버의 기존 리소스를 수정할 때 사용
- DELETE: 서버의 특정 리소스를 삭제할 때 사용
2. GET 요청과 쿼리 파라미터 전달
API를 호출할 때 URL 뒤에 붙는 ?key=value 형태의 쿼리 스트링(Query String)은 문자열을 직접 이어 붙이지 않고 params 딕셔너리로 넘기는 것이 안전합니다.
import requests
url = "https://jsonplaceholder.typicode.com/posts"
# 쿼리 파라미터 정의 (예: userId가 1인 게시글만 필터링)
params = {
"userId": 1
}
# 헤더 정보 설정 (User-Agent 또는 인증 토큰 전달 시 필수)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
# API 호출 (타임아웃 5초 설정)
response = requests.get(url, params=params, headers=headers, timeout=5)
# HTTP 상태 코드 확인 (200 OK)
print(f"상태 코드: {response.status_code}")
print(f"요청된 최종 URL: {response.url}")
params 파라미터를 사용하면 공백이나 한글, 특수문자가 포함된 검색어도 URL 인코딩(URL Encoding)이 자동으로 적용되어 전송 에러를 방지합니다.
3. 응답 데이터 JSON 파싱 및 정제
API 서버는 대부분 JSON(JavaScript Object Notation) 포맷의 텍스트로 데이터를 응답합니다. requests 객체의 .json() 메서드를 호출하면 JSON 문자열을 파이썬 딕셔너리(Dictionary)나 리스트(List) 구조로 즉시 역직렬화(Deserialization)할 수 있습니다.
import requests
import json
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url, timeout=5)
# 1. JSON 응답을 파이썬 딕셔너리로 변환
data = response.json()
# 2. 특정 필드 값 추출
post_id = data.get("id")
title = data.get("title")
body = data.get("body")
print(f"[{post_id}] 제목: {title}")
# 3. 파이썬 객체를 보기 좋은(Indented) JSON 문자열로 출력 (디버깅용)
pretty_json = json.dumps(data, indent=4, ensure_ascii=False)
print(pretty_json)
4. POST 요청으로 데이터 전송하기
서버에 데이터를 전송할 때는 전송 포맷에 따라 data 옵션(폼 데이터)이나 json 옵션(REST API 표준)을 선택하여 전달합니다.
import requests
url = "https://jsonplaceholder.typicode.com/posts"
payload = {
"title": "파이썬 자동화 테스트",
"body": "requests 라이브러리를 통한 데이터 전송",
"userId": 101
}
# json 파라미터를 넘기면 자동으로 Content-Type: application/json 헤더가 설정됨
response = requests.post(url, json=payload, timeout=5)
if response.status_code == 201:
print("데이터 생성 성공 (201 Created)")
print(response.json())
else:
print(f"전송 실패: {response.status_code}")
5. 실무 필수: 예외 처리 및 방어 코드 구축
외부 API 서버는 간헐적인 통신 두절, 500 서버 에러, 404 경로 오류 등이 언제든 발생할 수 있으므로 반드시 견고한 예외 처리가 동반되어야 합니다.
import requests
from requests.exceptions import HTTPError, Timeout, ConnectionError, RequestException
url = "https://jsonplaceholder.typicode.com/invalid-endpoint"
try:
# timeout을 반드시 지정하여 무한 대기 현상 방지 (초 단위)
response = requests.get(url, timeout=3)
# 4xx(클라이언트 오류) 또는 5xx(서버 오류) 발생 시 즉각 HTTPError 예외 발생시킴
response.raise_for_status()
data = response.json()
print("정상 데이터 수신:", data)
except HTTPError as http_err:
print(f"HTTP 오류 발생: {http_err} (상태 코드: {response.status_code})")
except Timeout:
print("요청 시간 초과 (서버 응답 지연)")
except ConnectionError:
print("네트워크 연결 실패 (DNS 오류 또는 서버 다운)")
except RequestException as err:
print(f"기타 요청 오류 발생: {err}")
6. 자주 발생하는 오류 및 트러블슈팅
1) json.decoder.JSONDecodeError
response.json() 호출 시 JSONDecodeError가 발생하며 스크립트가 멈추는 현상입니다.
- 원인: API 서버가 정상적인 JSON 대신 HTML 에러 페이지(예: 403 Forbidden, 502 Bad Gateway 웹페이지)를 반환했기 때문입니다.
- 해결법: 파싱 전 반드시 response.status_code를 확인하거나 response.text를 출력하여 응답 본문이 실제 JSON 형식인지 검증합니다.
if response.status_code == 200:
try:
data = response.json()
except ValueError:
print("응답이 JSON 포맷이 아닙니다:", response.text[:200])
2) 특정 사이트의 403 Forbidden 차단
브라우저에서는 열리는 API나 웹페이지가 파이썬 코드에서는 403 차단되는 경우입니다.
- 원인: requests의 기본 User-Agent가 python-requests/x.x.x로 설정되어 있어 웹 서버 방화벽(Cloudflare, WAF)이 봇으로 감지하고 차단한 것입니다.
- 해결법: 브라우저의 실제 User-Agent 문자열을 헤더에 명시적으로 추가하여 전송합니다.
7. 요약 및 실무 가이드
파이썬으로 안정적인 API 수집 파이프라인을 구축하기 위한 핵심 원칙입니다.
- 쿼리 파라미터는 하드코딩 대신 params 딕셔너리로 넘겨 자동 URL 인코딩을 적용합니다.
- 모든 requests 요청에는 시스템 멈춤을 방지하기 위해 반드시 timeout(권장 3~10초)을 명시합니다.
- response.raise_for_status()와 try-except RequestException 구조를 조합하여 에러 발생 시 프로그램이 튕기지 않고 안전하게 복구되도록 설계합니다.