본문으로 건너뛰기
피드

Python 3.15에서 헤드라인은 못 탔지만 꽤 쓸만한 기능들

backend 약 7분
vote
0
댓글
북마크

Python 3.15에는 lazy imports나 Tachyon profiler 같은 큰 기능 말고도 실무에서 바로 체감될 만한 작은 개선들이 들어가. TaskGroup 취소, 컨텍스트 매니저 데코레이터 개선, 스레드 안전 이터레이터처럼 평소 애매하게 불편했던 지점들이 꽤 깔끔해졌어.

  • 1

    asyncio TaskGroup에 예외 없이 그룹을 취소하는 cancel 기능이 추가됨

  • 2

    ContextDecorator가 제너레이터·코루틴·비동기 제너레이터의 전체 수명주기를 감싸도록 개선됨

  • 3

    threading.serialize_iterator로 이터레이터를 스레드 안전하게 감쌀 수 있음

  • 4

    collections.Counter에 xor 연산이 추가됨

  • 5

    frozendict 추가로 JSON 타입 전체를 불변·해시 가능 형태로 표현할 수 있게 됨

  • Python 3.15는 큰 기능만 있는 릴리스가 아님.
    • lazy imports나 Tachyon profiler처럼 눈에 띄는 기능도 있지만, 이번 글은 헤드라인을 못 탄 작은 변화들을 훑음.
    • 작은 기능이라도 실무에서 반복적으로 밟던 발목 지점을 없애는 경우가 있어서, 이런 게 은근 오래 감.

asyncio 쪽은 TaskGroup 취소가 깔끔해짐

  • Python 3.15에서는 asyncio TaskGroup을 더 우아하게 취소할 수 있음.

    • TaskGroup은 여러 비동기 작업을 구조적으로 묶어 실행하는 기능.
    • 기존에는 그룹 실행 중 어떤 신호를 받아 전체를 멈추려면, 커스텀 예외를 던지고 ExceptionGroup에서 걸러내는 식의 우회가 필요했음.
  • 새 TaskGroup.cancel은 그 우회를 없애줌.

    • 그룹 안의 작업을 취소하되, 일부러 예외를 만들어 흐름 제어에 쓰지 않아도 됨.
    • “설명할 게 거의 없을 만큼 단순하다”는 원문 표현이 딱 맞는 변화.

💡

> asyncio 코드에서 TaskGroup 종료를 위해 커스텀 예외를 던지고 suppress로 걸러내던 패턴이 있다면, Python 3.15부터는 TaskGroup.cancel로 단순화할 여지가 있음.

컨텍스트 매니저 데코레이터가 제너레이터 수명주기까지 감쌈

  • Python에서는 컨텍스트 매니저를 데코레이터처럼 쓸 수 있음.

    • 예를 들어 특정 블록의 실행 시간을 재는 컨텍스트 매니저를 함수 데코레이터로 붙이는 식.
    • 이 기능 자체는 Python 3.3부터 가능했음.
  • 문제는 이 방식이 이터레이터, 비동기 함수, 비동기 이터레이터에서는 잘 안 맞았다는 점.

    • 일반 함수는 호출 시 실제 실행이 바로 일어나지만, 제너레이터 함수는 호출하면 제너레이터 객체만 반환하고 본문 실행은 나중에 시작됨.
    • 코루틴 함수와 비동기 제너레이터도 비슷하게 “호출 시점”과 “실제 실행 수명주기”가 분리됨.
    • 그래서 데코레이터가 감싸야 할 전체 작업이 아니라 객체 생성 순간만 감싸고 끝나는 함정이 생겼음.
  • Python 3.15의 ContextDecorator는 감싸는 함수의 타입을 확인해 전체 수명주기를 덮도록 바뀜.

    • 이터레이터면 반복이 끝날 때까지, 코루틴이면 await가 끝날 때까지, 비동기 제너레이터면 비동기 반복 수명까지 커버하는 식.
    • 글쓴이는 이 변화 덕분에 컨텍스트 매니저가 데코레이터를 만드는 가장 좋은 방법이 됐다고 평가함. 살짝 과감한 주장인데, 발목 포인트가 줄어든 건 맞음.

스레드 안전 이터레이터가 표준 라이브러리에 들어옴

  • Python 이터레이터는 기본적으로 스레드 안전하지 않음.

    • 여러 스레드가 같은 이터레이터를 동시에 소비하면 값이 건너뛰어지거나 내부 상태가 깨질 수 있음.
    • free-threading 쪽 흐름까지 생각하면 이 문제가 더 중요해짐.
  • Python 3.15에는 threading.serialize_iterator가 추가됨.

    • 기존 이터레이터를 감싸서 여러 스레드가 안전하게 값을 하나씩 가져가도록 만듦.
    • generator 함수 결과에 이 처리를 적용하는 threading.synchronized_iterator 데코레이터도 있음.
  • threading.concurrent_tee도 추가됨.

    • 값을 나눠 갖는 게 아니라, 여러 이터레이터에 같은 값을 복제해 전달하는 용도.
    • 예전에는 이런 동기화를 하려면 Queue 중심으로 구조를 바꾸는 일이 많았는데, 이제 이터레이터 추상화를 유지한 채 해결할 수 있는 선택지가 생김.

