기본 콘텐츠로 건너뛰기

uv 0.11.3 Operations Notes

thumbnail

uv 0.11.3 실전 업그레이드 포인트: `uv audit` 무시 규칙부터 workspace metadata까지

meta_description: uv 0.11.3(2026-04-01)는 기능 ‘추가’보다 운영 품질을 올리는 릴리스다. uv audit--ignore/--ignore-until-fixed가 들어오고, uv workspace metadata가 lock의 의존성 정보를 더 보여주며, wheel/ABI 관련 에러 메시지도 더 친절해졌다. 이 글은 팀 repo에서 uv를 올릴 때 바로 쓰는 체크리스트(20분)와 CI 적용 팁을 정리한다. meta_keywords: python,uv,packaging,dependency,lockfile,workspace,metadata,audit,security,vulnerability,ignore,CI,uv publish,hashing,abi3,free-threaded,wheel,error,PEP,release meta_robots: index,follow

uv는 “빠른 패키지 도구”로만 보면 끝이다.

실무에서 uv가 진짜 가치가 있는 지점은, 의존성/빌드/배포를 한 덩어리로 운영할 때다.

그래서 uv 업그레이드는 릴리스 노트 한 줄 때문에 CI가 깨지는지(혹은 더 좋아지는지)를 바로 드러낸다.

이번 uv 0.11.3(Released 2026-04-01)는 큰 기능 쇼케이스보다, 운영 쪽에서 자주 부딪히는 포인트를 정리해 준 릴리스다.

  • uv audit--ignore--ignore-until-fixed 추가(프리뷰)
  • uv publish에서 해시 계산 단계에 진행바 추가
  • uv workspace metadata가 lock의 의존성 정보를 더 보여주도록 확장
  • 빌드된 wheel 에러에서 플랫폼/ABI 관련 메시지가 더 읽히게 개선

이 글은 “릴리스 요약”이 아니라, 레포에서 안전하게 올리는 순서로 정리한다.


1) 결론: 0.11.3은 ‘보안 감사 결과를 운영 가능한 형태로’ 만드는 게 핵심

대부분의 팀은 보안 감사를 이렇게 운영한다.

  • 감사 도구 돌림
  • CVE 쏟아짐
  • “이거 언제 다 고치지?”
  • 결국 끄거나 무시함

uv audit--ignore/--ignore-until-fixed가 들어온 건(프리뷰 기능이긴 하지만), 이 흐름을 현실적으로 바꾸려는 의도가 읽힌다.

실전 관점에서 중요한 차이

  • --ignore: “이건 우리 리스크로 받아들인다”에 가까움
  • --ignore-until-fixed: “지금은 못 고치지만, 고쳐질 때까지는 추적하겠다”에 가까움

즉, 완전 무시운영 가능한 예외를 분리할 수 있다.


2) 20분 업그레이드 체크리스트(복붙)

(1) 먼저 버전 고정부터

CI와 로컬이 섞이면 “나는 되는데?”가 시작된다.

  • pyproject/lock에서 uv 버전은 어디서 관리하는가?
  • 설치는 어디서 하는가?

가능하면 CI에서 설치 경로를 고정해 둔다.

(2) uv audit는 ‘실패 기준’부터 정하자

감사 결과를 무조건 fail로 두면, 결국 팀은 감사를 끈다.

내가 추천하는 단계는 이렇다.

1) 처음 1~2주는 리포트 모드(경고만) 2) 이후부터 중요도 기준 또는 denylist 기준으로 fail 3) 정말 못 고치는 건 --ignore-until-fixed 같은 식으로 이유를 남기고 예외 처리

(3) workspace 기반 프로젝트면 uv workspace metadata를 확인

모노레포/멀티 패키지 구조에서 “지금 lock에 뭐가 들어갔지?”가 자주 문제다.

