파이썬 3.15는 2026년 10월 9일 정식(final) 버전으로 나왔고, 기본 인코딩이 UTF-8로 바뀐 것이 기존 코드에 가장 먼저 영향을 주는 변경이다. 모듈 로딩을 첫 사용 때로 미루는 lazy import, 불변 딕셔너리 frozendict, 새 샘플링 프로파일러 Tachyon도 들어갔다. 업그레이드 전에는 파일을 여는 코드에 encoding이 명시돼 있는지부터 본다(2026년 10월 10일 기준).
파이썬 공식 블로그의 3.15.0 출시 공지에 따르면 3.14 이후 5,643개 커밋에 1,012명이 참여했다. 세부 동작은 Python 3.15 What's New에 나와 있다.
파이썬 3.15 신기능 한눈에 보기
인터프리터, 표준 라이브러리, 타입 힌트, C API, 빌드 쪽 변경이 함께 들어왔다. 일반 개발자가 직접 만나게 되는 것부터 정리하면 다음과 같다.
| 변경 | 내용 | PEP |
|---|---|---|
| UTF-8 기본 인코딩 | 시스템 로캘과 무관하게 입출력 기본값이 UTF-8 | 686 |
| lazy import | lazy import json처럼 첫 사용 때 모듈을 로딩 | 810 |
| frozendict | 내장 불변 매핑 타입 | 814 |
| sentinel | 고유한 센티넬 값을 만드는 내장 타입 | 661 |
| 컴프리헨션 언패킹 | [*L for L in lists]처럼 *, ** 사용 | 798 |
| profiling 패키지, Tachyon | 추적·샘플링 프로파일러를 한 패키지로 묶음 | 799 |
| TypedDict 추가 항목, TypeForm | 타입 힌트 확장 | 728, 747 |
실험적 JIT 컴파일러도 개선돼, 공지에는 x86-64 Linux에서 표준 인터프리터 대비 기하평균 7~8%, AArch64 macOS에서 tail-calling 인터프리터 대비 11~12% 빨라졌다고 적혀 있다. 비교 기준이 서로 다른 수치이므로 한 표에 놓고 견주지 않는다.
파이썬 기본 인코딩 UTF-8 변경, 무엇이 달라지나
3.15부터는 open('flying-circus.txt')처럼 encoding을 주지 않아도 UTF-8로 열린다. 공식 문서는 시스템 환경과 무관하게 UTF-8이 기본이 된다고 설명한다(PEP 686). 따라서 encoding 없이 파일을 여는 기존 코드는 3.15에서 UTF-8로 해석되고, 파일이 다른 인코딩으로 저장돼 있다면 읽기 결과가 달라질 수 있다.

이전 동작이 필요하면 환경 변수 PYTHONUTF8=0 또는 실행 옵션 -X utf8=0을 쓴다. 근본적인 해결은 encoding을 명시하는 것이고, 시스템 로캘 인코딩이 꼭 필요한 곳에는 encoding='locale'(3.10부터 지원)을 쓴다. 영향받는 코드는 io 모듈 문서의 선택형(opt-in) 인코딩 경고로 찾는다. 3.10 이상에서 python -X warn_default_encoding app.py로 실행하면 encoding이 빠진 open() 호출마다 EncodingWarning이 출력되므로, 경고가 0건이 되면 인코딩 명시가 끝난 것이다.
PYTHONUTF8=0 python app.py
python -X utf8=0 app.py
lazy import 사용법: 시작 시간을 줄이는 지연 임포트
lazy import(PEP 810)는 모듈 맨 위에서 lazy를 붙여 로딩을 첫 사용 시점까지 미루는 문법이다. 공지는 명시적 lazy import가 시작 시간을 줄인다고 설명한다.