보너스 기능도 소소하게 흥미로움

  • collections.Counter에 xor 연산이 들어감.

    • Counter는 단순 빈도 카운터처럼 보이지만, 집합처럼 교집합·합집합류 연산도 제공해 왔음.
    • Python 3.15에서는 대칭 차집합에 해당하는 xor까지 추가됨.
    • 글쓴이는 실제 사용처가 바로 떠오르진 않지만, 완성도 측면에서는 납득된다는 반응.
  • frozendict 추가로 JSON 타입 전체를 불변·해시 가능 형태로 표현할 수 있게 됨.

    • JSON의 배열, 불리언, 숫자, null, 문자열은 이미 불변 표현이 가능했지만 객체는 일반 dict라 해시 불가능했음.
    • frozendict가 들어오면서 JSON object까지 불변 구조로 다룰 수 있게 됨.

기술 맥락

  • 이번 변화들은 대부분 “새로운 패러다임”보다는 기존 추상화의 빈틈을 메우는 쪽이에요. TaskGroup, ContextDecorator, iterator는 이미 많이 쓰이는데, 특정 상황에서만 갑자기 복잡해지는 부분이 있었거든요.

  • TaskGroup.cancel이 중요한 이유는 예외를 흐름 제어용으로 덜 쓰게 해준다는 점이에요. 비동기 코드에서 ExceptionGroup까지 얽히면 디버깅이 금방 피곤해지는데, 취소 의도를 API로 직접 표현하면 코드 읽는 사람이 훨씬 덜 헷갈려요.

  • ContextDecorator 개선은 라이브러리 작성자에게 특히 의미가 있어요. 데코레이터 하나가 일반 함수와 제너레이터, 비동기 함수에서 다르게 동작하면 사용자는 버그를 자기 코드 문제로 오해하기 쉽거든요.

  • 스레드 안전 이터레이터는 free-threading 시대를 준비하는 성격도 있어요. 이터레이터라는 깔끔한 추상화를 유지하면서 동시 소비를 안전하게 만들 수 있으니, 기존 코드를 Queue 중심으로 크게 바꾸지 않아도 되는 장점이 있어요.

Python 3.15의 작은 기능들은 화려하진 않지만, 라이브러리 작성자나 동시성 코드를 만지는 사람에겐 꽤 반가운 변화야. 특히 컨텍스트 매니저를 데코레이터로 쓸 때 생기던 수명주기 함정이 줄어든 건 실무 버그를 조용히 줄여줄 가능성이 큼.

댓글

댓글

댓글을 불러오는 중...

backend

Go에서 Rust로 옮길 때 진짜로 바뀌는 것들

이 글은 Go 백엔드 서비스를 Rust로 옮길 때 속도보다 컴파일 타임 보장, 런타임 트레이드오프, 개발자 경험이 더 중요하다고 설명한다. nil 패닉, 데이터 레이스, 에러 처리, 제네릭, 비동기 모델, 마이그레이션 전략까지 실무 관점에서 Go와 Rust를 길게 비교한다.

backend

심평원, DUR부터 의료영상 심사까지 클라우드로 갈아엎는다

심평원이 정보시스템 클라우드 전환과 함께 병·의원 업무에 직접 닿는 DUR, 의료영상 AI 심사, 요양급여내역 조회 시스템을 고도화한다. 핵심은 설치형 프로그램 중심이던 연계를 웹과 API 기반으로 넓히고, 진료·청구 과정에서 실시간 확인과 자동 판독을 강화하는 쪽이다.

backend

윈도우 에러 코드 7번 ‘ERROR_ARENA_TRASHED’는 어디서 왔을까

ERROR_ARENA_TRASHED는 Win32에서 실제로 쓰이는 현대적 에러라기보다 MS-DOS 시절 메모리 관리 구조에서 넘어온 잔재야. MS-DOS가 메모리 블록 앞의 arena 시그니처를 훑다가 예상한 값이 아니면 ‘arena가 망가졌다’고 보고 이 에러를 냈다는 이야기야.

backend

C/C++ 컴파일러의 느슨한 메모리 동시성 버그를 자동으로 잡는 박사논문

C와 C++ 컴파일러에서 relaxed memory 동시성 버그를 찾는 자동 테스트 프레임워크를 다룬 박사논문이 공개됐어. Téléchat, Atomic-mixer 같은 도구로 소스 수준 동작과 컴파일된 프로그램 동작을 비교하고, LLVM과 GCC 툴체인에서 실제 버그를 찾아낸 내용이 핵심이야.

backend

자바 Valhalla가 도메인 원시 타입의 성능 핑계를 지워가고 있음

글은 Project Valhalla의 value class가 자바에서 도메인 제약을 타입으로 표현할 때 생기던 성능 비용을 크게 줄인다고 설명한다. PositiveInt 같은 래퍼 타입이 기존엔 객체 헤더와 포인터 추적으로 비쌌지만, Valhalla에서는 정적 타입이 맞을 때 배열 슬롯이나 객체 필드에 평평하게 저장될 수 있다. 다만 제네릭 박싱, 프레임워크 어댑터, == 의미 변화 같은 현실적인 주의점은 아직 남아 있다.