프로그래밍

파이썬 3.15 출시, 3.10은 이제 작별? · lazy import · 3.11 기준선

2026년 10월 9일 파이썬 3.15가 나왔고 3.10은 지원이 끝났어요. lazy import, frozendict, Tachyon 프로파일러 등 핵심 변화와 3.11로 최소 버전을 올릴 때의 체크포인트를 정리했어요.

핵심 요약 5가지

  1. 01파이썬 3.15.0은 2026년 10월 9일에 정식 출시됐고, 3.15는 2031년 10월경까지 지원돼요.
  2. 02개발자 가이드 기준 파이썬 3.10의 지원 종료일은 2026-10-01이고, 3.11은 2027년 10월까지 보안 수정을 받아요.
  3. 03PEP 810의 lazy 키워드(lazy import json)로 모듈 로딩을 처음 사용하는 시점까지 미룰 수 있어요.
  4. 04open() 같은 I/O에서 encoding을 생략하면 이제 시스템 환경과 무관하게 UTF-8이 기본값이에요(PEP 686).
  5. 05Tachyon(profiling.sampling)은 실행 중인 프로세스에 PID로 붙어 코드 수정 없이 샘플링하고, 최대 1,000,000 Hz 샘플링을 지원한다고 문서에 적혀 있어요.

파이썬 3.15가 2026년 10월 9일에 정식 출시됐어요. 오픈소스 개발자 Simon Willison은 이 소식에 "3.10과는 작별, 이제 3.11 기능을 써도 된다"는 제목을 붙였어요. 새 버전이 나오면 기능 목록만 보게 되지만, 라이브러리나 팀 프로젝트를 관리하는 사람에게는 오히려 "어떤 버전을 더 이상 지원하지 않아도 되는가"가 실무에 더 크게 와닿아요. 이 글은 두 가지를 같이 짚어요. 3.15에서 실제로 바뀐 것, 그리고 3.10이 빠진 지금 최소 지원 버전을 어디에 두면 좋은가예요.

3.15는 언제 나왔고 얼마나 지원될까

파이썬은 PEP 602에 따라 매년 한 번 새 기능 버전을 내요. 3.15의 일정은 PEP 790에 정리돼 있어요. 2025년 5월 7일에 개발이 시작됐고, 알파 8개와 베타 4개, 릴리스 후보 3개를 거쳐 2026년 10월 9일에 3.15.0 final이 나왔어요. 마지막 후보(rc3)가 10월 2일이었으니 최종본까지 일주일이 걸린 셈이에요.

이후 계획도 PEP에 적혀 있어요. 3.15.1은 2026년 12월 1일 예정이고, 약 두 달마다 버그 수정 릴리스가 나와요. 마지막 정기 버그 수정 릴리스는 3.15.12(2028년 10월 3일 예정)로, 바이너리 설치 파일이 함께 제공되는 마지막 버전이에요. 그 뒤에는 소스 전용 보안 수정이 2031년 10월경까지 비정기적으로 나와요.

버전별 지원 상태

파이썬 개발자 가이드의 표를 기준으로 현재 상태를 정리하면 이래요.

버전상태첫 릴리스지원 종료
3.15bugfix2026-10-092031-10
3.14bugfix2025-10-072030-10
3.13security2024-10-072029-10
3.12security2023-10-022028-10
3.11security2022-10-242027-10
3.10end-of-life2021-10-042026-10-01

한 가지 짚을 점이 있어요. Simon의 글은 "3.15가 나왔으니 3.10이 공식적으로 지원 종료"라고 표현하지만, 개발자 가이드의 3.10 종료일은 3.15 출시(10월 9일)보다 조금 이른 2026-10-01이에요. 어느 쪽이든 결론은 같아요. 지금 시점에서 3.10은 지원 대상이 아니에요.

여기서 3.11도 눈여겨볼 만해요. 3.11은 2027년 10월에 끝나요. 3.10을 버리고 3.11을 최소 버전으로 잡으면 약 1년 뒤에 같은 고민을 다시 하게 되니, 새로 정한다면 3.12나 3.13을 기준으로 삼는 선택지도 현실적이에요.

파이썬 개발자 가이드 버전 표 기준

3.15의 큰 변화 한눈에 보기

What's new in Python 3.15는 이번 릴리스의 큰 줄기를 이렇게 요약해요. lazy import, frozendict와 sentinel 내장 타입, UTF-8 기본 인코딩, 컴프리헨션 안의 언패킹, 자유 스레드 빌드용 안정 ABI가 가장 큰 변화이고, 라이브러리 쪽에서는 새 프로파일링 패키지와 샘플링 프로파일러가 눈에 띄어요. 하나씩 볼게요.

명시적 lazy import (PEP 810)

