Python 패키지 매니저 uv에서 개발용 의존성(dev-dependencies) 설치 및 관리 방법
Problem
Python 프로젝트에서 uv를 도입하여 가상 환경과 의존성을 관리하려고 할 때, 프로덕션용 의존성과 로컬 개발용 의존성(예: pytest, factory-boy 등)을 함께 설치하는 데 어려움을 겪는 경우가 많습니다. 기존의 uv pip compile과 uv pip sync 명령어를 사용하면 requirements.txt가 생성되지만, 개발용 의존성은 누락되기 쉽습니다. 또한 uv sync를 시도했을 때 프로젝트 구조 설정 문제로 에러가 발생하거나, 개발용 패키지가 정확히 어떻게 관리되는지 헷갈릴 수 있습니다.
Background
Python 프로젝트의 의존성은 크게 세 가지로 나눌 수 있습니다. 첫째, 앱 실행에 필수적인 프로덕션 의존성, 둘째, 특정 기능에만 필요한 선택적 의존성(Optional dependencies), 셋째, 테스트나 린팅 등 로컬 개발에만 필요한 **개발용 의존성(Development dependencies)**입니다. 과거에는 requirements.txt와 requirements-dev.txt로 나누어 관리했지만, 최근 Python 생태계는 pyproject.toml 하나로 통합하는 추세입니다. 특히 최근 제안된 PEP 735 표준에 따라 개발용 의존성은 pyproject.toml 내의 [dependency-groups] 테이블에서 관리하는 것이 권장되며, uv는 이 최신 표준을 완벽하게 지원합니다.
Solution
uv를 사용하여 개발용 의존성을 추가하고 설치하는 방법은 매우 직관적입니다. 기존의 복잡한 pip compile 과정 없이 uv의 자체 명령어를 사용하는 것이 핵심입니다.
1. Python 버전 고정하기
프로젝트에서 사용할 Python 버전을 먼저 지정합니다. 이 명령어는 .python-version 파일을 생성합니다.
# Python 3.10 버전을 프로젝트에 고정
uv python pin 3.10
2. 개발용 의존성 추가하기
개발에만 필요한 패키지(예: pytest, factory-boy)를 추가할 때는 --dev 플래그를 사용합니다.
# 프로덕션 의존성 추가
uv add django
# 개발용 의존성 추가
uv add --dev factory-boy pytest
위 명령어를 실행하면 pyproject.toml 파일이 다음과 같이 자동으로 구성됩니다.
[project]
name = "my-project"
dynamic = ["version"]
requires-python = ">=3.10"
dependencies = [
"django",
]
# PEP 735 표준을 따르는 의존성 그룹
[dependency-groups]
dev = [
"factory-boy",
"pytest",
]
3. 가상 환경 생성 및 의존성 설치 (Sync)
로컬 개발 환경을 세팅할 때는 uv sync 명령어 하나면 충분합니다. 이 명령어는 가상 환경(.venv)을 자동으로 생성하고, 프로덕션 의존성과 개발용 의존성을 모두 설치합니다.
# 가상 환경 생성 및 모든 의존성(dev 포함) 설치
uv sync
# 가상 환경 활성화 (macOS/Linux)
source .venv/bin/activate
4. 프로덕션 환경에서 설치하기
CI/CD 파이프라인이나 실제 운영 서버에서는 테스트 도구 같은 개발용 의존성이 필요 없습니다. 이때는 --no-dev 플래그를 사용합니다.
# 개발용 의존성을 제외하고 프로덕션 패키지만 설치
uv sync --no-dev
Deep Dive
uv는 dev 그룹 외에도 사용자가 원하는 임의의 의존성 그룹을 만들 수 있도록 지원합니다. 예를 들어 테스트용 패키지와 문서화용 패키지를 분리하고 싶다면 uv add --group docs sphinx와 같이 사용할 수 있습니다. 이렇게 추가된 특정 그룹만 설치하려면 uv sync --group docs를 실행하면 됩니다.
또한 uv add --dev는 사실 uv add --group dev의 문법적 설탕(Syntactic sugar)입니다. 기본적으로 uv sync는 dev 그룹을 자동으로 포함하여 설치하지만, pyproject.toml의 [tool.uv] 섹션에서 default-groups = ["dev", "test"]와 같이 설정하여 기본으로 설치될 그룹을 직접 커스터마이징할 수도 있습니다.
Conclusion
uv를 사용할 때는 레거시 방식인 requirements.txt 생성 방식(uv pip compile)에서 벗어나, pyproject.toml과 uv sync를 활용하는 모던 워크플로우로 전환하는 것이 좋습니다. 로컬 개발 시에는 uv add --dev로 패키지를 추가하고 uv sync로 설치하며, 배포 시에는 uv sync --no-dev를 사용하여 깔끔하고 표준화된 의존성 관리를 구현해 보세요.