[FastAPI 1일차] 개념, Path Parameter, Query Parameter

이번 포스트에서는

FastAPI의 개념부터 Path Parameter와 Query Parameter를 이용해 간단한 API를 만드는 흐름까지 다뤄보았습니다.

 

FastAPI란?

FastAPI는 Python 기반 고성능 웹 API 프레임워크입니다.

가장 큰 장점은 이름처럼 '빠르다(Fast)'는 것과, 코드를 작성할 때 변수의 타입을 미리 정해두는 타입 힌트 기능을 사용하면 데이터 검증과 문서 작성이 자동으로 된다는 점입니다.

 

FastAPI는 파이썬의 타입 힌트를 적극적으로 활용합니다. 예를 들어, user_id: int라고 함수에 지정하면, 사용자가 user_id 자리에 숫자가 아닌 문자('abc')를 보내면 FastAPI가 자동으로 에러를 처리해 줍니다. 개발자가 직접 검증 코드를 짤 필요가 없어서 편리합니다.

 

주요 특징

  • 빠른 성능: Starlette 기반입니다.
  • 타입 힌트 기반 자동 검증: 타입 힌트로 입력값 검증이 자동으로 동작합니다.
  • 자동 API 문서: Swagger 문서가 자동으로 생성됩니다.

주요 용도

  • 백엔드 API 서버 구축
  • AI 또는 ML 모델을 API로 서빙할 때 사용

 

Django vs Flask vs FastAPI:

  • Django: 기능이 너무 많아서 배우기 어렵고(러닝 커브가 높음), 큰 프로젝트에 적합함
  • Flask: 아주 가벼워서 작은 프로젝트에 좋음. 하지만 기능이 적어 필요한 것을 직접 만들어야 함.
  • FastAPI: 빠르고, API 서버와 AI 모델 서빙에 특화되어 있어 요즘 많이 사용됨.

개발 환경 준비

Python 버전

Python **3.10+** 사용을 권장합니다.

 

가상환경 생성

python3.13 -m venv .venv
 
 

가상환경 활성화

macOS

source .venv/bin/activate
 

Windows

.venv\Scripts\activate
 

FastAPI 설치

pip install "fastapi[standard]"

 

 

FastAPI 기본 구조

FastAPI는 FastAPI()로 앱을 만들고 데코레이터로 라우트를 등록합니다.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
	return {"message": "Hello FastAPI"}

 

 

 

기본 구조의 이해: FastAPI 서버를 시작하는 가장 기본적인 형태입니다.

  • from fastapi import FastAPI: FastAPI 기능을 가져옵니다.
  • app = FastAPI(): 서버 애플리케이션 객체를 만듭니다.
  • @app.get("/"): / 경로에 GET 요청이 들어오면 바로 아래에 있는 함수(root)를 실행하라는 뜻입니다.
  • return {"message": "Hello FastAPI"}: 함수가 실행된 후, 이 딕셔너리(key: value 형태)를 JSON 형태의 HTTP 응답으로 클라이언트에게 돌려줍니다.

 

💡FastAPI 서버 실행 시 지피티 등 다양하게 이용하다보면 다음과 같은 다양한 명령을 보게 됩니다.

fastapi dev 000:app
fastapi dev -e 000:app
fastapi dev 000.py

 

 

대체 이게 무슨 차이가 있는 애들일까요? 아래에서 알아보았습니다.

 

FastAPI 실행의 기본 원리

FastAPI 서버 실행의 핵심은 Python 파일 안에 있는 app 객체를 서버에 전달하는 것입니다.

# 000.py 
from fastapi import FastAPI 

app = FastAPI()

 

이때 FastAPI는 다음 형식을 기대합니다.

파일이름 : 앱객체이름
 
 

정석적인 실행 방식은 다음과 같습니다.

fastapi dev 000:app

000.py 파일 안에 정의된 app 객체를 개발 서버로 실행하라는 의미

 

이 명령은 FastAPI 개발 서버를 실행하며, 코드 변경 시 자동 재시작 기능이 포함된 기본 개발 모드입니다.

 

-e 옵션의 의미

-e 옵션은 FastAPI의 환경 변수 로딩 및 개발 편의 모드를 활성화하는 옵션입니다.

fastapi dev -e 000:app
 

주요 기능

  • 코드 변경 사항을 즉시 반영하는 안정적인 자동 리로드
  • 개발 환경에 최적화된 실행
  • (선택적) .env 파일이 있을 경우 자동 로딩

000.py 방식이 동작하는 이유

fastapi dev 000.py

이는 FastAPI CLI의 편의 기능 때문입니다.
FastAPI는 내부적으로 다음과 같이 추정하여 실행합니다.

000.py → 000:app
 

즉 000.py 방식은 축약형, 000:app 방식은 정석 문법입니다.

 

가끔 실습을 진행하다보면 :app 은 안 되는데 .py는 실행이 될 때가 있습니다.

이 현상은 FastAPI CLI의 동작 방식 차이 때문입니다.

 

 .py 방식은 FastAPI가 "추측"해 주는 모드입니다

.py 로 실행되면 FastAPI는 다음 과정을 자동으로 수행합니다.

  1. 000.py 파일을 찾습니다.
  2. 파일을 import 합니다.
  3. 그 안에서 FastAPI 객체(app)를 자동으로 탐색합니다.
  4. 발견되면 해당 객체를 서버로 실행합니다.

.py 방식은 FastAPI가 내부에서 "이 파일 안에 app이 있겠지?" 하고 알아서 찾아 주는 모드입니다.

 

 