가장 화제가 될 만한 기능이에요. 큰 파이썬 애플리케이션은 시작이 느린 경우가 많은데, 의존성 트리가 깊으면 import만으로 수 초가 걸리기도 해요. 지금까지는 함수 안에서 import하거나 importlib로 필요할 때 불러오는 식으로 우회했어요. 동작은 하지만 import 문이 코드 곳곳에 흩어지고 일관되게 지키기도 어려웠어요.

3.15는 lazy라는 소프트 키워드를 도입했어요. 문서의 예시는 이래요.

lazy import json
lazy from pathlib import Path
 
print("Starting up...")  # 아직 json, pathlib는 완전히 import되지 않았어요
 
data = json.loads('{"key": "value"}')  # 여기서 json이 실제로 import돼요
p = Path(".")                          # 여기서 pathlib가 실제로 import돼요

lazy로 표시한 import는 가벼운 프록시 객체를 만들어 두고, 이름을 처음 쓰는 순간에 실제 로딩이 일어나요. 로딩이 실패하면(예: 없는 모듈) import 시점이 아니라 처음 쓰는 시점에 예외가 나요. 트레이스백에는 이름을 쓴 위치와 원래 import 문이 같이 나와서 원인을 찾기 어렵지 않다고 문서는 설명해요.

PEP 810의 lazy 소프트 키워드

제약도 분명해요. lazy import는 모듈 최상위에서만 쓸 수 있어요. 함수나 클래스 본문, try/except/finally 안에서 쓰면 SyntaxError예요. 별표 import와 __future__ import도 lazy로 만들 수 없어요.

코드를 안 고치고 전역으로 켜는 방법도 있어요. -X lazy_imports 옵션이나 PYTHON_LAZY_IMPORTS 환경 변수에 all 또는 normal(기본값)을 줄 수 있어요. sys.set_lazy_imports_filter()로 "우리 앱 모듈만 lazy"처럼 선택적으로 제어할 수도 있어요. 구버전과 함께 지원해야 하는 코드를 위해서는 모듈에 __lazy_modules__ = ["json", "pathlib"]처럼 이름 목록을 두면, 해당 모듈의 일반 import가 lazy로 처리돼요.

Simon이 이 기능에 가장 기뻐한 이유도 실무적이에요. 그가 만드는 llm CLI는 플러그인 구조인데, sentence_transformers 같은 무거운 의존성을 가진 플러그인을 설치만 해도 명령 실행마다 몇 초가 늘어나는 문제가 있었어요. 그래서 플러그인 작성자에게 수동 lazy import를 권장해 왔다고 해요. 언어 차원의 해법이 생긴 거예요.

컴프리헨션 안의 언패킹 (PEP 798)

리스트, 집합, 딕셔너리 컴프리헨션과 제너레이터 표현식에서 *와 **를 쓸 수 있어요. 중첩 컴프리헨션이나 itertools.chain.from_iterable()을 대체하는 문법이에요.

lists = [[1, 2], [3, 4], [5]]
[*L for L in lists]   # [1, 2, 3, 4, 5]
# [x for L in lists for x in L] 와 같아요
 
dicts = [{'a': 1}, {'b': 2}, {'a': 3}]
{**d for d in dicts}  # {'a': 3, 'b': 2}

PEP 448이 3.5에서 도입한 언패킹 문법을 컴프리헨션까지 넓힌 거예요. 비동기 제너레이터 표현식도 같은 방식으로 지원돼요.

frozendict와 sentinel 내장 타입

frozendict는 생성 후 수정할 수 없는 새 내장 딕셔너리 타입(PEP 814)이에요. 주의할 점은 dict의 하위 클래스가 아니라 object를 직접 상속한다는 거예요. 키와 값이 모두 해시 가능하면 자신도 해시 가능하고, 삽입 순서는 유지하지만 비교할 때 순서는 보지 않아요. 그래서 isinstance(arg, dict)로 검사하던 코드는 isinstance(arg, (dict, frozendict))나 collections.abc.Mapping으로 고쳐야 이 타입을 받아줘요. json, pickle, copy 등 여러 표준 라이브러리 모듈이 frozendict를 받도록 갱신됐어요.

sentinel(PEP 661)은 "값이 없음"을 구분하기 위한 고유 마커 객체를 만드는 내장 타입이에요. 복사해도 동일성이 유지되고, 타입 표현식에서 | 연산자와 함께 쓸 수 있어요. 지금까지 _MISSING = object() 같은 패턴을 직접 만들던 분들에게 반가운 변화예요.

UTF-8이 기본 인코딩으로 (PEP 686)

조용하지만 영향 범위가 큰 변경이에요. 이제 open('flying-circus.txt')처럼 encoding을 지정하지 않은 I/O도 시스템 환경과 무관하게 UTF-8을 써요. 특히 Windows에서 로케일 인코딩 때문에 한글 파일이 깨지던 경험이 있다면 체감이 있을 거예요.

