신입 개발자를 위한 Python uv 완벽 가이드: 현대적인 패키지 관리의 시작
Python 개발을 시작하는 신입 개발자라면 패키지 관리와 가상환경 설정에 대해 고민해본 적이 있을 것입니다. 기존의 pip
, virtualenv
, conda
등 다양한 도구들이 있지만, 최근 주목받고 있는 uv는 이 모든 것을 하나로 통합한 혁신적인 도구입니다. 이번 포스트에서는 uv가 무엇인지, 왜 사용해야 하는지, 그리고 실제로 어떻게 사용하는지를 신입 개발자 관점에서 상세히 알아보겠습니다.
uv란 무엇인가?
uv는 Astral에서 개발한 Python 패키지 및 프로젝트 관리 도구입니다. Rust로 작성되어 기존 Python 도구들보다 월등히 빠른 성능을 자랑하며, 다음과 같은 기능을 하나의 도구로 통합했습니다:
- 패키지 설치 및 관리 (pip 대체)
- 가상환경 생성 및 관리 (virtualenv 대체)
- 프로젝트 의존성 관리 (requirements.txt 개선)
- Python 버전 관리 (pyenv 유사 기능)
- 프로젝트 스캐폴딩 (cookiecutter 유사 기능)
왜 uv를 사용해야 할까?
1. 압도적인 속도
- 10-100배 빠른 패키지 설치: Rust로 작성되어 기존 pip보다 월등히 빠름
- 병렬 다운로드: 여러 패키지를 동시에 다운로드하여 시간 단축
2. 통합된 워크플로우
- 하나의 도구로 모든 것 해결: 여러 도구를 배울 필요 없음
- 일관된 명령어 체계: 직관적이고 기억하기 쉬운 명령어
3. 현대적인 의존성 관리
- 자동 잠금 파일 생성: 재현 가능한 빌드 보장
- 의존성 해결 최적화: 충돌 없는 패키지 조합 자동 계산
uv 설치하기
macOS/Linux 설치
가장 간단한 방법은 공식 설치 스크립트를 사용하는 것입니다:
# 공식 설치 스크립트 사용
curl -LsSf https://astral.sh/uv/install.sh | sh
Homebrew를 사용하는 경우:
# Homebrew로 설치
brew install uv
Windows 설치
PowerShell에서 다음 명령을 실행합니다:
# PowerShell에서 설치
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
또는 Scoop을 사용하는 경우:
# Scoop으로 설치
scoop install uv
설치 확인
설치가 완료되면 다음 명령으로 확인할 수 있습니다:
# uv 버전 확인
uv --version
# 도움말 보기
uv --help
첫 번째 Python 프로젝트 만들기
1. 새 프로젝트 생성
uv를 사용하여 새로운 Python 프로젝트를 생성해보겠습니다:
# 새 프로젝트 생성
uv init my-first-project
# 프로젝트 디렉토리로 이동
cd my-first-project
생성된 프로젝트 구조를 살펴보면:
my-first-project/
├── .python-version # Python 버전 지정
├── pyproject.toml # 프로젝트 설정 파일
├── README.md # 프로젝트 설명
└── src/
└── my_first_project/
└── __init__.py
2. pyproject.toml 이해하기
pyproject.toml
파일은 프로젝트의 메타데이터와 의존성을 정의합니다:
[project]
name = "my-first-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.8"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
3. Python 버전 관리
uv는 Python 버전 관리도 지원합니다:
# 사용 가능한 Python 버전 확인
uv python list
# 특정 Python 버전 설치
uv python install 3.12
# 프로젝트에 Python 버전 지정
uv python pin 3.12
패키지 관리하기
1. 패키지 추가하기
프로젝트에 필요한 패키지를 추가해보겠습니다:
# 패키지 추가 (자동으로 pyproject.toml에 추가됨)
uv add requests
# 개발 의존성 추가
uv add --dev pytest black flake8
# 특정 버전 지정
uv add "django>=4.0,<5.0"
# 여러 패키지 동시 추가
uv add fastapi uvicorn python-multipart
2. 패키지 제거하기
# 패키지 제거
uv remove requests
# 개발 의존성 제거
uv remove --dev pytest
3. 의존성 설치하기
기존 프로젝트를 클론했거나 새로운 환경에서 작업할 때:
# 모든 의존성 설치
uv sync
# 개발 의존성 제외하고 설치
uv sync --no-dev
가상환경 관리하기
1. 가상환경 생성 및 활성화
uv는 자동으로 가상환경을 관리하지만, 수동으로도 제어할 수 있습니다:
# 가상환경 생성
uv venv
# 가상환경 활성화 (Linux/macOS)
source .venv/bin/activate
# 가상환경 활성화 (Windows)
.venv\Scripts\activate
# 가상환경 비활성화
deactivate
2. uv run으로 간편하게 실행하기
가상환경을 수동으로 활성화하지 않고도 명령을 실행할 수 있습니다:
# Python 스크립트 실행
uv run python main.py
# 설치된 패키지의 명령어 실행
uv run pytest
# 일회성 패키지 실행
uv run --with requests python -c "import requests; print(requests.get('https://httpbin.org/json').json())"
실전 예제: 웹 스크래핑 프로젝트
실제 프로젝트를 통해 uv 사용법을 익혀보겠습니다.
1. 프로젝트 설정
# 새 프로젝트 생성
uv init web-scraper
cd web-scraper
# 필요한 패키지 추가
uv add requests beautifulsoup4 pandas
# 개발 도구 추가
uv add --dev pytest black isort mypy
2. 메인 스크립트 작성
src/web_scraper/main.py
파일을 생성합니다:
"""간단한 웹 스크래핑 예제"""
import requests
from bs4 import BeautifulSoup
import pandas as pd
from typing import List, Dict
def scrape_quotes() -> List[Dict[str, str]]:
"""명언 사이트에서 명언들을 스크래핑합니다."""
url = "http://quotes.toscrape.com/"
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
quotes = []
for quote in soup.find_all('div', class_='quote'):
text = quote.find('span', class_='text').text
author = quote.find('small', class_='author').text
tags = [tag.text for tag in quote.find_all('a', class_='tag')]
quotes.append({
'text': text,
'author': author,
'tags': ', '.join(tags)
})
return quotes
def save_to_csv(quotes: List[Dict[str, str]], filename: str = 'quotes.csv') -> None:
"""명언들을 CSV 파일로 저장합니다."""
df = pd.DataFrame(quotes)
df.to_csv(filename, index=False, encoding='utf-8')
print(f"총 {len(quotes)}개의 명언이 {filename}에 저장되었습니다.")
def main():
"""메인 함수"""
print("웹 스크래핑을 시작합니다...")
quotes = scrape_quotes()
save_to_csv(quotes)
# 첫 번째 명언 출력
if quotes:
print(f"\n첫 번째 명언:")
print(f"'{quotes[0]['text']}'")
print(f"- {quotes[0]['author']}")
if __name__ == "__main__":
main()
3. 테스트 코드 작성
tests/test_main.py
파일을 생성합니다:
"""웹 스크래핑 함수들에 대한 테스트"""
import pytest
from src.web_scraper.main import scrape_quotes, save_to_csv
import os
def test_scrape_quotes():
"""스크래핑 함수 테스트"""
quotes = scrape_quotes()
# 기본 검증
assert len(quotes) > 0
assert all('text' in quote for quote in quotes)
assert all('author' in quote for quote in quotes)
assert all('tags' in quote for quote in quotes)
def test_save_to_csv():
"""CSV 저장 함수 테스트"""
test_quotes = [
{'text': 'Test quote', 'author': 'Test Author', 'tags': 'test, example'}
]
test_filename = 'test_quotes.csv'
save_to_csv(test_quotes, test_filename)
# 파일이 생성되었는지 확인
assert os.path.exists(test_filename)
# 테스트 파일 정리
os.remove(test_filename)
4. 프로젝트 실행 및 테스트
# 메인 스크립트 실행
uv run python src/web_scraper/main.py
# 테스트 실행
uv run pytest
# 코드 포맷팅
uv run black src/ tests/
# 타입 체킹
uv run mypy src/
고급 기능 활용하기
1. 스크립트 정의하기
pyproject.toml
에 자주 사용하는 명령어를 스크립트로 정의할 수 있습니다:
[project.scripts]
scrape = "web_scraper.main:main"
[tool.uv]
dev-dependencies = [
"pytest>=7.0.0",
"black>=23.0.0",
"isort>=5.0.0",
"mypy>=1.0.0",
]
[tool.uv.scripts]
test = "pytest tests/"
format = "black src/ tests/"
lint = "mypy src/"
check = ["uv run format", "uv run lint", "uv run test"]
이제 다음과 같이 간단하게 실행할 수 있습니다:
# 스크립트 실행
uv run scrape
# 개발 명령어들
uv run test
uv run format
uv run lint
uv run check # 모든 검사를 순차적으로 실행
2. 환경별 의존성 관리
# 프로덕션 환경용 그룹 생성
uv add --group production gunicorn
# 테스트 환경용 그룹 생성
uv add --group test pytest-cov pytest-mock
# 특정 그룹만 설치
uv sync --group production
3. 잠금 파일 관리
uv는 자동으로 uv.lock
파일을 생성하여 정확한 버전을 기록합니다:
# 잠금 파일 업데이트
uv lock
# 잠금 파일 기반으로 설치
uv sync --frozen
기존 프로젝트를 uv로 마이그레이션하기
1. requirements.txt에서 마이그레이션
# 기존 requirements.txt가 있는 프로젝트에서
uv init --no-readme
# requirements.txt의 패키지들을 pyproject.toml로 이동
uv add $(cat requirements.txt)
2. Poetry에서 마이그레이션
# pyproject.toml이 이미 있는 Poetry 프로젝트에서
uv sync
# Poetry 특정 설정들을 uv 형식으로 조정
팀 협업을 위한 베스트 프랙티스
1. 프로젝트 설정 표준화
팀에서 사용할 표준 pyproject.toml
템플릿:
[project]
name = "project-name"
version = "0.1.0"
description = "프로젝트 설명"
readme = "README.md"
requires-python = ">=3.9"
authors = [
{name = "Your Name", email = "your.email@example.com"}
]
dependencies = []
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"isort>=5.0.0",
"mypy>=1.0.0",
"pre-commit>=3.0.0",
]
[tool.uv]
dev-dependencies = [
"pytest>=7.0.0",
"black>=23.0.0",
"isort>=5.0.0",
"mypy>=1.0.0",
]
[tool.black]
line-length = 88
target-version = ['py39']
[tool.isort]
profile = "black"
line_length = 88
[tool.mypy]
python_version = "3.9"
warn_return_any = true
warn_unused_configs = true
2. 개발 환경 설정 자동화
프로젝트 루트에 setup.sh
스크립트 생성:
#!/bin/bash
# 개발 환경 설정 스크립트
echo "🚀 개발 환경을 설정합니다..."
# uv 설치 확인
if ! command -v uv &> /dev/null; then
echo "❌ uv가 설치되어 있지 않습니다."
echo "설치 방법: curl -LsSf https://astral.sh/uv/install.sh | sh"
exit 1
fi
# 의존성 설치
echo "📦 의존성을 설치합니다..."
uv sync
# pre-commit 훅 설치
echo "🔧 pre-commit 훅을 설치합니다..."
uv run pre-commit install
echo "✅ 개발 환경 설정이 완료되었습니다!"
echo "다음 명령어로 개발을 시작하세요:"
echo " uv run python src/main.py"
echo " uv run pytest"
3. CI/CD 설정
GitHub Actions 예제 (.github/workflows/test.yml
):
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v1
with:
version: "latest"
- name: Set up Python $
run: uv python install $
- name: Install dependencies
run: uv sync --all-extras --dev
- name: Run tests
run: uv run pytest
- name: Run linting
run: |
uv run black --check src/ tests/
uv run isort --check-only src/ tests/
uv run mypy src/
문제 해결 및 팁
자주 발생하는 문제들
1. 패키지 충돌 해결
# 의존성 트리 확인
uv tree
# 특정 패키지의 의존성 확인
uv tree --package requests
# 충돌 해결을 위한 강제 업데이트
uv lock --upgrade
2. 캐시 관리
# 캐시 정보 확인
uv cache info
# 캐시 정리
uv cache clean
# 특정 패키지 캐시만 정리
uv cache clean requests
3. 디버깅
# 상세한 로그 출력
uv --verbose add requests
# 매우 상세한 로그
uv -vv sync
성능 최적화 팁
1. 병렬 설치 활용
# 최대 병렬 작업 수 설정
UV_CONCURRENT_DOWNLOADS=10 uv sync
2. 로컬 인덱스 사용
# 사내 PyPI 서버 사용
uv add --index-url https://pypi.company.com/simple/ internal-package
결론
uv는 Python 개발 환경을 혁신적으로 개선하는 도구입니다. 신입 개발자에게 특히 유용한 이유는:
주요 장점 요약
- 학습 곡선 완화: 하나의 도구로 모든 것을 해결
- 빠른 개발 속도: 압도적인 패키지 설치 속도
- 현대적인 워크플로우: 업계 표준에 맞는 프로젝트 구조
- 팀 협업 최적화: 일관된 개발 환경 보장
- 미래 지향적: 지속적인 업데이트와 커뮤니티 지원
다음 단계
uv를 마스터했다면 다음 단계로 나아가보세요:
- Docker와 연동: 컨테이너 환경에서 uv 활용
- CI/CD 파이프라인: 자동화된 테스트 및 배포
- 모노레포 관리: 여러 Python 프로젝트 통합 관리
- 패키지 배포: PyPI에 자신만의 패키지 배포
Python 개발의 새로운 표준이 되어가고 있는 uv와 함께 더욱 효율적이고 즐거운 개발 경험을 만들어보세요!
이 가이드는 uv 0.4.x 버전을 기준으로 작성되었습니다. 최신 기능은 공식 문서를 참고하세요.