티스토리 뷰
작성일: 2026년 1월 16일
카테고리: Python, 개발 도구, 패키징
키워드: uv, Python, editable install, 개발 모드, pip, 패키지 개발

요약
uv는 Python 패키지를 기본적으로 editable mode로 설치한다. uv sync 한 번으로 프로젝트와 의존성이 모두 개발 모드로 설치되어, 코드 수정 시 재설치 없이 즉시 반영된다. 기존 pip의 pip install -e .보다 10배 빠르며, 현대적인 Python 패키지 개발의 표준이 되고 있다.
왜 Editable Install이 필요한가?
반복 작업의 고통
Python 패키지를 개발할 때 다음 과정을 수백 번 반복한다:
# 1. 코드 수정
vim mypackage/utils.py
# 2. 패키지 재설치
pip install .
# 3. 테스트
python test.py
# 4. 또 수정
vim mypackage/utils.py
# 5. 또 재설치
pip install .
# 무한 반복...
문제: 매번 재설치는 시간 낭비다.
일반 설치 vs Editable 설치
일반 설치 (pip install .):
프로젝트 디렉토리 → [복사] → site-packages/- 파일을 site-packages로 복사
- 코드 수정 → 재설치 필요
Editable 설치 (pip install -e . 또는 uv sync):
프로젝트 디렉토리 ← [링크] ← site-packages/- 프로젝트 디렉토리를 링크만 연결
- 코드 수정 → 즉시 반영
비유
일반 설치: 책을 복사해서 책장에 넣기
- 원본 수정해도 책장의 책은 그대로
Editable 설치: 책의 위치를 메모만 해두기
- 원본 수정하면 바로 확인 가능
uv의 Editable Install: 기본이 개발 모드
핵심 철학
uv는 "개발하는 동안은 항상 editable이어야 한다"는 철학을 가진다.
# uv: editable이 기본
uv sync
# 이것만으로 프로젝트가 editable로 설치됨
# 별도 플래그 불필요
프로젝트 구조 예시
my-package/
├── pyproject.toml
├── src/
│ └── mypackage/
│ ├── __init__.py
│ └── utils.py
└── tests/
└── test_utils.pypyproject.toml:
[project]
name = "mypackage"
version = "0.1.0"
dependencies = []
[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]
개발 워크플로우
# 1. 프로젝트 동기화 (editable 설치)
cd my-package
uv sync
# 2. 코드 수정
vim src/mypackage/utils.py
# 3. 즉시 테스트 (재설치 불필요!)
uv run pytest
# 4. 또 수정
vim src/mypackage/utils.py
# 5. 또 즉시 테스트
uv run pytest
# 재설치 없이 무한 반복 가능
pip와의 비교
| 작업 | pip | uv |
|---|---|---|
| Editable 설치 | pip install -e . |
uv sync |
| 개발 의존성 | pip install -e .[dev] |
uv sync --group dev (자동) |
| 실행 | python script.py |
uv run python script.py |
| 재설치 여부 | -e 플래그 있어야 editable | 기본이 editable |
| 속도 | 느림 (Python 구현) | 매우 빠름 (Rust 구현) |
성능 비교
실측 예시:
# pip (전통적 방식)
$ time pip install -e .
real 0m8.543s
# uv (현대적 방식)
$ time uv sync
real 0m0.892s
uv가 약 10배 빠르다.
uv 사용법
1. 기본 동기화
# 프로젝트를 editable로 설치
uv sync
# 이제 어디서든 import 가능
python
>>> import mypackage
>>> mypackage.__file__
'/home/user/projects/my-package/src/mypackage/__init__.py'
경로가 프로젝트 디렉토리를 가리키면 성공이다.
2. 개발 의존성 포함
[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]
docs = ["sphinx"]
# 모든 optional dependencies 포함
uv sync --all-extras
# 특정 그룹만
uv sync --extra dev
3. 로컬 의존성도 Editable로
여러 패키지를 동시에 개발할 때:
# my-api/pyproject.toml
[project]
dependencies = ["mylib"]
[tool.uv.sources]
mylib = { path = "../my-lib", editable = true }
# my-api 프로젝트에서
uv sync
# mylib도 자동으로 editable 설치됨
이제 my-lib를 수정하면 my-api에서 즉시 반영된다.
4. Non-editable이 필요한 경우
프로덕션이나 CI 환경에서는:
# Non-editable 설치
uv sync --no-editable
# 또는 프로덕션 전용 명령
uv pip install .
5. 스크립트 실행
# uv run으로 실행 (격리된 환경)
uv run python script.py
# uv run으로 테스트
uv run pytest
# uv run으로 린터
uv run black src/
uv run mypy src/
uv run은 자동으로 가상환경을 활성화하고 실행한다.
실전 활용 사례
1. 라이브러리 개발
# 프로젝트 구조
mylibrary/
├── pyproject.toml
├── src/
│ └── mylibrary/
│ ├── __init__.py
│ └── core.py
└── tests/
└── test_core.py
# 한 번만 동기화
cd mylibrary
uv sync
# 개발 루프
vim src/mylibrary/core.py # 수정
uv run pytest # 즉시 테스트
vim src/mylibrary/core.py # 또 수정
uv run pytest # 또 즉시 테스트
2. 모노레포: 여러 패키지 동시 개발
workspace/
├── packages/
│ ├── core/ # 핵심 라이브러리
│ ├── api/ # API (core 의존)
│ └── cli/ # CLI (api, core 의존)
각 패키지의 pyproject.toml:
# packages/api/pyproject.toml
[project]
dependencies = ["mycore"]
[tool.uv.sources]
mycore = { path = "../core", editable = true }
# packages/cli/pyproject.toml
[project]
dependencies = ["myapi", "mycore"]
[tool.uv.sources]
myapi = { path = "../api", editable = true }
mycore = { path = "../core", editable = true }
# CLI 패키지에서 동기화
cd packages/cli
uv sync
# 이제 core, api, cli 모두 editable
# 어느 패키지를 수정해도 즉시 반영
3. 오픈소스 라이브러리 디버깅
# 라이브러리 클론
git clone https://github.com/some/library.git
cd library
# Editable 설치
uv sync
# 소스 수정하며 디버깅
vim src/library/module.py
# 내 프로젝트에서 즉시 수정된 라이브러리 사용
cd ~/my-project
uv run python app.py # library의 수정사항 반영됨
4. 플러그인 시스템 개발
plugins/
├── main-app/
├── plugin-auth/
├── plugin-payment/
└── plugin-analytics/
각 플러그인을 editable로:
# 메인 앱
cd main-app && uv sync
# 플러그인들
cd ../plugin-auth && uv sync
cd ../plugin-payment && uv sync
cd ../plugin-analytics && uv sync
# 모든 플러그인을 수정하며 실시간 테스트
cd main-app
uv run python main.py # 모든 플러그인 변경사항 즉시 반영
pip로 Editable Install 하기 (레거시)
기존 프로젝트나 팀에서 pip를 사용한다면:
pip install -e
# 현재 디렉토리를 editable로
pip install -e .
# 특정 경로
pip install -e /path/to/package
# 의존성 포함
pip install -e .[dev]
pip의 한계
# 1. 느림
$ time pip install -e .
real 0m8.543s
# 2. 명시적 플래그 필요
pip install -e . # -e 빼먹으면 일반 설치
# 3. 의존성 해석 느림
pip install -e .[dev,docs,test] # 수 초 대기
# 4. 가상환경 별도 관리
python -m venv .venv
source .venv/bin/activate
pip install -e .
uv로 마이그레이션
기존 pip 명령어를 uv로 전환:
| pip | uv |
|---|---|
pip install -e . |
uv sync |
pip install -e .[dev] |
uv sync --extra dev |
python script.py |
uv run python script.py |
pytest |
uv run pytest |
추가 이점:
- 10배 빠른 속도
- 자동 가상환경 관리
- lock 파일로 재현 가능성
동작 원리
Editable Install의 내부 구조
패키지를 editable로 설치하면 링크 파일이 생성된다:
$ ls .venv/lib/python3.11/site-packages/ | grep editable
__editable___mypackage-0.1.0-py3.11.pth
__editable___mypackage_0_1_0_finder.py
.pth 파일
# __editable___mypackage-0.1.0-py3.11.pth
import __editable___mypackage_0_1_0_finder; \
__editable___mypackage_0_1_0_finder.install()
Python 시작 시 이 파일이 자동 실행된다.
Finder 파일
# __editable___mypackage_0_1_0_finder.py
MAPPING = {
'mypackage': '/home/user/projects/my-package/src/mypackage'
}
def install():
# Import hook 등록
# mypackage import 시 MAPPING 경로로 리다이렉트
Import 과정
graph LR
Import[import mypackage]
Finder[Editable Finder]
Mapping[경로 매핑]
Source[프로젝트 소스]
Module[모듈 로드]
Import --> Finder
Finder --> Mapping
Mapping --> Source
Source --> Module
style Import stroke:#2563eb,stroke-width:3px
style Finder stroke:#16a34a,stroke-width:2px
style Source stroke:#ea580c,stroke-width:3px
style Module stroke:#dc2626,stroke-width:2px
import mypackage실행- Editable finder가 가로챔
- 매핑 테이블에서 실제 경로 확인
- 프로젝트 소스 디렉토리에서 로드
uv의 고급 기능
1. Workspace 지원
uv.toml (워크스페이스 루트):
[workspace]
members = ["packages/*"]
# 한 번에 모든 패키지 동기화
uv sync --workspace
# 모든 패키지가 editable로 설치됨
2. Lock 파일로 재현성
# 처음 동기화 시 uv.lock 생성
uv sync
# 다른 환경에서 동일한 버전 설치
uv sync --frozen
CI/CD에서 정확히 같은 환경을 재현할 수 있다.
3. 빠른 의존성 추가
# 의존성 추가 + 동기화 (한 번에)
uv add requests
# 개발 의존성 추가
uv add --dev pytest
# Editable 상태 유지됨
4. 선택적 동기화
# 특정 패키지만 업데이트
uv sync --package mypackage
# 의존성 제외 (프로젝트만)
uv sync --no-deps
주의사항
1. C/C++ 확장 모듈
Python 파일만 editable이다. C 확장 모듈은 재빌드가 필요하다:
# C 코드 수정 후
uv sync # 재빌드 트리거
2. IDE Import 해석 문제
VSCode의 Pylance 등은 PEP-660 import hook을 제대로 인식 못할 수 있다.
증상:
import mypackage # "Import could not be resolved" 경고
실제로는 실행되지만 IDE가 경고를 표시한다.
해결책:
- VSCode 재시작
- Python 인터프리터 재선택 (Cmd/Ctrl+Shift+P → "Python: Select Interpreter")
.venv경로를 명시적으로 선택
3. 프로덕션 배포
Editable은 개발 전용이다. 프로덕션에서는:
# ❌ 프로덕션에서 이러면 안 됨
uv sync
# ✅ Non-editable 설치
uv sync --no-editable
# ✅ 빌드하여 배포
uv build
uv pip install dist/mypackage-0.1.0-py3-none-any.whl
4. 경로 이동
Editable 설치는 절대 경로를 사용한다:
# Editable 설치
cd /home/user/project
uv sync
# 프로젝트 이동
mv /home/user/project /opt/project
# ❌ Import 실패
python -c "import mypackage" # ModuleNotFoundError
해결:
cd /opt/project
uv sync # 새 경로로 재설치
5. 의존성 메타데이터 변경
코드 변경은 즉시 반영되지만, 메타데이터 변경은 재동기화 필요:
# pyproject.toml 수정
vim pyproject.toml
# 재동기화 필요
uv sync
pip vs uv 완전 비교
설치
| 작업 | pip | uv |
|---|---|---|
| Editable 설치 | pip install -e . |
uv sync |
| 개발 의존성 | pip install -e .[dev] |
uv sync --extra dev |
| 속도 | 8초 | 0.9초 |
실행
| 작업 | pip | uv |
|---|---|---|
| 가상환경 활성화 | source .venv/bin/activate |
불필요 |
| 스크립트 실행 | python script.py |
uv run python script.py |
| 테스트 | pytest |
uv run pytest |
의존성 관리
| 작업 | pip | uv |
|---|---|---|
| 의존성 추가 | vim pyproject.toml + pip install -e . |
uv add package |
| Lock 파일 | 별도 도구 필요 | uv.lock 자동 생성 |
| 재현성 | requirements.txt 수동 관리 | uv sync --frozen |
모노레포
| 작업 | pip | uv |
|---|---|---|
| 로컬 패키지 링크 | 각각 pip install -e |
tool.uv.sources + uv sync |
| 워크스페이스 | 미지원 | uv sync --workspace |
마이그레이션 가이드
Step 1: uv 설치
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Homebrew
brew install uv
Step 2: 기존 프로젝트 전환
# 기존 가상환경 제거 (선택)
rm -rf .venv
# uv로 동기화
uv sync
# 테스트
uv run pytest
Step 3: CI/CD 업데이트
Before (pip):
- name: Install dependencies
run: |
python -m venv .venv
source .venv/bin/activate
pip install -e .[dev]
- name: Run tests
run: |
source .venv/bin/activate
pytest
After (uv):
- name: Setup uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Run tests
run: uv run pytest
훨씬 간단하고 빠르다.
Step 4: 팀원 교육
# 기존 명령어 → uv 명령어
pip install -e . → uv sync
pip install requests → uv add requests
python script.py → uv run python script.py
pytest → uv run pytest
문제 해결
"No pyproject.toml found"
원인: 프로젝트 루트가 아닌 디렉토리에서 실행
해결:
cd /path/to/project # pyproject.toml이 있는 디렉토리로 이동
uv sync
Import가 안 됨
확인:
$ uv run python -c "import sys; print(sys.path)"
프로젝트 경로가 포함되어 있는지 확인.
해결:
# 재동기화
uv sync
# 또는 가상환경 재생성
rm -rf .venv
uv sync
변경사항이 반영 안 됨
원인: Python 인터프리터가 모듈을 캐시
해결:
# Python 재시작
exit()
# 새 세션에서
uv run python
>>> import mypackage # 변경사항 반영됨
uv가 느림
원인: 네트워크 문제 또는 대량 의존성
해결:
# 캐시 확인
uv cache clean
# 오프라인 모드 (캐시만 사용)
uv sync --offline
요약
Editable Install이란?
| 항목 | 일반 설치 | Editable 설치 |
|---|---|---|
| 파일 위치 | site-packages에 복사 | 프로젝트 디렉토리 링크 |
| 코드 수정 시 | 재설치 필요 | 즉시 반영 |
| 용도 | 프로덕션, 배포 | 개발, 디버깅 |
| 속도 | 느림 (복사) | 빠름 (링크만) |
uv의 장점
- 기본이 Editable: 별도 플래그 불필요
- 10배 빠른 속도: Rust 구현
- 자동 가상환경: 활성화 불필요
- Lock 파일: 재현 가능한 환경
- Workspace 지원: 모노레포 최적화
권장 사항
신규 프로젝트: uv 사용 강력 권장
- 현대적이고 빠름
- 개발 경험 우수
기존 프로젝트: 점진적 마이그레이션
uv sync로 전환 용이- 기존 pip와 혼용 가능
Editable install은 Python 패키지 개발의 필수 기능이며, uv는 이를 가장 편리하고 빠르게 사용할 수 있는 도구다.
참고 자료
uv 공식 문서
- uv: Managing packages
- uv: Configuring projects
- Using Python UV with Editable Source Code Dependencies
Python 패키징 표준
pip (레거시)
'실제 경험과 인사이트를 AI와 함께 정리한 글' 카테고리의 다른 글
| Agent Skills로 Claude Code 확장하기: React 개발 역량 강화 (0) | 2026.01.16 |
|---|---|
| Claude Code 커밋 메시지 자동 서명 비활성화하기 (0) | 2026.01.16 |
| watchmedo: Python 파일 시스템 변경 감지 도구 (0) | 2026.01.16 |
| Antigravity IDE "Agent terminated due to error" 해결하기: Gemini /stats로 사용 한도 진단 (0) | 2026.01.16 |
| Streamlit으로 테스트 도구 만들기: API 테스터 구축 실전 가이드 (0) | 2026.01.09 |
- Total
- Today
- Yesterday
- SHACL
- api gateway
- 개발 도구
- Rag
- Next.js
- AI agent
- backend
- knowledge graph
- frontend
- Developer Tools
- Tailwind CSS
- security
- AI Development
- Ontology
- authentication
- AGENTS.md
- imprun.dev
- troubleshooting
- Go
- Tax Analysis
- architecture
- authorization
- PYTHON
- Claude Opus 4.5
- claude code
- react
- LLM
- AI
- Development Tools
- Kubernetes
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
