중국어가 \u4e2d\u6587로 바뀌는 이유
핵심 요약: \u4e2d\u6587 이스케이프는 합법적인 Unicode이지 인코딩 실패가 아닙니다. 진짜 깨짐은 다르게 생겼고, 둘을 구분하는 것이 실제로 고칠 것을 결정합니다.

핵심부터 말하면, \uXXXX 출력을 합법적 이스케이프로 취급하고 JSON.parse로 왕복됨을 확인하세요. 읽히는 중국어를 원하면 ensure_ascii=False 같은 순수 ASCII 직렬화를 끄세요. 이스케이프는 비 ASCII를 운반할 수 없는 전송로에만 남기세요.
이스케이프되었기 때문이고 손상되지 않았습니다.
JSON.parse('"\\u4e2d\\u6587"') // "中文"
\u4e2d는 中, \u6587은 文. 합법적 이스케이프 시퀀스이고 어떤 파서든 복원합니다. 깨진 것은 없고, 로그, diff, 패킷 캡처에서 그냥 읽히지 않을 뿐입니다.
누가 이스케이프하나
| 도구 | 기본 | 토글 |
|---|---|---|
Python json.dumps |
이스케이프(ensure_ascii=True) |
ensure_ascii=False |
JavaScript JSON.stringify |
이스케이프 없음 | — |
| Java Jackson | 이스케이프 없음 | 선택 |
PHP json_encode |
5.4부터 이스케이프 없음 | — |
Go encoding/json |
이스케이프 없음 | — |
Python이 압도적으로 흔한 원천입니다. 기본값에는 이유가 있습니다. 순수 ASCII 출력은 어떤 전송로에서도 살아남습니다. 비용은 비 ASCII 문자가 모두 여섯 문자가 된다는 것입니다.
이스케이프 vs 깨짐
이스케이프: \u4e2d\u6587, \uXXXX와 일치. 직렬화기 설정이 원인.
깨짐: 测试, 涓枃. UTF-8 바이트를 쓰고 Latin-1이나 GBK로 읽은 데서 원인.
빠른 시험: 텍스트를 브라우저 콘솔에서 JSON.parse('"…"')로 붙여 넣으세요. 읽히게 돌아오면 이스케이프였습니다. 실패하거나 깨진 채로 남으면 인코딩 불일치이고, 수정은 직렬화기가 아니라 인코딩을 정렬하는 것입니다.
끄기
json.dumps(data, ensure_ascii=False)
그다음 하류를 검증하세요. 일부 레거시 시스템은 ASCII 전용 전송에 진짜로 의존합니다. 특히 SMS 게이트웨이와 옛 메일 릴레이입니다.
이스케이프가 올바른 선택일 때
- 비 ASCII에 적대적인 전송로(레거시 HTTP 헤더, 일부 SMS 게이트웨이)
- 다른 JSON 문자열 안에 중첩된 JSON, 이스케이프가 인용부호 충돌을 줄임
- 바이트로 절단해 멀티바이트 문자를 자를 수 있는 로그 파이프라인
그 외에는 가독성을 선호하고 끄세요.
FAQ
Python이 왜 기본으로 중국어를 이스케이프하나?
ensure_ascii=True가 기본이라 어떤 전송로에서도 살아남는 순수 ASCII 출력을 보장하기 때문입니다. 비용은 비 ASCII 문자가 모두 여섯 문자가 된다는 것입니다.
ensure_ascii를 꺼야 하나?
가독성이 중요할 때 끄세요. 그런 다음 하류를 검증하세요. 레거시 HTTP 헤더, 일부 SMS 게이트웨이, 바이트로 절단하는 로그 파이프라인은 여전히 ASCII 전용 내용에 의존할 수 있습니다.
전송로가 비 ASCII를 운반할 수 없다면?
이스케이프를 유지하세요. JSON이 다른 JSON 문자열 안에 내장되거나 비 ASCII에 적대적인 채널을 통과할 때, 이스케이프는 인용부호 충돌을 피하고 멀티바이트 문자가 잘리는 것을 막습니다.