0.11.3에서 uv workspace metadata가 lock의 의존성 정보를 더 보여주도록 확장된 건, 이 디버깅 시간을 줄여준다.

  • 락이 바뀌었는데 뭐가 바뀐 건지
  • 어떤 의존성이 실제로 들어갔는지

이걸 명시적으로 확인할 수 있어야 한다.

(4) publish 파이프라인이 있는 팀은 uv publish 체감 개선 확인

uv publish의 해시 단계 진행바는 사소해 보이지만,

  • “멈춘 건지”
  • “느린 건지”

를 구분할 수 있게 해준다.

배포 단계에서 이 UX는 생각보다 중요하다.


3) CI 적용 예시(가장 안전한 기본형)

팀 CI에서 uv를 쓰는 목적은 보통 두 가지다.

  • lock 기반으로 재현 가능한 설치
  • 감사/체크를 자동화

아래는 가장 보수적인 기본형 예시다.

# 1) lock 기반 설치
uv sync --frozen

# 2) 보안 감사(처음엔 리포트로)
uv audit || true

# 3) 테스트
uv run pytest -q

그리고 audit를 fail로 돌리고 싶으면, fail 기준을 팀 룰로 합의한 뒤에 바꾼다.

예:

  • (초기) uv audit || true
  • (운영) uv audit + 예외는 --ignore-until-fixed로 문서화

“끄지 말고, 운영하자”가 요지다.


4) wheel/ABI 에러 메시지 개선이 실무에서 도움이 되는 순간

패키지 설치/빌드 이슈는 대부분 ‘정확한 원인’보다 ‘추측’으로 시간을 버린다.

  • 내 파이썬이 문제인가?
  • 플랫폼 태그가 문제인가?
  • wheel이 잘못 빌드됐나?

0.11.3에서 에러 메시지에 플랫폼을 예쁘게 보여주거나, free-threaded Python 관련 정보를 더 보여주는 개선이 들어갔다.

이런 변화는 릴리스 노트만 보면 밋밋하지만,

  • 장애 대응 속도
  • 새 환경(예: 다른 아키텍처)에서의 온보딩

에 직접 영향을 준다.


5) 업그레이드 후 바로 확인할 것 7개(현장용)

1) uv sync --frozen이 CI에서 그대로 통과하는가 2) lock이 불필요하게 다시 써지지 않는가 3) uv audit 결과가 “읽을 수 있는 형태”로 나오나(과도한 노이즈는 없는가) 4) 예외 처리해야 하는 취약점이 있다면, 무시가 아니라 “이유가 남는 방식”으로 남길 수 있나 5) workspace 프로젝트면 metadata 출력으로 의존성 변화가 설명되는가 6) publish 파이프라인이 있다면, 해시 단계에서 멈춘 것처럼 보이지 않는가 7) 새 환경에서 wheel 에러 메시지로 원인이 빨리 좁혀지는가

이 체크를 통과하면, uv 업그레이드는 ‘버전 올리기’가 아니라 ‘운영 품질 올리기’가 된다.


6) uv audit 예외를 ‘문서화’하는 최소 패턴(팀이 감사 기능을 안 끄게 만드는 방법)

감사를 운영하려면, 예외가 생길 때마다 “왜 무시했는지”가 남아야 한다.

나는 보통 아래 2가지를 같이 둔다.

1) 예외를 코드처럼 관리한다 - PR에 남기고 - 근거 링크(이슈/업스트림 PR/릴리스 예정)를 적는다

2) 예외는 ‘영구 무시’가 아니라 ‘기한 있는 무시’를 기본값으로 둔다 - 여기서 0.11.3의 --ignore-until-fixed가 의미가 있다

예시(의도만 보여주는 커맨드):

# 당장 못 올리는 취약점이 있을 때
# (예: 업스트림 패치 대기)
uv audit --ignore-until-fixed <ADVISORY_ID>

이렇게 해두면,

  • 지금은 막지 않되
  • “고쳐지면 다시 잡히게” 만들 수 있다.

