

FastAPI 튜토리얼을 따라 하다가 첫 줄에서 막혔다.
$ uv add "fastapi[standard]"
error: No `pyproject.toml` found in current directory or any parent directory
패키지 이름을 잘못 쓴 것도, uv가 안 깔린 것도 아니었다. 원인은 훨씬 단순했다.
uv는 명령어가 두 갈래로 나뉜다.
| 명령 | 하는 일 |
|---|---|
프로젝트 인터페이스uv add, uv remove, uv run, uv sync | pyproject.toml을 읽고 고쳐 쓴다 |
pip 인터페이스uv pip install, uv pip list | 활성화된 환경에 그냥 설치한다 |
uv add는 후자가 아니라 전자다. 단순히 "패키지를 설치해줘"가 아니라 "이 프로젝트의 의존성 목록에 이 패키지를 추가하고, 잠금 파일을 갱신하고, 환경을 동기화해줘"라는 뜻이다.
그러니 의존성을 적어둘 pyproject.toml이 없으면 uv 입장에서는 할 말이 없다. 어디에 적으라는 건지 모르니까.
No pyproject.toml found in current directory or any parent directory
뒷부분이 핵심이다. uv는 현재 디렉터리만 보고 포기하지 않는다. 루트에 닿을 때까지 상위 디렉터리를 거슬러 올라가며 pyproject.toml을 찾는다. 모노레포나 워크스페이스 하위에서 명령을 실행해도 동작하게 하기 위한 설계다.
/ ← pyproject.toml 없음
└── Users/joon/ ← pyproject.toml 없음
└── ADA_Challenge/ ← pyproject.toml 없음
└── bamti-backend/ ← 여기서 시작, 없음
전부 훑고도 못 찾았다는 얘기다. 즉 "오타가 났다"가 아니라 "아직 프로젝트가 아니다"라는 신호다.
uv init --name bamti-backend --python 3.13
# Initialized project `bamti-backend`
uv add "fastapi[standard]"
이제는 조용히 잘 된다. fastapi, uvicorn, starlette, pydantic, typer, watchfiles까지 30여 개 패키지가 한 번에 들어온다. ([standard]는 개발 서버와 CLI에 필요한 것들을 묶어놓은 extras다.)
main.py를 만들고,
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
띄운다.
uv run fastapi dev main.py
⚡️ Starting FastAPI in development mode
🐍 Using import string: main:app
🌐 Server started at http://127.0.0.1:8000
Documentation at http://127.0.0.1:8000/docs
curl http://127.0.0.1:8000/ → {"Hello":"World"}. 끝.
| 파일 | 역할 |
|---|---|
pyproject.toml | 의존성 목록. uv add가 고쳐 쓰는 대상 |
uv.lock | 정확한 버전 잠금. 커밋할 것 |
.python-version | 파이썬 버전 고정 (3.13) |
.venv/ | 가상환경. uv가 알아서 만들고 관리 |
.gitignore, README.md, src/ | 기본 스캐폴딩 |
.git/ | git 저장소도 같이 초기화된다 |
시스템 파이썬은 3.14.7이었지만 --python 3.13으로 고정하자 uv가 3.13을 알아서 받아왔다. 이게 .python-version에 박혀서 협업자도 같은 버전을 쓰게 된다.
uv run을 앞에 붙이면 uv가 알아서 프로젝트 환경에서 실행한다. 심지어 실행 직전에 uv.lock과 환경이 어긋났는지 확인하고 동기화까지 해준다.
uv run fastapi dev main.py # activate 없이 바로
uv run python -c "import fastapi; print(fastapi.__version__)"
activate를 깜빡해서 전역 파이썬에 설치하는 사고가 구조적으로 사라진다.
정리하다 보니 디렉터리에 uv라는 이름의 0바이트 파일이 하나 있었다. 아마 uv 뭐시기를 치다가 리다이렉션 오타(>)를 냈던 것 같다. 눈에 안 띄는 쓰레기 파일이니 지우고 넘어갔다.
uv add가 pyproject.toml을 못 찾겠다고 하면,
uv inituv venv 후 uv pip installuv add --script script.py fastapi (PEP 723 인라인 메타데이터)pyproject.toml만 딱 필요하다면 → uv init --bare튜토리얼이 uv init으로 시작하는 데는 이유가 있었다.
환경: uv 0.12.7 / macOS(Apple Silicon) / Python 3.13 / FastAPI 0.141.1