반대로 로케일 인코딩에 의존해 온 코드는 동작이 바뀔 수 있어요. 문서는 버전 간 호환을 위해 항상 encoding 인자를 명시하라고 권하고, 영향을 받는 코드를 찾는 데는 opt-in 인코딩 경고를 쓰라고 안내해요. 이전 동작이 필요하면 PYTHONUTF8=0 환경 변수나 -X utf8=0 옵션으로 UTF-8 모드를 끌 수 있어요. 현재 로케일을 쓰려면 encoding='locale'을 쓰면 되고, 이 값은 3.10부터 지원돼 왔어요.

새 프로파일링 패키지와 Tachyon

cProfile이 하던 결정적(deterministic) 호출 추적은 profiling.tracing으로 옮겨졌고, cProfile은 하위 호환용 별칭으로 남아요. 여기에 새 통계적 샘플링 프로파일러 Tachyon(profiling.sampling)이 합류했어요(PEP 799). 순수 파이썬 구현인 profile 모듈은 deprecated이고 3.17에서 제거될 예정이에요.

샘플링 프로파일러는 실행 중인 프로세스의 스택을 주기적으로 찍어서 어느 함수에 시간이 몰리는지 계산해요. 모든 호출을 계측하는 방식이 아니라서 부담이 적고, 코드 수정이나 재시작이 필요 없어요. 문서에 따르면 최대 1,000,000 Hz의 샘플링 속도를 낼 수 있어요. 사용법은 이런 식이에요.

# 실행 중인 프로세스에 PID로 붙어서 샘플링 (Ctrl+C로 중단하면 리포트 출력)
python -m profiling.sampling attach 1234

Simon은 macOS에서 sudo가 필요했다고 적었어요. 대상 지정은 attach(실행 중인 프로세스), run(스크립트를 처음부터), run -m(모듈), dump(스레드별 스택 스냅샷, 멈춘 프로세스 조사에 유용) 네 가지예요. 측정 기준도 wall-clock, CPU, GIL 점유, 예외 처리 시간 중에서 고를 수 있고, 출력은 pstats, 콜랩스드 스택, 플레임그래프, 히트맵, Firefox Profiler용 Gecko 형식을 지원해요. 예전에 py-spy 같은 외부 도구에 기대던 일을 표준 라이브러리가 맡게 된 거예요.

관련해서 CPython이 기본적으로 프레임 포인터를 켠 채 빌드되는 변화(PEP 831)도 있어요. 네이티브 스택 언와인딩이 빨라지고 안정돼서 시스템 프로파일러나 eBPF 기반 관측 도구에 유리해요. 대신 문서는 서드파티 빌드 백엔드가 Python의 sysconfig 플래그를 유지해야 하고, 프레임 포인터 없이 빌드된 네이티브 구성 요소 하나가 전체 스택 언와인딩을 깨뜨릴 수 있다고 경고해요.

속도는 얼마나 달라졌을까

기대와 달리 일반 속도 향상은 크지 않아요. Simon이 소개한 Miguel Grinberg의 측정(3.15.0rc3 기준)에서 성능은 3.14와 대체로 같았고, 예외는 실험적 JIT였어요. 피보나치 테스트에서 표준 3.15 인터프리터보다 약 1.2배 빨랐고, Miguel이 JIT에서 의미 있는 향상을 본 건 처음이라고 해요. 3.14가 3.13 대비 여러 항목에서 큰 향상을 보였던 것과는 대조적이에요. 즉 3.15는 "빨라서 올리는 버전"보다 "기능과 도구 때문에 올리는 버전"에 가까워요.

그 밖에도 자유 스레드 빌드용 안정 ABI(abi3t), 명령줄 출력의 색상 확대, 타입 시스템 쪽 PEP 728, 747, 800 등이 포함돼 있어요. 전체 목록은 공식 문서에서 확인하세요.

3.10을 보내면 무엇이 좋아질까

최소 지원 버전을 올리면 호환 코드를 걷어낼 수 있어요. Simon은 3.11에서 얻는 것들을 이렇게 꼽았어요.

  • tomllib이 표준 라이브러리에 들어와서 TOML을 읽는 데 외부 패키지가 필요 없어요.
  • asyncio에 TaskGroup과 timeout()이 생겼어요.
  • datetime.UTC가 datetime.timezone.utc의 별칭으로 추가됐어요.
  • sqlite3에 setlimit()/getlimit(), create_window_function(), blobopen()이 추가됐고, set_authorizer(None)으로 authorizer를 제거할 수 있어요.
  • 타입 시스템도 여러 면에서 개선됐어요.