결국 목표는 보안 감사를 ‘완벽’하게 하는 게 아니라, 꺼지지 않게 만드는 거다.


7) workspace/lock 디버깅에 시간 쓰는 팀이라면: metadata 출력으로 “왜 lock이 바뀌었는지”를 설명하자

모노레포에서 자주 생기는 사고는 이런 거다.

  • 누군가 의존성을 추가했는데
  • lock diff가 너무 커서 리뷰가 피곤하고
  • 결과적으로 “그냥 머지”가 된다

0.11.3에서 uv workspace metadata가 lock의 의존성 정보를 더 보여주도록 확장된 건, 이 상황에서 꽤 도움 된다.

실전에서는 이렇게 쓰면 된다.

  • lock이 바뀐 PR에서
  • metadata 출력(또는 요약)을 PR 본문에 붙이고
  • “무엇이 추가/변경됐는지”를 사람 언어로 적는다

이 한 번이 쌓이면, lockfile은 더 이상 ‘검은 상자’가 아니라 리뷰 가능한 산출물이 된다.


8) 릴리스 노트에서 ‘놓치기 쉬운’ 항목들(하지만 장애 대응에서 빛나는 것들)

0.11.3 릴리스 노트에는 이런 항목들도 있다.

  • wheel 에러에서 플랫폼을 예쁘게 출력
  • free-threaded Python 관련 정보를 에러에서 더 보여줌
  • abi3 관련 태그 처리 개선

이건 기능 소개로는 심심하지만, 현장에서는 의미가 크다.

  • 새로운 런타임/플랫폼에서 설치가 깨질 때
  • “뭐가 문제인지”를 빨리 좁히면
  • 하루가 아니라 10분 만에 끝날 때가 있다

도구 업그레이드의 ROI는 결국 여기서 나온다.


Sources

  • uv GitHub Releases — 0.11.3 (Released 2026-04-01)
    • https://github.com/astral-sh/uv/releases/tag/0.11.3
  • PyPI — uv 0.11.3
    • https://pypi.org/project/uv/0.11.3/

Keywords

python,uv,packaging,dependency,lockfile,workspace,metadata,audit,security,vulnerability,ignore,CI,uv publish,hashing,abi3,free-threaded,wheel,error,PEP,release


이미지 크레딧/라이선스

  • CSS code on a screen (Unsplash).jpg — Sai Kiran Anagani / CC0
    • https://commons.wikimedia.org/wiki/File:CSS_code_on_a_screen_(Unsplash).jpg
    • http://creativecommons.org/publicdomain/zero/1.0/deed.en
  • Gaming PC (Unsplash).jpg — Maxime Rossignol / CC0
    • https://commons.wikimedia.org/wiki/File:Gaming_PC_(Unsplash).jpg
    • http://creativecommons.org/publicdomain/zero/1.0/deed.en

댓글

이 블로그의 인기 게시물

Django에서 트랜잭션 관리하기

Django에서 트랜잭션 관리하기 안녕하세요! 오늘은 Django에서 데이터베이스 트랜잭션을 효과적으로 관리하는 방법에 대해 알아보겠습니다. 1. 트랜잭션의 중요성 트랜잭션은 데이터베이스의 일관성과 무결성을 보장하는 중요한 개념입니다. Django에서는 여러 가지 방법으로 트랜잭션을 관리할 수 있습니다. 1.1 기본 개념 원자성(Atomicity) : 트랜잭션은 모두 실행되거나 모두 실행되지 않아야 합니다. 일관성(Consistency) : 트랜잭션 전후로 데이터베이스의 일관성이 유지되어야 합니다. 격리성(Isolation) : 동시에 실행되는 트랜잭션들이 서로 영향을 주지 않아야 합니다. 지속성(Durability) : 완료된 트랜잭션의 결과는 영구적으로 저장되어야 합니다. 2. Django의 트랜잭션 관리 2.1 기본 설정 # settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydatabase', 'USER': 'myuser', 'PASSWORD': 'mypassword', 'HOST': 'localhost', 'PORT': '5432', 'ATOMIC_REQUESTS': True, # 모든 뷰를 트랜잭션으로 래핑 } } 2.2 데코레이터 사용 from django.db import transaction @transaction.atomic def create_order(user, items): order = Order.objects.create(user=...

