파이썬 3.14 새 기능 정리: t-string, 지연 어노테이션, 프리스레딩 공식 지원
파이썬 3.14는 2025년 10월에 릴리스됐습니다. 원주율 버전(3.14)이라는 농담과 함께 나왔지만 내용물은 묵직합니다. 새 문자열 문법 하나, 오래 끌어온 어노테이션 문제의 결론, 그리고 파이썬 동시성의 방향을 바꾸는 프리스레딩 공식화까지. 이 글은 실무 영향이 큰 순서로 3.14의 변화를 정리합니다.
t-string: f-string과 닮았지만 문자열이 아닙니다 (PEP 750) #
가장 눈에 띄는 새 문법입니다. f 대신 t를 붙이면, 즉시 문자열이 되는 대신 Template 객체가 만들어집니다.
name = "월드"
greeting_f = f"안녕, {name}" # str: "안녕, 월드"
greeting_t = t"안녕, {name}" # Template 객체: 아직 문자열이 아님
# Template은 정적 텍스트와 보간 값이 분리된 채로 들어 있습니다
for part in greeting_t:
print(repr(part))
# '안녕, '
# Interpolation(value='월드', expression='name', ...)핵심은 소비하는 쪽이 보간 값을 어떻게 처리할지 결정할 수 있다는 점입니다. f-string은 값이 즉시 문자열에 녹아 버려서, HTML 이스케이프나 SQL 바인딩 처리를 끼워 넣을 방법이 없었습니다. t-string은 값이 분리된 채로 전달되므로, 라이브러리가 값만 골라 이스케이프하거나 파라미터로 바꿀 수 있습니다.
def safe_html(template) -> str:
parts = []
for item in template:
if isinstance(item, str):
parts.append(item) # 정적 텍스트는 그대로
else:
parts.append(escape(str(item.value))) # 보간 값만 이스케이프
return "".join(parts)
user_input = "<script>alert('x')</script>"
print(safe_html(t"<p>{user_input}</p>"))
# <p><script>alert('x')</script></p>f-string 인젝션 문제의 구조적 해법이라서, HTML 템플릿, SQL, 로그 마스킹, 프롬프트 조립 라이브러리들이 이 위에서 다시 만들어지고 있습니다. 당장 애플리케이션 코드에서 t-string을 직접 쓸 일은 적지만, 라이브러리들이 t-string을 받기 시작하면 “사용자 입력이 섞이는 문자열은 t-string으로"가 새 관행이 될 가능성이 큽니다.
어노테이션 지연 평가가 기본이 됩니다 (PEP 649/749) #
지금까지 타입 힌트는 함수 정의 시점에 즉시 평가됐습니다. 그래서 아직 정의되지 않은 클래스를 참조하면 NameError가 났고, 이를 피하려고 문자열로 감싸거나("User") 파일 맨 위에 from __future__ import annotations를 넣는 관행이 퍼졌습니다.
3.14부터는 어노테이션이 필요할 때 평가되는 것이 기본 동작입니다.
class Node:
# 3.13까지: NameError 또는 "Node" 문자열 필요
# 3.14부터: 그대로 동작
def next_node(self) -> Node | None: ...- 순환 참조 때문에 어노테이션을 문자열로 감싸던 코드는 이제 그럴 필요가 없습니다.
from __future__ import annotations는 여전히 동작하지만, 새 코드에서는 필요가 없어졌습니다.- 런타임에 어노테이션을 읽는 코드(Pydantic, FastAPI 같은 라이브러리)는 새로 추가된
annotationlib모듈 경유로 표준화됐습니다. 주요 라이브러리들은 이미 대응을 마쳤으므로, 애플리케이션 개발자 입장에서는 의존성을 최신으로 올리는 것으로 충분합니다.
프리스레딩(GIL 제거) 빌드가 공식 지원됩니다 (PEP 779) #
3.13에서 실험적으로 들어왔던 free-threaded 빌드가 3.14에서 실험 딱지를 떼고 공식 지원 단계가 됐습니다. GIL(전역 인터프리터 잠금)이 없는 파이썬에서는 스레드 여러 개가 실제로 여러 코어에서 동시에 파이썬 코드를 실행합니다.
현실적인 위치를 정확히 알아야 합니다.
- 여전히 별도 빌드입니다(
python3.14t). 기본 설치 파이썬은 GIL이 있는 그대로이고, 두 빌드는 C 확장 호환성이 다릅니다. - 단일 스레드 성능은 GIL 빌드보다 다소 느립니다. 격차는 3.13 대비 크게 줄었지만 0은 아닙니다.
- C 확장 생태계(NumPy 등 주요 패키지)가 프리스레딩 대응 휠을 내는 중이고, 대응 여부가 도입 가능성을 결정합니다.
지금 시점의 판단은 이렇게 요약됩니다. CPU 병렬이 절실한 워크로드는 프리스레딩 빌드를 검증해 볼 가치가 충분하고, 일반 웹 서비스는 서두를 이유가 없습니다. 웹 앱의 병렬성은 여전히 프로세스(워커) 단위가 표준입니다. 프로세스와 스레드의 차이가 헷갈린다면 프로세스와 스레드의 차이를 함께 보시기 바랍니다.
같은 맥락의 변화로, 다중 인터프리터가 표준 라이브러리로 들어왔습니다(PEP 734, concurrent.interpreters). 한 프로세스 안에 GIL이 각자 따로 있는 인터프리터를 여러 개 띄우는 방식으로, 프로세스보다 가볍고 스레드보다 격리된 중간 지점입니다. concurrent.futures.InterpreterPoolExecutor로 기존 Executor 인터페이스 그대로 쓸 수 있습니다.
작지만 반가운 변화들 #
- 괄호 없는 except (PEP 758): 예외 여러 개를 잡을 때
except (ValueError, TypeError):대신except ValueError, TypeError:로 쓸 수 있습니다.as를 쓸 때는 여전히 괄호가 필요합니다. - Zstandard 압축 표준 탑재 (PEP 784):
compression.zstd모듈이 들어왔습니다. gzip보다 빠르고 잘 압축되는 zstd를 서드파티 없이 쓸 수 있습니다. - 원격 디버깅 인터페이스 (PEP 768): 실행 중인 파이썬 프로세스에 밖에서 안전하게 붙을 수 있는 공식 통로가 생겼고,
pdb가 이를 지원합니다. “운영에서 멈출 수 없는 프로세스의 내부를 보고 싶다"에 대한 표준 답이 생긴 셈입니다. 프로파일링 관점의 같은 문제는 py-spy로 다룬 적이 있습니다. - 에러 메시지 개선: 오타 난 키워드 인자 제안, 문자열과 숫자를 잘못 섞었을 때의 안내 등이 더 구체적으로 바뀌었습니다. 버전을 올리는 것만으로 디버깅 경험이 좋아지는 부분입니다.
- UUID v6·v7·v8 지원:
uuid모듈이 최신 규격을 지원합니다. 특히 시간 순 정렬이 되는 UUIDv7은 DB 기본 키 용도로 수요가 많았습니다.
업그레이드 판단 #
3.14는 문법 비호환 변경이 거의 없는 릴리스라서 업그레이드 장벽은 낮은 편입니다. 순서는 늘 같습니다. 의존성 라이브러리의 3.14 지원 휠 존재를 확인하고, CI에 3.14를 추가해 테스트를 통과시키고, 그다음 런타임을 올립니다. uv를 쓴다면 uv python install 3.14로 버전을 받고 lock 파일 재생성으로 검증하는 흐름이 됩니다. 여러 버전을 오가는 관리법은 파이썬 패키징 #4에서 다뤘습니다.
정리 #
- t-string은 보간 값이 분리된 템플릿 객체를 만들어, 이스케이프와 바인딩을 라이브러리가 처리할 수 있게 합니다. 인젝션 문제의 구조적 해법입니다.
- 어노테이션 지연 평가가 기본이 되어, 문자열로 감싸던 관행과
from __future__ import annotations가 필요 없어졌습니다. - 프리스레딩 빌드가 공식 지원이 됐습니다. CPU 병렬 워크로드는 검증할 가치가 있고, 일반 웹 서비스는 아직 프로세스 병렬이 표준입니다.
- 다중 인터프리터, zstd 압축, 원격 디버깅, UUIDv7 등 표준 라이브러리의 실무 도구가 두터워졌습니다.
- 비호환 변경이 적은 릴리스이므로, 의존성 휠 확인 → CI 추가 → 런타임 업그레이드 순서로 올리면 됩니다.