GN⁺: PEP 686 - UTF-8 모드의 기본 설정화
(peps.python.org)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"
을 지정하지 않음 - 일관되지 않은 기본 인코딩으로 인해 많은 버그가 발생함
- UTF-8로 인코딩된 텍스트 파일(JSON, TOML, Markdown, Python 소스 파일 등)을 읽을 때
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
, 문자화け 또는 조용한 데이터 손상이 발생할 수 있음 - 하위 호환성 문제를 해결하기 위한 지침:
- UTF-8 모드를 비활성화
-
EncodingWarning
(PEP 597)을 사용하여 UTF-8 모드가 영향을 미치는 모든 위치 찾기-
encoding
옵션이 생략된 경우encoding="utf-8"
또는encoding="locale"
사용 고려 -
locale.getpreferredencoding()
이 사용되는 경우"utf-8"
또는locale.getencoding()
사용 고려
-
- UTF-8 모드로 애플리케이션 테스트
GN⁺의 의견
- 이 PEP은 Python의 기본 인코딩을 UTF-8로 통일하여 다른 언어 및 시스템과의 상호 운용성을 높이는 것을 목표로 함. 이는 Python이 글로벌 개발 환경에서 더욱 원활하게 사용될 수 있도록 도와줄 것임
- 그러나 이러한 변경은 기존 Python 프로그램의 하위 호환성에 영향을 줄 수 있음. 특히 Windows 환경에서 실행되는 프로그램의 경우 주의가 필요함
- 개발자들은
EncodingWarning
을 활용하여 영향받는 부분을 식별하고,encoding
옵션을 명시적으로 지정하는 등의 방법으로 대응해야 함 - 장기적으로는 이 변경이 Python 생태계에 긍정적인 영향을 미칠 것으로 예상됨. 그러나 단기적으로는 일부 프로젝트에서 마이그레이션 비용이 발생할 수 있음
- 개발자들은 Python 3.15로의 업그레이드를 계획할 때 이 변경 사항을 고려해야 하며, 필요한 경우 하위 호환성을 위한 적절한 조치를 취해야 함
Hacker News 의견
- 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만 사용할 거라 생각했음