# PEP 686 - UTF-8 모드의 기본 설정화

> Clean Markdown view of GeekNews topic #14541. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=14541](https://news.hada.io/topic?id=14541)
- GeekNews Markdown: [https://news.hada.io/topic/14541.md](https://news.hada.io/topic/14541.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-04-28T10:22:42+09:00
- Updated: 2024-04-28T10:22:42+09:00
- Original source: [peps.python.org](https://peps.python.org/pep-0686/)
- Points: 3
- Comments: 1

## Topic Body

### PEP 686 - Python 3.15부터 UTF-8 모드를 기본값으로 설정

- UTF-8이 사실상 표준 텍스트 인코딩이 되어감
  - Python 소스 파일의 기본 인코딩은 UTF-8
  - JSON, TOML, YAML은 UTF-8 사용
  - Visual Studio Code, Windows 메모장 등 대부분의 텍스트 편집기는 기본적으로 UTF-8 사용
  - 대부분의 웹사이트와 인터넷 상의 텍스트 데이터는 UTF-8 사용
  - Node.js, Go, Rust, Java 등 많은 다른 인기 프로그래밍 언어도 기본적으로 UTF-8 사용
- 기본 인코딩을 UTF-8로 변경하면 Python이 다른 언어와 상호 운용하기가 더 쉬워짐
- 많은 Unix 사용 Python 개발자들은 기본 인코딩이 플랫폼에 따라 다르다는 사실을 잊어버림
  - UTF-8로 인코딩된 텍스트 파일(JSON, TOML, Markdown, Python 소스 파일 등)을 읽을 때 `encoding="utf-8"`을 지정하지 않음
  - 일관되지 않은 기본 인코딩으로 인해 많은 버그가 발생함

### PEP 686의 주요 변경 사항
- Python 3.15부터 UTF-8 모드가 기본적으로 활성화됨
  - 사용자는 여전히 `PYTHONUTF8=0` 또는 `-X utf8=0`을 설정하여 UTF-8 모드를 비활성화할 수 있음
- `locale.getencoding()` 추가
  - UTF-8 모드에 관계없이 로케일 인코딩을 얻기 위한 API
  - `warn_default_encoding` 옵션이 지정되면 `locale.getpreferredencoding()`은 `open()`과 마찬가지로 `EncodingWarning`을 발생시킴 (PEP 597 참조)
- `encoding="locale"` 옵션 수정
  - `TextIOWrapper`는 `encoding="locale"`이 지정된 경우 UTF-8 모드에서도 로케일 인코딩을 사용해야 함

### 하위 호환성
- 대부분의 Unix 시스템은 UTF-8 로케일을 사용하고 Python은 로케일이 C 또는 POSIX일 때 UTF-8 모드를 활성화하므로 이 변경은 주로 Windows 사용자에게 영향을 줌
- Python 프로그램이 기본 인코딩에 의존하는 경우 이 변경으로 인해 `UnicodeError`, 문자화け 또는 조용한 데이터 손상이 발생할 수 있음
- 하위 호환성 문제를 해결하기 위한 지침:
  1. UTF-8 모드를 비활성화
  2. `EncodingWarning` (PEP 597)을 사용하여 UTF-8 모드가 영향을 미치는 모든 위치 찾기
     - `encoding` 옵션이 생략된 경우 `encoding="utf-8"` 또는 `encoding="locale"` 사용 고려
     - `locale.getpreferredencoding()`이 사용되는 경우 `"utf-8"` 또는 `locale.getencoding()` 사용 고려
  3. UTF-8 모드로 애플리케이션 테스트

### GN⁺의 의견
- 이 PEP은 Python의 기본 인코딩을 UTF-8로 통일하여 다른 언어 및 시스템과의 상호 운용성을 높이는 것을 목표로 함. 이는 Python이 글로벌 개발 환경에서 더욱 원활하게 사용될 수 있도록 도와줄 것임
- 그러나 이러한 변경은 기존 Python 프로그램의 하위 호환성에 영향을 줄 수 있음. 특히 Windows 환경에서 실행되는 프로그램의 경우 주의가 필요함
- 개발자들은 `EncodingWarning`을 활용하여 영향받는 부분을 식별하고, `encoding` 옵션을 명시적으로 지정하는 등의 방법으로 대응해야 함
- 장기적으로는 이 변경이 Python 생태계에 긍정적인 영향을 미칠 것으로 예상됨. 그러나 단기적으로는 일부 프로젝트에서 마이그레이션 비용이 발생할 수 있음
- 개발자들은 Python 3.15로의 업그레이드를 계획할 때 이 변경 사항을 고려해야 하며, 필요한 경우 하위 호환성을 위한 적절한 조치를 취해야 함

## Comments



### Comment 24751

- Author: neo
- Created: 2024-04-28T10:22:42+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=40168242) 
- Python의 기본 텍스트 파일 인코딩이 플랫폼에 따라 다른 것은 오랫동안 문제였음
- 파일 시스템 인코딩 문제는 별개이며, 이번 변경에서는 다루지 않음
- 시스템 기본값에 의존하는 것은 좋지 않음. 가정과 달라질 수 있기 때문
- 과거 우분투와 `init.d` 스크립트에서 문제가 있었음. 루트로 실행되는 Java 실행 스크립트가 일반 사용자와 다른 인코딩을 사용하여 문제 발생
- 요즘은 덜 문제지만, OS에 이를 맡기는 것은 피해야 함. UTF-8 외 인코딩 사용은 의도치 않은 경우일 가능성이 높음
- 명시적으로 지정하지 않고 OS 설정에 의존하는 것은 좋지 않음
- 이번 변경은 좋은 방향. 깨지는 코드는 간단히 수정하는 게 나음
- 내용 손상 버그의 가능성이 있는 상태로 두는 것보다 낫다고 봄

> 최근 수십 년 동안 점점 더 사실이 되어 가는 경험칙: "charset" 설정이 UTF-8이 아니라면 잘못된 것임

- Python 2는 charset에 구애받지 않아 항상 잘 동작했지만, Python 3의 개선은 개선 그 이상이었음
- Python 3 스크립트와 Python 2 스크립트를 구분하는 방법:
  - `"utf-8"` 문자열이 있으면 Python 3
  - `C.UTF-8` 로케일에서만 동작하면 Python 3
- 이번 변경은 환영할 만한 것이며, Python 3를 "개선"할 것으로 보임

- Python 3부터 기본값이었다고 생각했음

> Node.js, Go, Rust, Java를 포함한 많은 인기 언어들이 기본적으로 UTF-8을 사용함

- Java가 UTF-16에서 UTF-8로 옮겨간 것은 몰랐음

- CPython의 내부 인코딩이 UTF-8인지는 모르겠음
- Python 문자열은 인덱싱이 가능하지만 임의 접근은 드물기에 필요할 때 지연 인덱싱하는 게 좋을 듯
- 한 칸씩 앞뒤로 이동만 하면 인덱스가 필요 없음
- 따라서 내부적으로 UTF-8 표현이 가능할 것으로 보임

- 왜 `utf-8-sig`가 아닌지? BOM을 선택적으로 처리해주는데 유용함

- UTF-8과 관련하여, 리눅스 프레임버퍼는 오래전부터 제대로 된 UTF-8 지원이 있었어야 함
- GNU Hurd는 2007년경부터 UTF-8을 지원하는 더 나은 '터미널 콘솔'을 가지고 있었음
- 2024년인 지금에야 이런 변화가 오다니

- 좋은 변화. 이제 JS만 UTF-8로 전환하면 되는데, 1995년에 쓰인 코드와 호환되어야 하기에 개선이 어려움

> 많은 유닉스 Python 개발자들이 기본 인코딩이 플랫폼마다 다르다는 걸 잊고, UTF-8 텍스트 파일을 읽을 때 `encoding="utf-8"`을 명시하지 않음

- "잊는다"라기보다는 제대로 인지하지 못하는 것 같음
- 명시적으로 요청하지 않는 한 Python이 모든 곳에서 UTF-8만 사용할 거라 생각했음
