[Python] 3.14 핵심 업데이트 변화 정리
2025 10월 7일에 정식으로 릴리즈된 Python 3.14에서 눈여겨볼 주요 업데이트 사항을 정리합니다.
1. t-string (Template String)
python 3.14에서는 새로운 문자열 포매팅 문법인 t-string이 도입되었습니다. f-string은 코드 실행 시점에 바로 문자열로 완성됩니다. 따라서 변수에 할당된 값이 삽입되어 최종적인 str 객체를 만듭니다.
반면, t-string은 string.templatelib.Template 객체를 반환합니다.
from string.templatelib import Interpolation
import html
user_input = '<script>alert("악성코드")</script>'
template = t"<p>Hello {user_input}</p>"
def html_render(template):
result = ""
for part in template:
if isinstance(part, Interpolation):
result += html.escape(str(part.value))
else:
result += str(part)
return result
print(html_render(template))
# 결과 : <p>Hello <script>alert("Hacked!")</script></p>
t-string을 사용하면 라이브러리들은 위와 같이 삽입된 값을 자동으로 인코딩하거나 escaping 하거나 검증하는 로직을 삽입할 수 있고, SQL 쿼리 생성, HTML 마크업 생성, 로깅 메시지 생성 등 다양한 도메인 특화 환경에서 보안성과 유연성을 높일 수 있습니다.
2. Deferred Annotations
Python 3.14부터 애너테이션 처리 방식이 크게 개선되었습니다. 가장 핵심적인 변화는 전방 참조(forward reference)와 지연 평가(deferred annotations)의 도입입니다.
def some_function(x: Node) -> Node:
return x.next_node
class Node:
def __init__(self,):
self.next_node = None
if __name__ == "__main__":
print('성공!')
"""
python 3.13:
Traceback (most recent call last):
File "/Users/euntaeklee/python/Workspace/concurrency/annotations.py", line 1, in <module>
def some_function(x: Node) -> Node:
^^^^
NameError: name 'Node' is not defined. Did you mean: 'None'?
-------------------------------------------------------------------------
python 3.14:
성공!
"""
- Python 3.14부터 애너테이션은 지연 평가되며, 전방 참조를 안전하게 사용할 수 있음
- 덕분에 모듈 의존성 문제 등을 자연스럽게 해결 가능
- 기존 Python 3.13까지는 이런 코드가 바로 NameError를 발생시켰다는 점에서 큰 차이가 있음
3. Multiple Interpreters & InterpreterPoolExecutor
Python 3.14에서는 멀티 인터프리터(Multiple Interpreters)와 이를 쉽게 활용할 수 있는 InterpreterPoolExecutor가 정식으로 도입되었습니다. 이 기능은 GIL(Global Interpreter Lock) 한계를 우회하고, CPU 집약적인 작업을 병렬로 실행할 수 있는 새로운 방식입니다.
Multiple Interpreters
Python은 전통적으로 하나의 GIL(Global Interpreter Lock) 때문에, 멀티스레드 CPU 연산 성능이 제한적입니다. Python 3.14부터는 서브 인터프리터(Sub-Interpreter) 를 만들어, 각각 독립된 GIL을 가진 인터프리터에서 코드 실행이 가능해졌습니다.
from concurrent import interpreters
interpreter = interpreters.create()
interpreter.exec('print("hello from sub-interpreter")')
def square(n):
return n * n
print(interpreter.call(square, 12))
print(square(12))
- interpreters.create()로 새로운 인터프리터 생성
- 각 인터프리터는 독립된 GIL과 메모리 공간을 가지므로, CPU 바운드 작업을 병렬로 수행 가능
- interpreter.exec()와 interpreter.call()로 인터프리터 내 코드 실행 및 함수 호출 가능
InterpreterPoolExecutor
InterpreterPoolExecutor는 멀티 인터프리터를 활용한 병렬 실행을 쉽게 구현할 수 있는 고수준 API입니다. ThreadPoolExecutor와 사용법이 유사하며, 내부적으로 각 작업을 별도의 서브 인터프리터에서 실행합니다.
import math, time
from concurrent.futures import InterpreterPoolExecutor, as_completed, ThreadPoolExecutor
results = []
start = time.perf_counter()
with InterpreterPoolExecutor(max_workers=4) as excutor:
futures = [excutor.submit(math.factorial, i) for i in range(20000, 22000)]
for future in as_completed(futures):
results.append(future.result())
end = time.perf_counter()
print(f"Multi Interpreter : {end-start}")
- CPU 바운드 작업인 math.factorial을 4개의 인터프리터에서 병렬 처리
- GIL이 각 인터프리터마다 독립적이므로, 멀티스레드보다 높은 CPU 활용 가능
성능 비교
같은 작업을 멀티 인터프리터, 멀티 스레드, 싱글 스레드에서 비교:
from concurrent.futures import ThreadPoolExecutor
import math, time
results = []
start = time.perf_counter()
# Multi Thread
with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(math.factorial, i) for i in range(20000, 22000)]
for future in as_completed(futures):
results.append(future.result())
end = time.perf_counter()
print(f"Multi Thread : {end-start}")
results = []
start = time.perf_counter()
# Single Thread
for i in range(20000, 22000):
results.append(math.factorial(i))
end = time.perf_counter()
print(f"Single Thread : {end-start}")
방식 | 소요시간 | 한계 |
---|---|---|
Multi Interpreter | 6.958329709013924 | 인터프리터 생성 비용 존재, 메모리 사용 증가 |
Multi Thread | 27.528747166972607 | CPU 바운드 작업에서 GIL 때문에 성능 제한 |
Single Thread | 27.57662904204335 | 병렬 처리 불가, 느림 |
Python 3.14의 멀티 인터프리터 기능은 GIL 한계를 극복하고 CPU 바운드 작업을 병렬로 안전하게 수행할 수 있는 혁신적인 방법입니다.
4. Free-Threaded Python
Python 3.14t는 GIL(Global Interpreter Lock) 제약을 제거한 Free-thread 모드를 지원하는 버전입니다. 이는 Python이 전통적으로 가지고 있던 멀티스레드 CPU 바운드 성능 한계를 완전히 혁신하는 기능입니다.
Python 3.14t(Free-thread) 특징
GIL 제거
- 각 스레드가 독립적으로 Python 바이트코드를 실행 가능
- 스레드 간 락 없이 CPU 바운드 병렬 처리 가능
완전한 멀티스레드 병렬
- ThreadPoolExecutor, concurrent.futures, asyncio 등 기존 스레드 API와 호환
- CPU 코어 수만큼 실제 병렬 처리 가능
기존 코드 호환
- 대부분의 기존 Python 코드는 변경 없이 사용 가능
- 단, C 확장 모듈에서 GIL 의존 코드는 주의 필요
성능 비교
기존 코드에서 python version을 3.14 -> 3.14t로 변경
방식 | 소요시간 |
---|---|
Multi Interpreter | 7.407573916018009 |
Multi Thread | 6.850294167059474 |
Single Thread | 27.134682000032626 |
Free-thread Python(3.14t)에서는 GIL이 제거되어, 멀티스레드 CPU-bound 작업에서 기존보다 훨씬 빠른 성능을 기대할 수 있습니다.
주의사항
- C 확장 모듈에서 GIL 의존 코드는 Free-thread에서 예상치 못한 동작 가능
- 스레드 안전성을 보장하지 않는 전역 상태나 라이브러리는 주의 필요
- 디버깅이나 프로파일링 시 기존 Python과 동작 차이 발생 가능
AsyncIO CLI Tool
Python 3.14에서는 asyncio 모듈과 함께 CLI(Command Line Interface) 도구를 제공하여, 실행 중인 비동기 프로그램의 상태를 쉽게 확인할 수 있습니다.
AsyncIO 비동기 코드 예제 :
import os, asyncio
async def function1():
await asyncio.sleep(15)
print('Hello Form 1')
async def function2():
await asyncio.sleep(20)
print('Hello Form 2')
async def main():
await asyncio.gather(
function1(),
function2()
)
if __name__ == '__main__':
print(os.getpid())
asyncio.run(main())
AsyncIO CLI 사용법
Python 3.14에서는 asyncio CLI를 통해 실행 중인 비동기 프로그램의 상태를 실시간으로 확인할 수 있습니다.
2-1. 프로세스 상태 확인
uv run asynccli.py # 코드 실행 후 PID 확인
- 위 명령으로 AsyncIO 프로그램 실행
- 프로그램 실행 시 PID를 출력 → CLI에서 해당 PID를 이용
sudo .venv/bin/python -m asyncio ps "PID"
tid task id task name coroutine stack awaiter chain awaiter name awaiter id
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7242000 0x451ad180210 Task-1 main 0x0
7242000 0x451ad180410 Task-2 sleep -> function1 main Task-1 0x451ad180210
7242000 0x451ad180610 Task-3 sleep -> function2 main Task-1 0x451ad180210
- ps 명령으로 해당 PID의 비동기 루프 상태 확인
- 현재 실행 중인 태스크, 스케줄된 코루틴 등 상세 정보 출력
2-2. 프로세스 트리 확인
sudo .venv/bin/python -m asyncio pstree "PID"
└── (T) Task-1
└── main /Users/username/Workspace/asynccli.py:12
├── (T) Task-2
│ └── function1 /Users/username/python/Workspace/asynccli.py:4
│ └── sleep /Users/username/.local/share/uv/python/cpython-3.14.0+freethreaded-macos-aarch64-none/lib/python3.14t/asyncio/tasks.py:702
└── (T) Task-3
└── function2 /Users/username/python/Workspace/asynccli.py:8
└── sleep /Users/username/.local/share/uv/python/cpython-3.14.0+freethreaded-macos-aarch64-none/lib/python3.14t/asyncio/tasks.py:702
- pstree 명령으로 해당 PID의 코루틴/태스크 구조 트리 시각화
- 어떤 코루틴이 실행 중인지, 어떤 순서로 스케줄되어 있는지 확인 가능
Python 3.14 AsyncIO CLI는 비동기 프로그램을 실행 중에도 실시간 모니터링하고, 코루틴 구조를 트리 형태로 시각화할 수 있는 강력한 도구입니다.
느낀점
Python 3.14는 GIL-Free, 서브 인터프리터, InterpreterPoolExecutor, Async CLI 등 병렬·동시성 측면에서 Python 역사상 가장 큰 구조적 진보를 보여주었습니다. 이제 Python도 멀티코어 성능을 제대로 활용할 수 있는 시대가 열렸지만, 아직 일부 프레임워크와 라이브러리와의 호환성 문제는 남아 있습니다. 그러나 지속적인 업데이트를 통해 점진적으로 개선될 것이 기대됩니다.