문자 인코딩 — UTF-8 필수
콘솔·파일·문서·설정·네트워크 전송 모두 UTF-8(BOM 없음). cp949 로 새지 않게 코드가 직접 막는다.
규칙
콘솔·코드·문서·설정·로그·SQL 전부 UTF-8, BOM 없음.
Windows 의 기본 인코딩(cp949, euc-kr)에 기대지 않고 코드가 직접 UTF-8 을 지정합니다. "터미널 설정을 바꾸면 된다"는 해결이 아닙니다 — 다른 PC·CI·서비스에서 또 깨집니다.
왜 — cp949 로 한 번 새면 되살릴 수 없습니다. 한글이
?나 대체 문자(U+FFFD)로 바뀌는 순간 원문이 사라집니다. 실제로 파일명0103_시험3_01(프로필)…이0103_??3_01(\D)…로 깨진 사고가 있었습니다.
언어별 방법
# Python — 표준 출력을 UTF-8 로 못박고, 파일은 항상 encoding 명시
import sys, io
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
io.open(path, "w", encoding="utf-8")
// C# — 콘솔 출력, 파일은 BOM 없는 UTF-8
Console.OutputEncoding = System.Text.Encoding.UTF8;
File.WriteAllText(path, text, new UTF8Encoding(false));
# PowerShell — Out-File / Set-Content 에 반드시 -Encoding 지정
$text | Out-File -FilePath out.txt -Encoding utf8
// Node.js — 인코딩 인자를 생략하지 않는다
fs.writeFileSync(path, text, 'utf8');
남이 준 파일
- 상대가 cp949 로 준 파일은 읽을 때만 그 인코딩을 지정합니다. 쓸 때는 UTF-8 로 씁니다.
- 바깥에서 들어온 글자(업로드 파일명 등)는 다시 쓰기 전에 깨졌는지 확인하고, 깨졌으면 원본을 그대로 둡니다. 이미 깨진 문자열로 원본을 덮어쓰지 않습니다.
명령줄로 네트워크에 보낼 때
파일 쓰기만 막아서는 부족합니다. 명령줄 인자에 한글을 넣으면 셸이 cp949 로 넘길 수 있습니다.
# X — 셸이 한글을 cp949 바이트로 넘겨 깨질 수 있다
curl -d '{"title":"실기기 울림 검증"}' https://example.com/api
# O — UTF-8 파일로 만든 뒤 파일을 보낸다
python -c "import io,json; io.open('p.json','w',encoding='utf-8').write(json.dumps({'title':'실기기 울림 검증'},ensure_ascii=False))"
curl -H 'content-type: application/json; charset=utf-8' --data-binary @p.json https://example.com/api
- 조회도 같습니다. DB 클라이언트는
--default-character-set=utf8mb4, Python 은PYTHONIOENCODING=utf-8을 지정하지 않으면 멀쩡한 자료가 깨져 보여 고장으로 오판합니다. - 넣은 뒤에는 되읽어서 확인합니다. 보낸 글자와 저장된 글자가 같은지 보지 않으면 깨진 줄 모르고, 저장된 뒤에는 원문을 되살릴 수 없습니다.
예외는 명시한다
다른 팀의 배포 파일을 바이트 그대로 보존해야 하는 사본(예: 상대 프로그램이 읽는 설정 파일의 사본)은 원본 형식(BOM·줄끝 포함)을 유지합니다. 이런 예외는 저장소 README 에 파일 단위로 적어 둡니다.
줄끝(Line ending)
줄끝(CRLF/LF)은 저장소마다 정할 수 있습니다. 정했으면 README 에 파일 종류별로 적고 지킵니다.
| 예 | 줄끝 |
|---|---|
문서 *.md | CRLF |
데이터·도구 *.json, *.py | LF |