파이썬 JSON 파일에서 한글이 \\uD55C\\uAE00처럼 보인다고 해서 곧바로 글자가 손상된 것은 아닙니다. ensure_ascii는 JSON 문자열을 어떤 표기로 출력할지 정하고, encoding='utf-8'은 파일의 문자를 어떤 방식으로 기록하고 읽을지 정합니다. 두 설정을 분리해서 확인하면 표시 방식과 실제 디코딩 오류를 빠르게 구분할 수 있습니다.
먼저 구분할 것: ensure_ascii와 encoding
json.dump()나 json.dumps()의 ensure_ascii 기본값은 True입니다. 이때 한글 같은 비ASCII 문자는 JSON 문자열 안에서 유니코드 이스케이프 형태로 출력될 수 있습니다. ensure_ascii=False를 사용하면 JSON 예약 문자와 제어 문자를 제외한 문자를 원문에 가깝게 출력합니다.
반면 open()의 encoding은 텍스트 파일의 바이트를 문자로 디코딩하거나 문자를 바이트로 인코딩하는 방식입니다. 따라서 한글을 파일에 직접 기록하고 다시 읽으려면 파일을 여는 양쪽에서 UTF-8을 명시하는 것이 핵심입니다. ensure_ascii=False만 지정한다고 파일 인코딩이 UTF-8로 바뀌지는 않습니다.
UTF-8로 저장하고 다시 읽는 최소 예제
import json
data = {
"message": "한글 JSON 저장",
"ok": True,
}
with open("result.json", "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=2)
with open("result.json", "r", encoding="utf-8") as file:
loaded = json.load(file)
print(loaded["message"])
이 예제에서 encoding='utf-8'은 파일 입출력의 인코딩을 정하고, ensure_ascii=False는 저장되는 JSON 문자열에서 한글을 이스케이프 대신 읽기 쉬운 형태로 표현하도록 합니다. with 블록을 사용하면 파일을 닫는 시점도 관리하기 쉽습니다.
문자열만 JSON 형태로 만들고 파일에는 직접 쓰지 않는다면 json.dumps()를 사용할 수 있습니다.
json_text = json.dumps(data, ensure_ascii=False)
print(json_text)
이 경우에도 dumps()는 문자열을 만들 뿐 파일 인코딩을 결정하지 않습니다. 파일로 저장하는 단계에서 open(..., encoding="utf-8")가 필요합니다.
\\uXXXX로 보이는 JSON은 정말 깨진 것일까?
파일에 다음처럼 보이는 값이 있다고 가정해 보겠습니다.
{"message": "\\uD55C\\uAE00"}
이 값이 JSON 문자열 안의 유효한 유니코드 이스케이프라면 json.load()로 읽었을 때 파이썬 문자열의 한글로 복원될 수 있습니다. 즉, 파일을 사람이 볼 때 이스케이프 표기로 보이는 것과 프로그램이 데이터를 잃은 것은 다른 문제입니다.
다음 순서로 확인해 보시면 됩니다.
- 파일을
encoding='utf-8'로 열어json.load()가 성공하는지 확인합니다. - 읽은 값의 실제 출력이 한글인지 확인합니다.
- 사람이 보는 파일에도 한글을 직접 남겨야 하는 요구가 있을 때만
ensure_ascii=False를 적용합니다.
반대로 백슬래시와 u가 JSON 이스케이프가 아니라 데이터 자체로 여러 번 저장된 경우에는 결과가 달라질 수 있습니다. 이때는 파일 일부를 눈으로만 판단하지 말고 json.load() 후 파이썬 값이 어떤 문자열인지 확인해야 합니다.
UnicodeDecodeError가 날 때 확인하는 순서
UnicodeDecodeError는 JSON 옵션보다 파일의 실제 바이트와 읽을 때 선택한 디코딩 방식의 불일치를 먼저 의심해야 합니다. ensure_ascii=False는 JSON 출력 표기와 관련된 옵션이지, 이미 다른 인코딩으로 저장된 파일을 자동으로 변환하지 않습니다.
운영 중에는 다음 순서가 안전합니다.
- 새로 저장하는 코드의
open()에encoding='utf-8'이 있는지 확인합니다. - 같은 파일을 읽는 코드에도
encoding='utf-8'을 지정했는지 확인합니다. - 기존 파일이 언제, 어떤 프로그램과 인코딩으로 만들어졌는지 확인합니다.
- 파일의 실제 인코딩을 모르는 상태에서
ensure_ascii만 바꾸어 문제를 해결하려 하지 않습니다.
기존 파일이 이미 다른 인코딩으로 저장되었다면 파일의 생성 과정과 바이트를 별도로 확인해야 합니다. 공식 문서만으로 특정 기존 파일의 인코딩을 확정할 수는 없습니다.
저장 전 체크리스트
- JSON 파일을 UTF-8로 관리하려면 읽기와 쓰기 모두
encoding='utf-8'을 지정합니다. - 파일에서 한글을 직접 읽기 좋게 보이게 하려면
ensure_ascii=False를 선택합니다. \\uXXXX표기는 먼저json.load()후 복원되는 값이 정상인지 확인합니다.UnicodeDecodeError는 JSON 표기 옵션과 분리해 파일의 실제 인코딩과 읽기 설정을 확인합니다.- JSON 구조 검증과는 별개로, 파일 경로와 현재 작업 폴더 문제는 파이썬 파일이 있는데 FileNotFoundError가 날 때: 상대경로와 현재 작업 폴더 확인법에서 이어서 확인할 수 있습니다.
정리하면, 파이썬 JSON 한글 저장에서 ensure_ascii=False는 표현 방식을 바꾸고 encoding='utf-8'은 파일 입출력 방식을 정합니다. 먼저 두 역할을 나눈 뒤 저장 코드와 읽기 코드를 같은 기준으로 맞추면, 단순한 이스케이프 표기와 실제 인코딩 오류를 구분할 수 있습니다.
출처
- Python 공식 문서: json — JSON encoder and decoder —
ensure_ascii,json.dump(),json.load()및 JSON 인코딩 관련 근거 - Python 공식 문서: Built-in Functions — open() — 텍스트 파일의
encoding인자 근거 - Python 공식 튜토리얼: Reading and Writing Files — UTF-8과
with open()사용 근거