그는 Datasette에서 set_authorizer(None) 우회 코드를 지우는 PR을 올렸고, 자신의 cookiecutter 템플릿들이 3.11부터 3.15까지를 테스트하도록 갱신했다고 해요. 라이브러리 관리자라면 같은 방식으로 CI 매트릭스를 "3.11 이상 3.15까지"로 조정하는 게 가장 직관적인 첫걸음이에요.

uv로 3.15 써 보기

가장 빠른 체험 방법은 uv예요. Simon이 자신의 Mac에서 쓴 순서는 다음과 같아요. 새 릴리스를 uv가 알아야 하므로 먼저 uv 자체를 업데이트해요.

uv self update
uv python install 3.15
uv python pin --global 3.15   # 프로젝트가 따로 고정하지 않은 경우의 기본값
uv run python --version

이미 uv tool install로 깔아 둔 도구는 uv tool upgrade datasette --python 3.15처럼 대상 파이썬을 지정해 다시 설치할 수 있어요. 전역 pin은 편하지만, 프로젝트별로 버전이 다르다면 프로젝트 안에서 명시적으로 고정하는 편이 사고가 적어요.

지금 무엇을 하면 좋을까

급하게 서두를 일은 아니에요. 다만 순서를 정해 두면 부담이 줄어요.

  • 운영 중인 서비스와 CI에서 3.10을 쓰는 곳을 찾아 목록으로 만들어요.
  • 3.10 사용처마다 3.11 이상으로 올릴 일정을 잡아요. 3.11은 2027년 10월까지라는 점도 같이 기록해요.
  • CI 매트릭스에 3.15를 추가하고, 의존 패키지가 3.15에서 설치되는지 확인해요.
  • open()이나 Path.read_text()에서 encoding을 생략한 코드를 찾아 명시해요. UTF-8 기본값 변경의 영향을 받을 수 있어요.
  • isinstance(x, dict) 검사가 있다면 frozendict를 받아야 하는지 판단해요.
  • 시작 시간이 느린 CLI나 도구가 있다면 lazy import나 -X lazy_imports 적용을 실험해 봐요.
  • 구버전도 함께 지원해야 하는 패키지라면 lazy 키워드 대신 __lazy_modules__를 검토해요.
  • 운영 중 성능 문제가 있다면 3.15 환경에서 profiling.sampling으로 샘플링해 봐요.
  • C 확장을 배포한다면 빌드 도구가 abi3t와 프레임 포인터 플래그를 어떻게 다루는지 확인해요.

정리하며

3.15는 속도보다 개발 경험을 바꾸는 릴리스예요. lazy import는 시작 시간 문제에, Tachyon은 운영 중 병목 분석에, UTF-8 기본값은 플랫폼 간 파일 처리 사고에 직접 닿아요. 그리고 3.10의 퇴장은 오래 붙들고 있던 호환 코드를 정리할 명분이 돼요. 새 기능을 당장 프로덕션에 쓰지 않더라도, CI에 3.15를 하나 추가해 두는 것만으로 다음 1년의 마이그레이션 비용이 꽤 줄어들어요.

자주 묻는 질문

파이썬 3.10을 아직 쓰고 있는데 당장 위험한가요?

개발자 가이드에는 3.10이 end-of-life(2026-10-01)로 올라 있어요. 더는 보안 수정도 기대할 수 없다는 뜻이라 3.11 이상으로 올릴 계획을 세우는 게 좋아요. 이미 배포된 서비스가 즉시 멈추는 것은 아니에요.

3.15로 바로 올려야 하나요, 아니면 3.14나 3.13에 머물러도 되나요?

3.13과 3.12는 보안 수정 단계, 3.14는 버그 수정 단계로 아직 지원돼요. 필수 의존 패키지가 3.15를 지원하는지 확인한 뒤 CI에 3.15를 추가해 보는 순서가 안전해요.

3.15가 3.14보다 많이 빨라졌나요?

Simon Willison이 인용한 Miguel Grinberg의 측정(3.15.0rc3 기준)에 따르면 성능은 3.14와 대체로 비슷했고, 실험적 JIT에서만 피보나치 테스트로 약 1.2배 향상이 있었어요. 워크로드마다 다르니 직접 재 보는 게 정확해요.

lazy import를 쓰면 기존 3.14 이하에서도 돌아가나요?

lazy 키워드 자체는 3.15 문법이라 이전 버전에서는 SyntaxError가 나요. 문서는 구버전을 함께 지원할 때 모듈에 __lazy_modules__ 목록을 정의하는 방법을 안내해요.

출처

  1. What's new in Python 3.15 (docs.python.org)docs.python.org
  2. PEP 790, Python 3.15 Release Schedulepeps.python.org
  3. Status of Python versions (Python Developer's Guide)devguide.python.org
  4. Hello Python 3.15, goodbye 3.10, and now I can use 3.11 (Simon Willison)simonwillison.net