
Uvicorn 서버 2회차 : 첫 실행 마스터, uvicorn app:app 문법 완전 이해
한눈에 보는 요약
Uvicorn은 FastAPI 같은 ASGI 웹 프레임워크를 실행하는 초고속 파이썬 서버입니다. 이 글에서는 Uvicorn을 “처음” 실행하는 분도 이해할 수 있도록, uvicorn main:app에서 main과 app이 각각 무엇을 의미하는지, 그리고 --host, --port 옵션을 어떻게 써야 하는지 아주 쉽게 설명합니다.
또한 프로젝트 구조를 어떻게 잡아야 import 경로 실수를 줄일 수 있는지도 함께 살펴보고, 마지막에는 바로 복사해 쓸 수 있는 실행 명령어 템플릿(내 PC용 / 외부 접속용) 2가지를 제공해 드립니다.
목차
- 1. 오늘의 학습 목표 정리
- 2. app.py / main.py: 진입점 파일이란?
- 3.
module:object표기법 완전 이해 (main:app, app.main:app) - 4.
--host/--port: 로컬 접속 vs 외부 접속 - 5. 실습:
uvicorn main:app --host 0.0.0.0 --port 8000실행하기 - 6. 실행 명령어 템플릿 2개 (내 PC용 / 외부 접속용)
- 7. 프로젝트 구조 & 자주 하는 실수 정리
- 8. 블로그 최적화 정보
1. 오늘의 학습 목표 정리
module:object표기법 이해 →uvicorn main:app에서main과app이 각각 어떤 의미인지 정확히 이해합니다.- 프로젝트 구조에서 import 경로 실수 줄이기 →
app/main.py같은 구조에서app.main:app이 왜 맞는지, 어떤 경우에 오류가 나는지 배웁니다. --host,--port옵션 이해 → “내 PC에서만 접속”과 “외부(다른 PC·모바일)에서도 접속”을 어떻게 나눌지 이해합니다.- 브라우저 / curl로 실제 호출 확인 → 서버 실행 뒤 브라우저와 터미널(curl)에서 응답을 직접 확인하는 방법을 익힙니다.
2. app.py / main.py: 진입점 파일이란?
웹 서버가 실행되려면 “어디서부터 코드를 시작할지” 정해줘야 합니다. 이 시작점이 되는 파일을 흔히 진입점(entrypoint)이라고 부릅니다. FastAPI + Uvicorn 프로젝트에서는 보통 다음 두 이름 중 하나를 많이 사용합니다.
main.pyapp.py
예를 들어, 아래처럼 가장 단순한 프로젝트 구조를 가정해 보겠습니다.
myproject/
└── main.py
이때 main.py 파일 안에서는 보통 아래와 같이 FastAPI 인스턴스를 만들고, 변수 이름을 app으로 둡니다.
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello, Uvicorn!"}
여기서 중요한 것은 두 가지입니다.
main.py라는 파일 이름 → 나중에uvicorn main:app의 main에 해당app이라는 변수 이름 →uvicorn main:app의 app에 해당
즉, 진입점 파일과 그 안의 애플리케이션 객체 이름은 Uvicorn 실행 명령에서 그대로 사용되므로, 처음부터 일관된 이름을 정해 두는 것이 매우 중요합니다.
3. module:object 표기법 완전 이해
이제 Uvicorn 실행 명령의 핵심인 module:object 표기법을 알아보겠습니다. 명령 예시는 다음과 같습니다.
uvicorn main:app
이 한 줄을 파이썬 코드 관점에서 풀어 쓰면 이렇게 이해하시면 됩니다.
main→main.py모듈을 의미 (파이썬 코드로 쓰면import main또는from main import app과 같은 느낌)app→ 그 모듈 안에 있는app이라는 이름의 객체 (여기서는app = FastAPI()로 만든 FastAPI 인스턴스)
조금 더 복잡한 구조를 예로 들어보겠습니다.
myproject/
└── app/
├── __init__.py
└── main.py
이때 app/main.py 안에 다음과 같이 코드를 작성했다고 가정해 보겠습니다.
# app/main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello from package!"}
이 프로젝트 루트(myproject/)에서 실행해야 할 명령은 다음과 같습니다.
uvicorn app.main:app
여기서의 의미는 다음과 같습니다.
app.main→app/main.py모듈app→ 해당 모듈 안의app객체
즉, 모듈경로:객체이름이라는 패턴만 기억하면, 어떤 구조에서도 “어디 파일의 어떤 객체를 실행하는지”를 눈으로 바로 해석할 수 있게 됩니다.
자주 하는 실수 예시
uvicorn app처럼:app을 빼먹는 경우 → “형식은module:object가 되어야 한다”는 오류가 남.uvicorn main:처럼 콜론 뒤 이름을 빼먹는 경우 → 마찬가지로 잘못된 APP 문자열 형식 오류.- 실제 파일은
main.py인데, 명령에서mian:app처럼 오타를 내는 경우 → 해당 모듈을 찾을 수 없다는 오류.
4. --host / --port: 로컬 접속 vs 외부 접속
다음으로 많이 헷갈리는 부분이 --host와 --port입니다. 간단히 말하면:
--host: “어디에서 들어오는 연결을 받을지” (IP 주소)--port: “어떤 포트 번호에서 들을지”
대표적으로 많이 쓰는 값은 다음 두 가지입니다.
| 환경 | host 값 | 의미 | 예시 URL |
|---|---|---|---|
| 로컬 개발 | 127.0.0.1 또는 생략 |
내 컴퓨터에서만 접속 가능 | http://127.0.0.1:8000 |
| 외부 접속 허용 | 0.0.0.0 |
모든 네트워크 인터페이스에서 접속 허용 | http://서버IP:8000 |
포트 번호(--port)는 기본적으로 8000을 많이 사용하지만, 이미 다른 프로그램이 쓰고 있다면 8001, 8080 등 다른 번호를 사용하면 됩니다. 중요한 것은 한 포트에는 한 프로세스만 바인딩된다는 점입니다.
5. 실습: uvicorn main:app --host 0.0.0.0 --port 8000 실행하기
이제 실제로 한 번 실행해 보겠습니다. 단계별로 따라와 주세요.
1) 프로젝트 폴더 만들기
mkdir uvicorn-example
cd uvicorn-example
2) 가상환경 생성 및 라이브러리 설치
python -m venv venv
# Windows
# venv\Scripts\activate
# macOS / Linux
source venv/bin/activate
pip install fastapi uvicorn
3) main.py 파일 작성
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello, Uvicorn!"}
4) 서버 실행 (외부 접속 허용)
이제 아래 명령을 실행합니다.
uvicorn main:app --host 0.0.0.0 --port 8000
터미널에 “Uvicorn running on http://0.0.0.0:8000” 비슷한 로그가 보이면 서버가 정상 실행된 것입니다. 이제 두 가지 방식으로 응답을 확인해 봅니다.
5) 브라우저에서 확인
- 같은 PC라면 주소창에
http://127.0.0.1:8000입력 - 다른 PC·모바일에서 접속하려면 → 서버의 실제 IP 주소를 사용 예:
http://192.168.0.10:8000,http://203.xxx.xxx.xxx:8000
정상 동작한다면 아래와 비슷한 JSON 응답이 보입니다.
{"message": "Hello, Uvicorn!"}
6) curl로 확인
터미널에서 다음 명령을 실행해 봅니다.
curl http://127.0.0.1:8000/
브라우저에서 본 것과 동일한 JSON 응답이 출력되면 서버가 잘 동작하고 있다는 의미입니다. 브라우저와 curl 두 가지 방식으로 테스트하는 습관을 들이면, 나중에 문제 발생 시 “네트워크 문제인지, 서버 문제인지, 브라우저 문제인지”를 분리해서 추적하는 데 큰 도움이 됩니다.
6. 실행 명령어 템플릿 2개 (내 PC용 / 외부 접속용)
마지막으로, 바로 복사해서 사용할 수 있는 실행 명령어 템플릿을 정리하겠습니다. 자신의 프로젝트 파일 이름과 패키지 구조에 맞게 main 또는 app.main 부분만 바꿔서 사용하시면 됩니다.
| 용도 | 예시 명령어 | 설명 |
|---|---|---|
| 내 PC 개발용 | uvicorn main:app --reload --host 127.0.0.1 --port 8000 |
코드 변경 시 자동 재시작(--reload)을 켜고, 내 컴퓨터에서만 접속 가능하도록 실행합니다. 가장 기본적인 개발용 설정입니다. |
| 외부 접속 테스트 / 서버용 | uvicorn main:app --host 0.0.0.0 --port 8000 |
모든 네트워크 인터페이스에서 접속을 허용합니다. 팀원이나 다른 기기에서 서버에 접속할 때 사용하는 가장 기본적인 설정입니다. |
패키지 구조를 사용한다면, 위 템플릿에서 main:app 대신 app.main:app처럼 바꾸어 사용하면 됩니다.
7. 프로젝트 구조 & 자주 하는 실수 정리
1) 프로젝트 루트는 항상 일정하게
Uvicorn을 실행할 때는 항상 “프로젝트 루트”를 어디로 볼지 정하고, 항상 그 위치에서만 명령을 실행하는 습관을 들이는 것이 좋습니다.
- 예:
backend/를 루트로 정했다면, 항상cd backend후에uvicorn app.main:app실행
2) 패키지 디렉터리에는 __init__.py 추가
app/main.py 구조를 쓰고 싶다면, app 디렉터리 안에 반드시 __init__.py 파일을 넣어 주세요. 그래야 app이 파이썬 입장에서 “패키지”로 인식되고, app.main이라는 모듈 경로를 사용할 수 있습니다.
3) 앱 객체 이름은 가능하면 통일
FastAPI 인스턴스 이름을 app으로 통일하면 실행 명령도 항상 XXX:app 형태로 일관되게 가져갈 수 있습니다. 혹시 이름을 바꾸고 싶다면, uvicorn main:my_app처럼 콜론 뒤의 이름도 함께 바꿔야 합니다.
4) 에러가 날 때 확인할 것
- 파일 이름이 정확한지? (
main.pyvsmian.py) - 모듈 경로가 올바른지? (
app.mainvsapps.main) - 애플리케이션 객체 이름이 정확한지? (
appvsapplication) - 현재 터미널 위치가 프로젝트 루트인지?
'Server' 카테고리의 다른 글
| Uvicorn 서버 4회차 : 로그를 다루는 법, 문제의 80%는 로그에서 끝난다 (0) | 2025.12.23 |
|---|---|
| Uvicorn 서버 3회차 : 개발 모드의 핵심, reload와 코드 변경 반영 (1) | 2025.12.22 |
| Uvicorn 서버 1회차: Uvicorn이 무엇인지, “서버”와 “앱”의 역할 분리 이해하기 (1) | 2025.12.22 |
| 포트포워딩이란? 공유기 예시로 10분 만에 이해하고, 깊이 있게 공부하기 (0) | 2025.12.21 |
| 우분투 데스크톱에서 서버 구축하기 : 초보자도 따라 하는 단계별 가이드 (0) | 2025.12.21 |