현대 웹 개발에서 효율성과 성능은 매우 중요합니다. 특히 백엔드 개발에서 이러한 요소들은 더욱 중요해지고 있습니다. FastAPI는 이러한 요구를 충족시키기 위해 설계된 Python 웹 프레임워크입니다. FastAPI는 비동기 프로그래밍을 지원하며, 빠른 API 개발을 위해 다양한 기능을 제공합니다. 이 글에서는 FastAPI를 사용하여 서버를 구축하고, Uvicorn을 사용하여 이를 실행하는 방법을 자세히 살펴보겠습니다.
1. FastAPI란?
FastAPI는 Python으로 작성된 최신 웹 프레임워크입니다. 그 주요 특징은 다음과 같습니다:
- 비동기 지원: FastAPI는 비동기 프로그래밍을 지원하여 높은 성능을 구현할 수 있습니다.
- 자동 문서화: FastAPI는 Swagger UI와 Redoc과 같은 자동 문서화 기능을 제공합니다.
- 타입 힌트: Python의 타입 힌트를 기반으로 API의 데이터 모델과 유효성 검사를 자동으로 처리합니다.
- 성능: Starlette와 Pydantic을 기반으로 구축되어 있어 매우 빠른 속도를 자랑합니다.
2. Uvicorn이란?
Uvicorn은 ASGI(Asynchronous Server Gateway Interface) 서버입니다. FastAPI와 같은 비동기 웹 프레임워크를 실행하기 위한 경량 웹 서버로, 다양한 비동기 처리를 지원합니다. FastAPI와 함께 사용할 때, 다음과 같은 장점이 있습니다:
- 높은 성능: Uvicorn은 비동기 IO를 활용하여 요청을 처리할 수 있으므로 매우 빠릅니다.
- 간단한 사용법: 명령어로 쉽게 서버를 실행할 수 있습니다.
- 적은 자원 소모: 가벼운 서버이기 때문에 소모하는 자원이 적습니다.
3. FastAPI 설치하기
FastAPI를 설치하기 위해서는 Python이 설치되어 있어야 합니다. Python이 설치된 후, 다음의 명령어를 사용하여 FastAPI와 Uvicorn을 설치할 수 있습니다:
pip install fastapi uvicorn
4. FastAPI 기본 설정
설치가 완료되면, FastAPI를 이용하여 간단한 API 서버를 구축해보겠습니다. 아래는 기본적인 FastAPI 설정을 보여주는 코드 예제입니다:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, FastAPI!"}
5. Uvicorn으로 FastAPI 서버 실행하기
FastAPI 애플리케이션을 실행하기 위해 Uvicorn을 사용할 수 있습니다. 위에서 작성한 코드를 main.py
라는 파일에 저장한 후, 다음의 명령어로 Uvicorn 서버를 실행할 수 있습니다:
uvicorn main:app --reload
여기서 main
은 파일 이름이고, app
는 FastAPI 인스턴스의 이름입니다. --reload
플래그는 코드 변경 시 자동으로 서버를 다시 시작해줍니다.
5.1 실행 결과 확인하기
서버가 성공적으로 실행되면, 브라우저를 열고 http://127.0.0.1:8000
에 접속하여 결과를 확인할 수 있습니다. JSON 형태로 {“message”: “Hello, FastAPI!”}가 출력됩니다. 또한, Swagger UI를 통해 API 문서에 접근할 수 있습니다. 주소는 http://127.0.0.1:8000/docs
입니다.
6. FastAPI의 경로 매개변수
FastAPI는 경로 매개변수를 통해 URL의 일부를 변수로 사용할 수 있게 해줍니다. 예를 들어 사용자의 이름을 포함하는 간단한 API를 작성해보겠습니다:
@app.get("/users/{user_id}")
async def read_user(user_id: int):
return {"user_id": user_id}
위의 예제에서 user_id
는 URL 경로에서 동적으로 추출되는 값입니다. 서버를 실행한 후 http://127.0.0.1:8000/users/1
와 같은 경로에 접속하면 {"user_id": 1}
와 같은 결과를 확인할 수 있습니다.
7. FastAPI의 쿼리 매개변수
쿼리 매개변수 역시 FastAPI에서 쉽게 처리할 수 있습니다. 다음은 쿼리 매개변수를 사용하는 예제입니다:
@app.get("/items/")
async def read_item(q: str = None):
return {"query": q}
이 API에 접속하면서 쿼리 매개변수를 전달하면, 예를 들어 http://127.0.0.1:8000/items/?q=test
로 접근 시 {"query": "test"}
라는 결과를 반환합니다.
8. FastAPI에서 POST 요청 처리하기
FastAPI는 POST 요청을 통해 클라이언트로부터 데이터를 받을 수 있습니다. 아래는 JSON 형식의 요청 데이터를 처리하는 예제입니다:
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.post("/items/")
async def create_item(item: Item):
return item
위와 같은 방식으로 POST 요청을 보내면, 전송된 데이터를 그대로 반환하는 API를 만들 수 있습니다. 예를 들어 요청을 보내는 방법은 다음과 같습니다:
import requests
response = requests.post("http://127.0.0.1:8000/items/", json={"name": "test", "price": 42.0})
print(response.json())
9. FastAPI와 데이터베이스 연동
FastAPI는 SQLAlchemy와 같은 ORM(Object Relational Mapping) 라이브러리와 함께 사용할 수 있습니다. 데이터베이스와의 연동을 통해 실제 데이터를 저장하고 불러오는 작업을 수행할 수 있습니다.
다음은 간단한 SQLAlchemy와 FastAPI를 연동한 코드 예제입니다:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
Base.metadata.create_all(bind=engine)
위의 코드는 SQLite 데이터베이스를 생성하고 users
테이블을 설정하는 작업을 수행합니다. FastAPI와 함께 데이터를 입력하고 조회하는 API를 작성할 수 있습니다.
10. 비동기 처리
FastAPI는 비동기 처리를 지원하므로, 예를 들어 여러 API를 동시에 호출해야 할 때 유용합니다. 비동기 함수를 사용하여 다음과 같이 작성할 수 있습니다:
import asyncio
async def fetch_data(url):
async with httpx.AsyncClient() as client:
response = await client.get(url)
return response.json()
@app.get("/data/")
async def get_data():
url = "http://api.example.com/data"
data = await fetch_data(url)
return data
11. FastAPI의 업데이트 및 삭제
FastAPI에서는 PUT 메서드를 사용하여 리소스를 업데이트하고, DELETE 메서드를 사용하여 리소스를 삭제할 수 있습니다. 다음은 업데이트와 삭제를 수행하는 간단한 예제입니다.
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
# 업데이트 로직
return {"item_id": item_id, **item.dict()}
@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
# 삭제 로직
return {"message": "Item has been deleted", "item_id": item_id}
12. FastAPI의 미들웨어
FastAPI는 미들웨어를 통해 요청과 응답을 가로채어 핸들링할 수 있는 기능을 제공합니다. 예를 들어, 모든 요청에 대해 로그를 기록하는 미들웨어를 작성할 수 있습니다:
from starlette.middleware.base import BaseHTTPMiddleware
class LogMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
print(f"Request: {request.url}, Response Status: {response.status_code}")
return response
app.add_middleware(LogMiddleware)
13. FastAPI와 보안
FastAPI는 OAuth2와 같은 인증 방법을 지원합니다. 이를 통해 안전하게 API를 보호하고 접근 제어를 할 수 있습니다. 아래는 간단한 보안 개요입니다:
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# 검증 로직
return {"access_token": form_data.username, "token_type": "bearer"}
14. 마치며
이 글에서는 FastAPI를 사용하여 백엔드 서버를 개발하고 Uvicorn을 통해 이를 실행하는 방법에 대해 살펴보았습니다. 비동기 처리, 데이터베이스 연동, RESTful API 설계 등 다양한 기능을 활용하여 강력한 웹 서버를 구축할 수 있음을 확인했습니다. FastAPI는 그 자체로도 훌륭하지만, 다양한 라이브러리와 함께 사용하여 진정한 강력함을 발휘합니다. 각자의 필요에 따라 FastAPI의 기능을 확장하여 자신만의 API 서버를 만들어 보세요!
부록: 관련 라이브러리 및 자료
FastAPI와 함께 잘 사용되는 여러 라이브러리와 자료를 소개합니다: