본문 바로가기
Server

Uvicorn 서버 2회차 : 첫 실행 마스터, uvicorn app:app 문법 완전 이해

by 마틴블레이크 2025. 12. 22.
반응형

Uvicorn 서버 2회차 : 첫 실행 마스터, uvicorn app:app 문법 완전 이해

한눈에 보는 요약

Uvicorn은 FastAPI 같은 ASGI 웹 프레임워크를 실행하는 초고속 파이썬 서버입니다. 이 글에서는 Uvicorn을 “처음” 실행하는 분도 이해할 수 있도록, uvicorn main:app에서 mainapp이 각각 무엇을 의미하는지, 그리고 --host, --port 옵션을 어떻게 써야 하는지 아주 쉽게 설명합니다.

또한 프로젝트 구조를 어떻게 잡아야 import 경로 실수를 줄일 수 있는지도 함께 살펴보고, 마지막에는 바로 복사해 쓸 수 있는 실행 명령어 템플릿(내 PC용 / 외부 접속용) 2가지를 제공해 드립니다.

목차


1. 오늘의 학습 목표 정리

  • module:object 표기법 이해uvicorn main:app에서 mainapp이 각각 어떤 의미인지 정확히 이해합니다.
  • 프로젝트 구조에서 import 경로 실수 줄이기app/main.py 같은 구조에서 app.main:app이 왜 맞는지, 어떤 경우에 오류가 나는지 배웁니다.
  • --host, --port 옵션 이해 → “내 PC에서만 접속”과 “외부(다른 PC·모바일)에서도 접속”을 어떻게 나눌지 이해합니다.
  • 브라우저 / curl로 실제 호출 확인 → 서버 실행 뒤 브라우저와 터미널(curl)에서 응답을 직접 확인하는 방법을 익힙니다.

2. app.py / main.py: 진입점 파일이란?

웹 서버가 실행되려면 “어디서부터 코드를 시작할지” 정해줘야 합니다. 이 시작점이 되는 파일을 흔히 진입점(entrypoint)이라고 부릅니다. FastAPI + Uvicorn 프로젝트에서는 보통 다음 두 이름 중 하나를 많이 사용합니다.

  • main.py
  • app.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!"}

여기서 중요한 것은 두 가지입니다.

  1. main.py라는 파일 이름 → 나중에 uvicorn main:appmain에 해당
  2. app이라는 변수 이름 → uvicorn main:appapp에 해당

즉, 진입점 파일과 그 안의 애플리케이션 객체 이름은 Uvicorn 실행 명령에서 그대로 사용되므로, 처음부터 일관된 이름을 정해 두는 것이 매우 중요합니다.


3. module:object 표기법 완전 이해

이제 Uvicorn 실행 명령의 핵심인 module:object 표기법을 알아보겠습니다. 명령 예시는 다음과 같습니다.

uvicorn main:app

이 한 줄을 파이썬 코드 관점에서 풀어 쓰면 이렇게 이해하시면 됩니다.

  • mainmain.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.mainapp/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.py vs mian.py)
  • 모듈 경로가 올바른지? (app.main vs apps.main)
  • 애플리케이션 객체 이름이 정확한지? (app vs application)
  • 현재 터미널 위치가 프로젝트 루트인지?

 

반응형