API 주소로 요청했는데 JSONDecodeError가 발생했다면 JSON 문법부터 고치기 전에 응답을 확인해야 합니다. 로그인 화면으로 이동했거나, 본문 없는 204를 받았거나, 프록시 오류 HTML을 받았을 수 있습니다. 이 글은 JSON 객체를 반환하기로 한 조회 API를 읽는 작은 함수를 만들고 실패 조건을 나눠 봅니다.
요청을 보내기 전 준비
Requests는 Python 표준 라이브러리가 아니므로 사용하는 가상환경에서 python -m pip install requests로 설치합니다. URL·인증·쿼리·성공 응답 구조는 호출할 서비스의 문서로 확인합니다. 아래 함수는 인증 설정을 가진 Session과 URL을 인자로 받으며, 글 저장이나 자동 재시도는 하지 않습니다.
import requests
def fetch_json_object(session, url, params=None):
with session.get(
url,
params=params,
headers={"Accept": "application/json"},
timeout=(3.05, 10),
allow_redirects=False,
) as response:
if 300 <= response.status_code < 400:
raise ValueError("이동 응답: 로그인 또는 URL을 확인하세요.")
response.raise_for_status()
if response.status_code == 204:
return None
if not 200 <= response.status_code < 300:
raise ValueError("예상하지 않은 HTTP 상태입니다.")
media_type = response.headers.get("Content-Type", "")
media_type = media_type.split(";", 1)[0].strip().lower()
if media_type != "application/json" and not (
media_type.startswith("application/")
and media_type.endswith("+json")
):
raise ValueError("JSON으로 선언된 응답이 아닙니다.")
data = response.json()
if not isinstance(data, dict):
raise ValueError("이 호출은 JSON 객체 응답을 기대합니다.")
return data
raise_for_status()는 4xx·5xx를 HTTP 오류로 올립니다. JSON으로 해석할 수 있다는 사실과 HTTP 성공 여부는 별개입니다. 204는 이 함수에서 None으로 구분하며, 빈 결과 객체 {}와 혼동하지 않습니다. 배열을 반환하는 API에는 마지막 자료형 검사를 그 계약에 맞게 바꿉니다. Requests Response·예외 인터페이스
정상 JSON 안에서도 필요한 필드 확인
관리자 도구 검색처럼 results 배열을 약속한 응답이라면 다음 검사를 더할 수 있습니다. 아래 데이터는 서버 호출 없이 실행하는 예제입니다.
data = {"results": [{"name": "글자수 계산기"}]}
results = data.get("results")
if not isinstance(results, list):
raise ValueError("검색 응답에 results 배열이 없습니다.")
for item in results:
if not isinstance(item, dict) or not isinstance(item.get("name"), str):
raise ValueError("검색 항목에 문자열 name이 필요합니다.")
print(item["name"])
현재 win-j 관리자 검색은 staff 세션이 필요합니다. 이 글의 함수만으로 로그인이 생기지 않습니다. 인증을 생략하고 운영 주소를 호출한 뒤 로그인 HTML이 왔다면 인증 절차를 먼저 확인해야 합니다. 실제 쿠키 값을 예제 파일에 복사하거나 저장소에 올리지 않습니다.
오류에 따라 다른 조치하기
| 상황 | 함수에서 나타나는 결과 | 다음 조치 |
|---|---|---|
| 200 + JSON 객체 | 객체 반환 | 필수 필드와 자료형 검사 |
| 200 + 로그인 HTML | 형식 오류 | 이동 이력·인증 방식 확인 |
| 302 | 이동 오류 | 새 URL 또는 로그인 필요 여부 확인 |
| 204 | None |
빈 본문을 허용하는 계약인지 확인 |
| 400·401·429·500 등 | HTTPError |
상태와 제공자 오류 규칙 확인 |
| JSON 헤더 + 깨진 본문 | JSONDecodeError |
서버 직렬화·잘린 응답 확인 |
| 접속 또는 수신 지연 | Timeout 계열 |
네트워크·서버 상태 점검 |
연결 실패는 ConnectionError, 인증서 문제는 SSLError 같은 예외로 구분할 수 있습니다. TLS 오류를 없애려고 verify=False를 기본으로 쓰면 서버 인증을 포기하게 됩니다. 인증서 체인·호스트 이름·신뢰 저장소를 확인합니다.
timeout과 재시도의 범위
timeout=(3.05, 10)은 연결 대기와 읽기 대기를 나눈 값입니다. 전체 다운로드가 반드시 13.05초 안에 끝난다는 뜻은 아닙니다. 큰 응답을 다루는 작업에는 다운로드 크기 제한·전체 작업 시간 제한을 별도로 설계해야 합니다. 위 함수는 작은 JSON 응답을 위한 입문 예제입니다. Requests timeout 설명
429를 받았다고 매초 무한 재시도하지 않습니다. 서버의 Retry-After, 제한량, 최대 시도 횟수를 반영합니다. POST는 응답이 사라져도 서버에서 저장됐을 수 있으므로 이 조회 함수를 POST 재시도 코드로 단순 변환하지 않습니다.
params·data·json을 선택하는 기준
쿼리 값은 params={"q": "글자수"}, 폼 본문은 data={...}, JSON 본문은 json={...}으로 전달합니다. json=은 직렬화와 JSON Content-Type 설정을 맡습니다. 현재 이 사이트의 관리자 글 저장은 폼 계약이므로 JSON으로 바꾸어 보내는 것만으로 호환되지 않습니다.
서버로 보내기 전에 형식을 비교하는 방법은 HTTP 헤더 글에 있습니다. 이 예제는 자동 로그인·대용량 처리·재시도·모든 JSON 스키마 검증까지 제공하는 범용 클라이언트는 아닙니다.
첫 댓글을 남겨보세요.