그래서 경로나 구조가 조금 틀려도 실행이 되는 경우가 많습니다.

 

그에 반해  :app 방식은 정석 문법이며 추측이 전혀 없습니다

이 방식은 FastAPI에게 정확히 <"000" 이라는 모듈 안에서 "app" 이라는 객체를 정확히 찾아 실행하라>  라고 요구합니다.

 

 

 

따라서 다음 중 하나라도 어긋나면 바로 실패합니다.

실패 원인  설명
파일 위치 현재 디렉토리에 000.py 가 없는 경우
실행 위치 터미널 위치가 파일이 있는 폴더가 아닌 경우
패키지 구조 폴더 구조로 인해 import 경로가 달라진 경우
객체 이름 FastAPI 객체 이름이 app 이 아닌 경우
모듈 충돌 동일한 이름의 폴더 또는 모듈이 존재하는 경우

실습을 하다보면 실습 파일이 계속 늘어나고, 파일명을 변경한다던가 하는 이유로

:app 방식은 실패할 수도 있고 이런 차이가 있다는 것을 알 수 있었습니다.🍀

 

아래와 같이 표로 간략하게 정리해봤습니다.

 

실행 명령 의미
fastapi dev 000:app FastAPI 정석 실행 방식
fastapi dev -e 000:app 정석 방식 + 환경변수 자동 로딩
fastapi dev 000.py CLI 편의 기능으로 동작하는 축약형

 


 

데코레이터 개념과 FastAPI에서의 역할

데코레이터란

함수를 감싸서 원래 함수의 동작 전후에 공통 로직을 추가하는 문법입니다.
중복 코드를 줄이고 선언적으로 기능을 표현하는 데 사용합니다.

예시는 다음과 같습니다.

def my_decorator(func): 
	def wrapper(*args, **kwargs): 
    	print("before") 
        result = func(*args, **kwargs) 
        print("after") 
        return result 
	return wrapper 
    
@my_decorator 
def hello(): 
	print("hello")
 

 

FastAPI에서 데코레이터 역할

FastAPI의 @app.get() 같은 데코레이터는 함수를 HTTP 엔드포인트로 등록합니다.
예를 들어 GET / 요청이 오면 root() 함수가 실행됩니다.

@app.get("/") 
def root(): 
	return {"message": "Hello FastAPI"}
 

 

자동 API 문서

FastAPI는 API 문서를 자동 생성합니다.

  • Swagger UI: http://localhost:8000/docs
  • Redoc: http://localhost:8000/redoc

 

Path Parameter

Path Parameter는 URL 경로 자체에 포함되는 값입니다.
주로 리소스를 식별할 때 사용합니다.

 

예시는 다음과 같습니다.

  • /users/3
  • /items/abc

 

{user_id} 를 경로에서 추출해 함수 인자로 받습니다.
user_id: int 같은 타입 힌트로 자동 검증이 동작합니다.

@app.get("/users/{user_id}") 
def get_user(user_id: int): 
	return {"user_id": user_id}
 

/users/abc처럼 타입이 맞지 않으면 422 에러로 검증 실패가 자동 처리됩니다.

Swagger 문서에도 타입 정보가 자동 반영됩니다.

 

 

또 Path 값에 조건과 설명을 붙일 수 있는데요.

  • ge=1은 1 이상만 허용합니다.
  • description은 Swagger에 설명을 표시합니다.
  • ...는 필수값을 의미합니다.
from fastapi import Path 

@app.get("/users/{user_id}") 
def get_user(user_id: int = Path(..., ge=1, description="유저 ID (1 이상)")): 
	return {"user_id": user_id}

 

실습을 해보겠습니다!

 

요구사항

  • GET /items/{item_id}
  • 예시 입력: /items/10
  • 예시 응답: {"item_id": 10}

정답 예시

@app.get("/items/{item_id}") 
def get_item(item_id: int): 
	return {"item_id": item_id}
 

 

Query Parameter

Query Parameter는 URL 뒤에 ?key=value 형태로 붙는 값입니다.
필터링, 정렬, 페이지네이션에 자주 사용합니다.

 

예시
/search?q=fastapi&limit=10

  • q는 필수입니다. 기본값이 없습니다.
  • limit은 선택입니다. 기본값이 10입니다.
@app.get("/search") 
def search(q: str, limit: int = 10): 
	return {"q": q, "limit": limit}

 

 

Query에는 조건을 걸 수 있습니다.

  • min_length, max_length는 문자열 길이 제한입니다.
  • ge, le는 숫자 범위 제한입니다.
from fastapi import Query 

@app.get("/search") 

def search( 
	q: str = Query(..., min_length=2, max_length=30), 
    limit: int = Query(10, ge=1, le=100), 
): 
    
    return {"q": q, "limit": limit}

 

Path + Query 같이 쓰기

원칙은 다음과 같습니다.

  • 리소스 식별은 Path입니다.
  • 옵션은 Query입니다.
  • URL 경로 상에 존재하면 Path입니다.
  • 존재하지 않으면 Query입니다.

예시로 /users/3/posts?limit=5가 제시 되었을 때 아래와 같이 쓸 수 있습니다.

@app.get("/users/{user_id}/posts") 

def list_posts(user_id: int, limit: int = 10): 
    return {"user_id": user_id, "limit": limit}

 

이것도 실습을 해보겠습니다.

 

요구사항

  • GET /products/search?q=apple&limit=5
  • 응답: {"q": "apple", "limit": 5}

정답 예시

@app.get("/products/search") 
def product_search(q: str, limit: int = 10): 
	return {"q": q, "limit": limit}