lazy import json
lazy from pathlib import Path
print("Starting up...") # json, pathlib은 아직 완전히 로딩되지 않음
data = json.loads('{"key": "value"}') # 이 시점에 json 로딩
제약이 있다. 모듈 최상위에서만 쓸 수 있고 함수, 클래스 본문, try/except/finally 안에서는 SyntaxError가 난다. 로딩 실패도 임포트 줄이 아니라 처음 사용하는 줄에서 예외로 나타나므로, 모듈이 없을 때의 오류 위치가 달라진다. 전체에 적용하려면 -X lazy_imports=all 또는 PYTHON_LAZY_IMPORTS 환경 변수를 쓰고, 기본값은 normal이다. 3.15 미만과 같이 쓰는 코드는 __lazy_modules__ = ["json", "pathlib"]로 같은 효과를 낼 수 있다.
frozendict, sentinel, 컴프리헨션 언패킹
frozendict는 값을 바꿀 수 없는 매핑이다. dict의 하위 클래스가 아니라서 isinstance(arg, dict)로 타입을 검사하던 코드는 isinstance(arg, (dict, frozendict)) 또는 collections.abc.Mapping 기준으로 바꿔야 한다. 키와 값이 모두 해시 가능하면 frozendict도 해시 가능하다(PEP 814).
a = frozendict(x=1, y=2)
a['z'] = 3 # TypeError: 'frozendict' object does not support item assignment
컴프리헨션 언패킹(PEP 798)은 중첩 리스트를 펼치는 코드를 짧게 만든다. [*L for L in lists]는 [x for L in lists for x in L]와 같은 결과이고, 집합은 {*s for s in sets}, 딕셔너리는 {**d for d in dicts}로 쓴다. sentinel(PEP 661)은 고유한 센티넬 값을 간결한 표현으로 만드는 내장 타입으로, 복사 후에도 identity가 유지되고 | 연산자로 타입 표현식에 쓸 수 있다.
Tachyon 프로파일러와 profiling 패키지
PEP 799로 profiling 패키지가 생겼다. 함수 호출을 빠짐없이 기록하는 profiling.tracing(기존 cProfile의 위치)과, 일정 간격으로 스택을 표본 추출하는 profiling.sampling(Tachyon)으로 나뉜다. cProfile은 호환 별칭으로 남지만 profile 모듈은 deprecated이며 3.17에서 제거될 예정이다.
Tachyon은 실행 중인 프로세스에 코드 수정이나 재시작 없이 붙을 수 있고, 시간 기준을 wall(기본), cpu, gil 중에서 고를 수 있다. 최대 1,000,000Hz로 표본을 추출하고, 출력은 pstats, collapsed, flamegraph, gecko, heatmap 형식을 지원한다. 자세한 사용법은 What's New의 Tachyon 항목에서 이어진다.
파이썬 3.15 업그레이드 전 확인할 것
공식 문서의 호환성 항목 가운데 실제 코드에 걸릴 가능성이 큰 순서로 정리했다.
| 확인 항목 | 바뀐 점 | 할 일 |
|---|---|---|
| 파일 읽기·쓰기 | 기본 인코딩이 UTF-8 | encoding 명시 또는 PYTHONUTF8=0 |
__cached__ 사용 | 3.13부터 deprecated였고 이제 설정되지 않음 | __spec__.cached 사용 |
.pth 파일의 import 줄 | 조용히 deprecated | 대응하는 .start 파일 형식 검토 |
tarfile 추출 | 거부된 멤버를 추출하지 않음 | 추출 결과 누락 여부 점검 |
importlib.metadata | 메타데이터 없으면 MetadataNotFound 예외 | 예외 처리 추가 |
argparse | suggest_on_error 기본값 True | 오류 메시지 형식에 의존하는 테스트 확인 |
profile 모듈 | deprecated, 3.17 제거 예정 | profiling으로 이동 |
macOS 27.0에서는 IDLE과 tkinter의 대화상자 메뉴를 열면 앱이 멈출 수 있다고 공지에 적혀 있다. macOS 27.0 쪽 동작 변경이 원인으로 보고됐고 추적 이슈는 #158053이다. 해당 환경이라면 IDLE 사용 흐름을 먼저 시험해 본다.

점검은 새 버전으로 별도 가상환경을 만들어 기존 테스트를 돌리는 것으로 시작한다. 인코딩 경고를 켜고 돌려 encoding이 빠진 호출을 찾고, 테스트가 통과하고 경고가 정리되면 배포 환경에 올린다. 새 환경에서 python --version이 3.15.0으로 나오는지, 한글이 든 텍스트 파일을 읽어 글자가 깨지지 않는지까지 확인하면 점검이 끝난다. 오늘 할 일은 프로젝트에서 open(을 검색해 encoding이 없는 줄이 몇 개인지 세는 것이다.
자주 묻는 질문
파이썬 3.15로 바로 업그레이드해도 되나요?
운영 중인 서비스라면 별도 환경에서 테스트를 먼저 돌린다. 공식 문서의 호환성 항목 가운데 encoding 없이 파일을 여는 코드와 __cached__, tarfile 추출 동작 변경이 기존 코드에 가장 먼저 걸린다.
UTF-8 기본 변경을 끄려면 어떻게 하나요?
PYTHONUTF8=0 환경 변수나 -X utf8=0 옵션으로 이전 동작을 유지할 수 있다. 다만 장기적으로는 encoding을 코드에 명시하는 쪽이 버전과 운영체제에 관계없이 안전하다.
lazy import를 함수 안에서 쓸 수 있나요?
쓸 수 없다. 모듈 최상위에서만 허용되고 함수, 클래스 본문, try 블록 안에서는 SyntaxError가 난다.
같은 주제 글
이 글이 도움이 되었다면 공유해주세요
최신 인사이트
카카오톡 공유 썸네일 안 나올 때 해결법 (Kakao JavaScript SDK 2025)
카카오톡 공유하기에서 썸네일 이미지가 안 나오는 원인과 scrapImage로 KAGE URL을 변환해 해결하는 방법을 단계별로 설명합니다. 지금 확인하세요.
Claude Code 서브에이전트로 CRM 사용자 설명서 20분 만에 완성하는 방법
Claude Code 서브에이전트를 활용해 CRM 코드베이스에서 사용자 설명서와 비주얼 가이드북을 20분 만에 자동 생성한 실전 사례를 공유합니다. 지금 확인하세요.
GEO 생성형 엔진 최적화: 2025년 AI 마케팅 전략 완전 가이드
GEO 생성형 엔진 최적화란 무엇이며 기존 SEO와 어떻게 다른지, 2025년 AI 마케팅 전략의 핵심 실행 방법 5가지를 데이터와 함께 알아보세요.
관련 프로젝트
새 글을 이메일로 받아보세요
마케팅, 분석, 개발 인사이트를 정리해서 보내드려요.

