Windows 의 Git Bash 에서 한글이 들어간 JSON 을 curl -d '...' 로 보냈더니 서버에는 깨진 글자가 저장됐다. 명령도 응답도 정상이라 한참 뒤에야 알았다.
증상
curl -X POST https://api.example.com/items \
-H 'Content-Type: application/json' \
-d '{"title":"테스트 항목"}'
응답은 200 이고 오류도 없다. 그런데 저장된 제목을 다시 조회하면 한글이 물음표나 엉뚱한 글자로 바뀌어 있다. 영문만 보낼 때는 전혀 문제가 없어서 스크립트를 한참 쓰다가 발견했다.
원인
명령줄 인자는 프로세스로 넘어가는 과정에서 Windows 의 코드 페이지 변환을 거친다. 셸 화면에는 UTF-8 로 보여도, 실제로 curl.exe 가 받는 바이트는 시스템 ANSI 코드 페이지(한국어 Windows 라면 CP949)를 거치면서 달라질 수 있다. 헤더에는 UTF-8 JSON 이라고 적어 보내면서 본문은 다른 인코딩이 되니, 서버는 그것을 UTF-8 로 해석하다가 깨뜨린다.
어떤 셸에서, 어떤 curl 을, 어떤 터미널 설정으로 실행했는지에 따라 될 때도 있고 안 될 때도 있다는 점이 더 나쁘다.
해결
본문을 명령줄에 적지 않는다. UTF-8 파일로 저장하고 파일에서 읽게 한다.
# body.json 을 UTF-8 로 저장한 뒤
curl -X POST https://api.example.com/items \
-H 'Content-Type: application/json; charset=utf-8' \
--data-binary @body.json
-d @file이 아니라--data-binary @file을 쓴다.-d는 파일의 줄바꿈을 제거한다.- 파일은 BOM 없는 UTF-8 로 저장한다. Windows PowerShell 5.1 의
Set-Content는 기본이 ANSI 라서-Encoding utf8을 줘야 하고, 그 경우 BOM 이 붙을 수 있으니 편집기나 스크립트 언어로 쓰는 편이 안전하다.
정리
한글·일본어·이모지처럼 멀티바이트 문자가 들어가는 요청 본문은 Windows 에서 명령줄 인자로 넘기지 않는다. 파일로 저장해서 --data-binary @파일 로 보내면 셸과 터미널 설정에 상관없이 같은 바이트가 나간다.
댓글 없음:
댓글 쓰기