외부 API JSON에서 data["id"]가 KeyError를 냈다면 코드가 까다로운 것이 아니라 계약이 달라졌거나 값이 빠졌다는 신호다. 모든 키를 get으로 숨기기보다 필수와 선택을 구분해야 한다.
data = {"id": 7, "name": "도서"}
name = data["name"] # 반드시 있어야 하는 값
nickname = data.get("nickname") # 없어도 되는 값
assert name == "도서"
assert nickname is None대괄호 접근은 필수 계약을 드러낸다
필수 키의 누락, 선택 키의 누락, 값 0이 실제로 들어온 경우는 서로 다르다. 아래 그림처럼 결과를 구분해야 기본값이 데이터 오류를 덮지 않는다.
필수 ID나 타입 같은 값이 없으면 이후 처리 자체가 잘못될 수 있다. 이때 KeyError를 의미 있는 검증 오류로 바꾸고, 어느 응답에서 어떤 필드가 빠졌는지 안전하게 관찰하는 편이 낫다.
if "id" not in data:
raise ValueError("응답에 id가 없습니다")
item_id = data["id"]data = {"name": "도서"}로 바꿔 다시 실행하면 검증 단계에서 멈춘다. 이 실패를 단위 테스트에 넣으면 뒤늦게 잘못된 ID로 저장하는 일보다 원인을 찾기 쉽다. 응답 본문 전체를 로그에 남기지 말고, 필요한 키의 존재 여부와 상태 코드처럼 안전한 진단 정보만 기록한다.
get의 기본값은 의미를 가진 값이어야 한다
data.get("count", 0)은 누락과 실제 0을 같은 값으로 만들 수 있다. 두 상태가 다르면 기본값을 주지 말고 None을 유지하거나 별도 상태로 표현한다. 중첩 JSON에서는 각 단계가 딕셔너리인지도 확인해야 한다.
payload = {"stats": {"count": 0}}
stats = payload.get("stats")
if not isinstance(stats, dict):
raise ValueError("stats 형식이 올바르지 않습니다")
count = stats.get("count")
assert count == 0필수 필드가 많아지면 매번 임의의 기본값을 넣기보다 입력 경계에서 한 번 검증하고 내부에는 검증된 값을 넘긴다. 실패한 응답을 조용히 성공처럼 처리하는 설계는 작은 화면에서는 편해 보여도 집계와 저장 단계에서 데이터 품질을 해친다.
정상·선택 키 누락·필수 키 누락을 따로 테스트한다
import json
def read_item(raw):
data = json.loads(raw)
if not isinstance(data, dict):
raise ValueError("객체 형식의 응답이 필요합니다")
if "id" not in data:
raise ValueError("id가 필요합니다")
return data["id"], data.get("nickname")
assert read_item('{"id": 7, "nickname": "book"}') == (7, "book")
assert read_item('{"id": 7}') == (7, None)
try:
read_item('{"nickname": "book"}')
except ValueError as error:
assert str(error) == "id가 필요합니다"
else:
raise AssertionError("필수 id 누락을 놓쳤습니다")첫 두 검사는 선택 키의 유무를, 마지막 검사는 필수 키가 빠졌을 때 즉시 멈추는지를 확인한다. 예외가 났다는 사실만 검사하지 말고 어떤 필드가 누락됐는지 메시지도 고정하면, 여러 검증 중 잘못된 지점에서 실패한 경우를 구분하기 쉽다. 0이나 빈 문자열이 허용되는 필드는 키 존재 여부와 값의 유효성 검사를 따로 둔다.
오류 로그에는 응답 전체 대신 안전한 진단 정보만 남긴다
입력 JSON은 파싱됐다는 이유만으로 형태까지 맞다고 신뢰하지 않는다. 타입·중첩 구조·허용 값을 입력 경계에서 검증하고, 내부 함수에는 검증된 값을 넘긴다. 오류 로그에는 전체 요청 본문이나 인증 정보를 남기지 말고 상태 코드, 필수 키의 존재 여부, 안전한 요청 식별자처럼 원인을 좁히는 정보만 기록한다.
기본값을 추가할 때는 기존 데이터 의미가 바뀌지 않는지도 확인한다. 누락과 실제 0을 같은 값으로 합치면 집계 오류가 조용히 쌓일 수 있다. 기본값은 편의 기능일 뿐 잘못된 입력으로 작업을 계속하게 만드는 장치가 아니어야 한다.
핵심 요약
data["key"]는 필수 키가 없을 때 즉시 실패하고, get은 선택 키의 기본값을 다룬다. 누락을 무조건 숨기지 말고 데이터 계약에서 필수·선택·기본값의 의미를 정하자. API 응답 변화는 예외 처리와 관측으로 빠르게 발견할 수 있어야 한다.
작성자
기초 개념을 구현과 검증, 실제 운영 판단까지 연결해 기록합니다.