Python에서 asyncio 완전 정복 (await, async, gather 등)

어휴, 요즘 파이썬으로 비동기 프로그래밍 하는 재미에 푹 빠졌어요! 특히 asyncio 는 정말 마법 같더라고요. 처음엔 좀 낯설었는데, 익숙해지니까 속도 향상이 눈에 띄게 느껴져서 완전 반해버렸습니다. 이 글에선 제가 asyncio 를 배우면서 깨달은 점들을 풀어놓을게요. 혹시 비동기 프로그래밍이 뭔지 잘 모르시겠다면, 간단히 말해 여러 작업을 동시에 처리해서 프로그램 속도를 엄청나게 높이는 기술이라고 생각하시면 돼요. 마치 여러 요리사가 동시에 음식을 만들어서 손님에게 빨리 제공하는 것과 비슷하죠! 일단 async 와 await 라는 녀석들이 핵심인데요, async 는 함수 앞에 붙여서 "얘는 비동기 함수야!"라고 선언하는 거예요. 그리고 await 는 다른 비동기 함수가 끝날 때까지 기다리라고 지시하는 역할을 하죠. 예를 들어, 네트워크에서 데이터를 가져오는 함수가 있다면, await 를 사용해서 데이터가 다 가져올 때까지 기다렸다가 다음 작업을 진행할 수 있어요. 그 동안 다른 작업을 처리할 수 있으니, 마치 멀티태스킹을 하는 것처럼 느껴져요. 신기하지 않나요? 그리고 asyncio.gather 는 여러 비동기 함수를 동시에 실행하고 결과를 모아주는 아주 유용한 친구입니다. 제가 웹사이트 여러 개에서 데이터를 동시에 가져와야 할 때 정말 요긴하게 썼어요. 하나씩 순서대로 가져오는 것보다 훨씬 빠르더라고요! 마치 여러 개의 탭을 동시에 열어놓고 작업하는 것과 같다고 생각하시면 될 것 같아요. 실제로 제가 썼던 코드를 보여드릴게요. 세 개의 웹사이트에서 데이터를 가져오는 예제인데요. (아래 코드 삽입) 이 코드를 보시면, fetch_data 함수가 각 웹사이트에서 데이터를 가져오는 역할을 하고, asyncio.gather 가 이 함수들을 동시에 실행하도록 도와주는 것을 볼 수 있을 거예요. asyncio.sleep(2) 는 네트워크 지연을 시뮬레이션하기 위해 넣...

AWS S3 + CloudFront로 정적 파일 서빙 완전 가이드

AWS S3 + CloudFront로 정적 파일 서빙 완전 가이드 안녕하세요! 오늘은 AWS S3와 CloudFront를 사용하여 정적 파일을 효율적으로 서빙하는 방법에 대해 알아보겠습니다. 왜 S3와 CloudFront를 사용할까요? 높은 가용성 : AWS의 글로벌 인프라를 활용 빠른 전송 속도 : CloudFront의 CDN 기능으로 전 세계 사용자에게 빠른 전송 비용 효율성 : 사용한 만큼만 지불 보안 : AWS의 보안 기능 활용 확장성 : 트래픽 증가에 자동 대응 1. S3 버킷 설정 1.1 버킷 생성 및 설정 import boto3 def create_s3_bucket(): s3 = boto3.client('s3') # 버킷 생성 bucket_name = 'your-static-files-bucket' s3.create_bucket( Bucket=bucket_name, CreateBucketConfiguration={ 'LocationConstraint': 'ap-northeast-2' } ) # 버킷 정책 설정 bucket_policy = { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObje...