# 문자 인코딩 — UTF-8 필수

## 규칙

**콘솔·코드·문서·설정·로그·SQL 전부 UTF-8, BOM 없음.**

Windows 의 기본 인코딩(cp949, euc-kr)에 기대지 않고 **코드가 직접 UTF-8 을 지정**합니다. "터미널 설정을 바꾸면 된다"는 해결이 아닙니다 — 다른 PC·CI·서비스에서 또 깨집니다.

> 왜 — cp949 로 한 번 새면 **되살릴 수 없습니다.** 한글이 `?` 나 대체 문자(U+FFFD)로 바뀌는 순간 원문이 사라집니다. 실제로 파일명 `0103_시험3_01(프로필)…` 이 `0103_??3_01(\D)…` 로 깨진 사고가 있었습니다.

## 언어별 방법

```python
# 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")
```

```csharp
// C# — 콘솔 출력, 파일은 BOM 없는 UTF-8
Console.OutputEncoding = System.Text.Encoding.UTF8;
File.WriteAllText(path, text, new UTF8Encoding(false));
```

```powershell
# PowerShell — Out-File / Set-Content 에 반드시 -Encoding 지정
$text | Out-File -FilePath out.txt -Encoding utf8
```

```js
// Node.js — 인코딩 인자를 생략하지 않는다
fs.writeFileSync(path, text, 'utf8');
```

## 남이 준 파일

- 상대가 cp949 로 준 파일은 **읽을 때만** 그 인코딩을 지정합니다. **쓸 때는 UTF-8** 로 씁니다.
- 바깥에서 들어온 글자(업로드 파일명 등)는 다시 쓰기 전에 깨졌는지 확인하고, 깨졌으면 원본을 그대로 둡니다. 이미 깨진 문자열로 원본을 덮어쓰지 않습니다.

## 명령줄로 네트워크에 보낼 때

파일 쓰기만 막아서는 부족합니다. **명령줄 인자에 한글을 넣으면 셸이 cp949 로 넘길 수 있습니다.**

```bash
# 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 |
