FastAPI 서버개발, 배포 준비

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 빠른 성능과 직관적인 사용성을 제공하여 RESTful API 서버를 구축하는 데 매우 유용합니다. 이 글에서는 FastAPI 서버를 개발하는 방법뿐만 아니라, 배포 준비 과정에 대해서도 상세히 설명하겠습니다.

FastAPI의 주요 특징

  • 빠른 성능: FastAPI는 Starlette와 Pydantic을 기반으로 하여 매우 빠른 성능을 제공합니다.
  • 자동 문서화: Swagger UI와 ReDoc을 통해 API 문서를 자동으로 생성합니다.
  • 비동기 처리 지원: Python의 비동기 프로그래밍을 쉽게 사용할 수 있습니다.
  • 타입 힌트: Python의 타입 힌트를 사용하여 코드의 가독성과 안정성을 높일 수 있습니다.

FastAPI 서버 개발 시작하기

FastAPI를 사용하여 간단한 웹 서버를 구축해보겠습니다. 이 예제에서는 간단한 사용자 등록 API를 만들어 보겠습니다.

1. FastAPI 설치

FastAPI를 설치하려면 pip를 사용합니다. 또한, Uvicorn을 ASGI 서버로 사용해 실행할 수 있습니다.

pip install fastapi uvicorn

2. FastAPI 앱 만들기

FastAPI 앱을 정의하고, 사용자 등록 API를 구현해보겠습니다.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    username: str
    email: str

@app.post("/register/")
async def register_user(user: User):
    return {"message": f"User {user.username} registered successfully!", "email": user.email}

3. 서버 실행하기

Uvicorn을 사용하여 서버를 실행합니다. 아래 명령어를 터미널에 입력하면 서버가 시작됩니다.

uvicorn main:app --reload

위 명령으로 `/register/` 엔드포인트가 활성화되며, 이를 통해 사용자 정보를 POST 방식으로 전송할 수 있습니다.

FastAPI 앱의 구조

FastAPI 앱은 보통 다음과 같은 구조로 구성됩니다:

my_fastapi_app/
|-- main.py
|-- models/
|   |-- __init__.py
|   |-- user.py
|-- routers/
|   |-- __init__.py
|   |-- user.py
|-- utils/
|   |-- __init__.py
|   |-- helpers.py

모듈화된 FastAPI 앱 개발

서버가 커질수록 모듈화된 구조가 중요합니다. 각 노력별로 파일을 나누어 관리하면 유지보수와 코드 가독성을 높일 수 있습니다.

1. 모델 정의하기

모델을 정의하는 `user.py` 파일은 아래와 같습니다:

from pydantic import BaseModel

class User(BaseModel):
    username: str
    email: str

2. 라우터 정의하기

라우터를 정의하는 `routers/user.py` 파일:

from fastapi import APIRouter
from models.user import User

router = APIRouter()

@router.post("/register/")
async def register_user(user: User):
    return {"message": f"User {user.username} registered successfully!", "email": user.email}

3. 메인 앱에 라우터 추가하기

메인 앱 파일인 `main.py`에서 라우터를 포함하는 방법:

from fastapi import FastAPI
from routers import user

app = FastAPI()
app.include_router(user.router)

환경 설정

FastAPI 애플리케이션의 환경 설정을 위해 `dotenv`를 사용하여 환경 변수를 관리하는 것이 좋습니다. 아래와 같이 설정할 수 있습니다.

1. python-dotenv 설치

pip install python-dotenv

2. .env 파일 생성

DATABASE_URL=mysql://user:password@localhost:3306/mydatabase

3. 환경 변수 사용하기

import os
from dotenv import load_dotenv

load_dotenv()
database_url = os.getenv("DATABASE_URL")

FastAPI 배포 준비

FastAPI 서버를 배포하기 위한 방법을 설명합니다. 아래 단계로 진행할 수 있습니다.

1. 배포 환경 선택

FastAPI 애플리케이션은 여러 클라우드 서비스 제공업체에서 배포할 수 있습니다. 예를 들어, AWS, GCP, 또는 DigitalOcean과 같은 서비스에서 VM을 생성하여 배포할 수 있습니다.

2. Gunicorn 설치

FastAPI 애플리케이션을 프로덕션 환경에서 실행하기 위해 Gunicorn을 설치할 수 있습니다.

pip install gunicorn

3. 배포 스크립트 작성

배포 스크립트를 작성하여 서버를 배포할 수 있습니다. 다음의 예시와 같이 `start.sh` 파일을 생성하세요:

#!/bin/bash
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

이 스크립트로 서버를 실행할 수 있습니다.

4. Reverse Proxy 설정 (선택 사항)

NGINX와 같은 Reverse Proxy 서버를 설정하여 FastAPI 서버의 앞단에 두면 보안과 성능을 향상시킬 수 있습니다.

테스트 및 모니터링

코드 배포 후에는 API의 기능이 올바르게 동작하는지 확인하고, 모니터링 도구를 사용하여 성능을 관찰해야 합니다.

1. 테스트 프레임워크 설정

FastAPI는 Pytest와 함께 사용할 수 있습니다. 아래는 간단한 테스트 예제입니다:

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_register_user():
    response = client.post("/register/", json={"username": "testuser", "email": "test@example.com"})
    assert response.status_code == 200
    assert response.json() == {"message": "User testuser registered successfully!", "email": "test@example.com"}

2. 모니터링 도구

서버의 상태와 성능을 모니터링하기 위해 Prometheus와 Grafana를 사용할 수 있습니다.

결론

이 글에서는 FastAPI를 사용한 서버 개발 과정과 배포 준비 방법에 대해 설명했습니다. FastAPI의 강력한 기능과 유연한 구조 덕분에 현업에서 RESTful API를 효과적으로 구축할 수 있습니다. 배포 후에는 성능 모니터링을 통해 안정적인 서비스를 제공하십시오.

참고 자료

FastAPI 서버개발, DB 조작, Done 리소스

현대의 웹 애플리케이션 개발에서는 효율적이고, 반응성이 뛰어난 API 서버가 필수적입니다. FastAPI는 Python으로 작성된 빠르고 현대적인 웹 프레임워크로, 빠른 개발과 높은 성능을 자랑합니다. 이 글에서는 FastAPI를 사용하여 백엔드 서버를 구축하고, 데이터베이스를 조작하며, Done 리소스를 구현하는 방법에 대해 자세히 설명하겠습니다.

1. FastAPI란?

FastAPI는 Pydantic과 Starlette을 기반으로 한 고성능 웹 프레임워크로, Python에서 API를 구축하기 위한 최적의 선택입니다. FastAPI의 주요 특징은 다음과 같습니다:

  • 자동 문서화: OpenAPI 및 Swagger UI를 사용하여 API 문서화를 자동으로 제공합니다.
  • 타입 검사: Python 타입 힌트를 사용하여 코드의 가독성을 높이고 런타임 오류를 줄입니다.
  • 비동기 지원: 비동기 프로그래밍을 지원하여 높은 성능을 발휘합니다.
  • 유연성: RESTful API, GraphQL 등 다양한 API 디자인을 지원합니다.

2. FastAPI 설치하기

FastAPI를 사용하기 위해 먼저 FastAPI와 서버를 구동할 수 있는 Uvicorn을 설치합니다. 아래 명령어를 사용하여 설치할 수 있습니다:

pip install fastapi uvicorn

3. FastAPI 기본 구조

FastAPI 서버의 기본 구조는 다음과 같습니다. 아래 코드는 간단한 “Hello, World!” API를 구현한 예시입니다.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello, World!"}

위의 코드를 main.py라는 파일에 저장한 후, 다음 명령어로 서버를 실행할 수 있습니다:

uvicorn main:app --reload

서버가 실행되면 http://127.0.0.1:8000/로 접속하여 결과를 확인할 수 있습니다.

4. 데이터베이스 연결하기

이제 FastAPI와 데이터베이스를 연결해보겠습니다. 이번 예제에서는 SQLite 데이터베이스를 사용하여 Todo 리스트를 관리할 것입니다. 먼저, SQLAlchemydatabases 패키지를 설치합니다.

pip install sqlalchemy databases

4.1 데이터베이스 모델 정의하기

데이터베이스 모델을 정의하기 위해 SQLAlchemy의 ORM을 사용합니다. 아래는 Todo 모델을 정의하는 예시입니다.

from sqlalchemy import create_engine, Column, Integer, String, Boolean
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 Todo(Base):
    __tablename__ = "todos"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    completed = Column(Boolean, default=False)

4.2 데이터베이스 초기화

데이터베이스를 초기화하기 위해 아래와 같은 코드를 추가합니다.

def init_db():
    Base.metadata.create_all(bind=engine)

init_db()

5. CRUD 엔드포인트 구현하기

이제 Todo 리스트를 관리하기 위한 CRUD(Create, Read, Update, Delete) 엔드포인트를 구현하겠습니다.

5.1 Todo 생성하기

from fastapi import Depends, FastAPI
from sqlalchemy.orm import Session

app = FastAPI()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.post("/todos/", response_model=Todo)
async def create_todo(todo: Todo, db: Session = Depends(get_db)):
    db.add(todo)
    db.commit()
    db.refresh(todo)
    return todo

5.2 Todo 목록 조회하기

@app.get("/todos/", response_model=List[Todo])
async def read_todos(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
    todos = db.query(Todo).offset(skip).limit(limit).all()
    return todos

5.3 Todo 수정하기

@app.put("/todos/{todo_id}", response_model=Todo)
async def update_todo(todo_id: int, todo: Todo, db: Session = Depends(get_db)):
    todo_instance = db.query(Todo).filter(Todo.id == todo_id).first()
    if todo_instance is None:
        raise HTTPException(status_code=404, detail="Todo not found")

    todo_instance.title = todo.title
    todo_instance.completed = todo.completed
    db.commit()
    db.refresh(todo_instance)
    return todo_instance

5.4 Todo 삭제하기

@app.delete("/todos/{todo_id}")
async def delete_todo(todo_id: int, db: Session = Depends(get_db)):
    todo_instance = db.query(Todo).filter(Todo.id == todo_id).first()
    if todo_instance is None:
        raise HTTPException(status_code=404, detail="Todo not found")

    db.delete(todo_instance)
    db.commit()
    return {"detail": "Todo deleted"} 

6. Done 리소스 구현하기

이번에는 완료된 Todo를 관리하는 Done 리소스를 구현해보겠습니다. 아래와 같이 새로운 엔드포인트를 추가합니다.

6.1 Done 목록 조회하기

@app.get("/done/", response_model=List[Todo])
async def read_done_todos(db: Session = Depends(get_db)):
    done_todos = db.query(Todo).filter(Todo.completed == True).all()
    return done_todos

7. 클라이언트 테스트하기

이제 Postman 등의 클라이언트를 사용하여 엔드포인트를 테스트해볼 수 있습니다. 아래는 각 엔드포인트에 대한 간단한 테스트 예시입니다.

  • POST /todos/: 새로운 Todo를 생성합니다.
  • GET /todos/: 모든 Todo 목록을 조회합니다.
  • PUT /todos/{todo_id}: 특정 Todo의 내용을 수정합니다.
  • DELETE /todos/{todo_id}: 특정 Todo를 삭제합니다.
  • GET /done/: 완료된 Todo 목록을 조회합니다.

8. 결론

이 글에서는 FastAPI를 사용하여 기본적인 CRUD API를 구축하고, 데이터베이스를 조작하는 방법에 대해 알아보았습니다. FastAPI는 간결한 문법과 뛰어난 성능으로 인해 현대 웹 애플리케이션 개발에 많은 도움이 됩니다. 더 나아가 부가적인 기능(예: JWT 인증, CORS 처리 등)을 추가하여 강력한 API 서버를 만들 수 있습니다.

FastAPI를 통해 여러분의 프로젝트에 더 많은 기능과 서비스를 추가해 보세요. Happy coding!

FastAPI 서버개발, 비동기 대응 CRUDs

최근 몇 년간 FastAPI는 Python에서 비동기 웹 프레임워크로 많은 인기를 얻고 있습니다. FastAPI는 비동기 프로그래밍의 장점을 제공하며, RESTful API를 쉽게 만들 수 있는 강력한 도구입니다. 이 글에서는 FastAPI를 사용하여 비동기적으로 CRUD(생성, 읽기, 수정, 삭제) 작업을 수행하는 방법에 대해 자세히 설명하겠습니다.

1. FastAPI란?

FastAPI는 Python으로 구축된 현대적인 웹 프레임워크로, 고성능 비동기 웹 API를 만드는 데 중점을 두고 설계되었습니다. 주요 특징으로는 다음과 같습니다:

  • 빠른 성능: Starlette와 Pydantic을 기반으로 하므로 속도가 매우 빠릅니다.
  • 자동 문서화: Swagger UI 및 ReDoc과 같은 자동화된 API 문서를 제공합니다.
  • 타입 힌트 지원: Python 타입 힌트를 사용하여 코드의 가독성을 높이고 오류를 줄일 수 있습니다.

2. 환경 설정

FastAPI를 시작하기 위해서는 Python과 pip(패키지 관리자)가 설치되어 있어야 합니다. 아래의 명령어로 FastAPI와 Uvicorn(ASGI 서버)를 설치할 수 있습니다:

pip install fastapi uvicorn

2.1. 프로젝트 구조 설정

간단한 프로젝트 구조를 설정합니다:


my_fastapi_app/
│
├── main.py        # FastAPI 애플리케이션
└── models.py      # Pydantic 모델

3. 기본 CRUD API 구현

이제 기본적인 CRUD 작업을 구현해보겠습니다. 우리는 사용할 데이터 모델을 정의하고, 이를 기반으로 CRUD 엔드포인트를 만들어 보겠습니다.

3.1. 모델 정의

우선 models.py 파일에 Pydantic 모델을 정의합니다:


from pydantic import BaseModel
from typing import Optional

class Item(BaseModel):
    id: int
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None

3.2. CRUD 작업 구현

main.py 파일에 CRUD 작업을 구현합니다:


from fastapi import FastAPI, HTTPException
from typing import List
from models import Item

app = FastAPI()

# 메모리에 데이터를 저장하기 위한 리스트
fake_items_db = []

@app.post("/items/", response_model=Item)
async def create_item(item: Item):
    fake_items_db.append(item)
    return item

@app.get("/items/", response_model=List[Item])
async def read_items():
    return fake_items_db

@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int):
    item = next((item for item in fake_items_db if item.id == item_id), None)
    if item is None:
        raise HTTPException(status_code=404, detail="Item not found")
    return item

@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: int, updated_item: Item):
    for index, item in enumerate(fake_items_db):
        if item.id == item_id:
            fake_items_db[index] = updated_item
            return updated_item
    raise HTTPException(status_code=404, detail="Item not found")

@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
    global fake_items_db
    fake_items_db = [item for item in fake_items_db if item.id != item_id]
    return {"message": "Item deleted successfully"}

4. 비동기 처리

FastAPI는 비동기 프로그래밍을 지원합니다. 설정한 CRUD 작업은 이미 비동기 함수로 정의되어 있으므로, 비동기적 요청 처리를 자동으로 활용할 수 있습니다. 다수의 사용자가 동시에 요청을 보내더라도, FastAPI는 효율적으로 요청을 처리할 수 있습니다.

4.1. 비동기 데이터베이스 연결

실제로는 인메모리 데이터베이스를 사용하지 않고, 데이터베이스와의 비동기 연결을 사용하는 것이 일반적입니다. 아래는 Async SQLAlchemy를 사용한 예시입니다:


from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "sqlite+aiosqlite:///./test.db"

engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, class_=AsyncSession)

# FastAPI 애플리케이션 생성
app = FastAPI()

# 데이터베이스 세션 종속성 정의
async def get_db() -> AsyncIterator[AsyncSession]:
    async with AsyncSessionLocal() as session:
        yield session

4.2. 비동기 CRUD 작업

이제 데이터베이스를 사용할 수 있으므로 CRUD 작업을 비동기 방식으로 업데이트합니다:


@app.post("/items/", response_model=Item)
async def create_item(item: Item, db: AsyncSession = Depends(get_db)):
    db.add(item)
    await db.commit()
    return item

@app.get("/items/", response_model=List[Item])
async def read_items(db: AsyncSession = Depends(get_db)):
    return await db.execute(select(Item)).scalars().all()

5. 테스트 및 디버깅

FastAPI는 자동으로 Swagger UI를 제공하므로, API를 테스트하는 데 매우 유용합니다. 서버를 실행하면 http://127.0.0.1:8000/docs에서 API 문서를 확인할 수 있습니다.

uvicorn main:app --reload

6. 결론

FastAPI는 비동기 프로그래밍을 통해 효율적인 API 서버를 구축할 수 있는 매우 강력한 도구입니다. 이번 글에서 소개한 CRUD 예제는 기본적인 개념을 이해하는 데 도움이 될 것입니다. 실제 프로젝트에서는 데이터베이스와의 연결, 사용자 인증, 그리고 비즈니스 로직을 추가하여 더욱 발전시킬 수 있습니다.

FastAPI의 장점인 고성능과 자동 문서화 기능을 활용하여 다양한 API를 손쉽게 개발해 보시기 바랍니다.

7. 참고 자료

FastAPI 서버개발, 도커파일 작성

FastAPI는 파이썬으로 작성된 현대적인 웹 프레임워크로, 빠른 성능과 직관적인 API 설계를 제공합니다. 이번 강좌에서는 FastAPI를 사용하여 간단한 웹 서버를 개발하고, 이를 도커로 감싸 배포하는 방법을 알아보겠습니다. 전체 과정은 크게 세 부분으로 나눌 수 있습니다:

  • FastAPI 서버 개발
  • FastAPI 서버의 기능 구현
  • 도커파일 작성 및 컨테이너화

1. FastAPI 서버 개발

1.1 FastAPI 설치

FastAPI를 사용하기 위해서는 먼저 FastAPI와 UVicorn(ASGI 서버)을 설치해야 합니다. 다음 명령어를 사용하여 설치할 수 있습니다:

pip install fastapi uvicorn

1.2 기본 FastAPI 서버 설정

아래의 간단한 예제는 기본적인 FastAPI 서버를 설정하는 방법을 보여줍니다:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"Hello": "World"}

위 코드는 가장 기본적인 FastAPI 서버로, 루트 URL(“/”)에 GET 요청을 보내면 JSON 형식으로 {“Hello”: “World”}를 반환합니다.

1.3 서버 실행

이제 서버를 실행해 보겠습니다. 아래와 같은 명령어로 서버를 시작할 수 있습니다:

uvicorn main:app --reload

여기서 main은 Python 파일의 이름(확장자 제외)이며, app은 FastAPI 인스턴스의 이름입니다. --reload 플래그는 코드 변경 시 자동으로 서버를 다시 시작합니다.

2. FastAPI 서버의 기능 구현

2.1 RESTful API 설계

FastAPI는 RESTful API 설계에 매우 유용합니다. 다음 단계에서는 사용자 관리 API를 구현해 보겠습니다.

2.2 데이터 모델 정의

FastAPI에서는 Pydantic을 사용하여 데이터 유효성 검사를 수행하는 모델을 정의할 수 있습니다. 사용자 모델을 정의해 보겠습니다:

from pydantic import BaseModel
from typing import List, Optional

class User(BaseModel):
    id: int
    name: str
    email: str

2.3 CRUD API 구현

다음으로 간단한 CRUD(Create, Read, Update, Delete) API를 만들어 보겠습니다. 사용자를 저장할 리스트를 만들고, 각 API 엔드포인트를 정의하겠습니다:

from fastapi import FastAPI, HTTPException

app = FastAPI()
users = []

@app.post("/users/", response_model=User)
async def create_user(user: User):
    users.append(user)
    return user

@app.get("/users/", response_model=List[User])
async def get_users():
    return users

@app.get("/users/{user_id}", response_model=User)
async def get_user(user_id: int):
    for user in users:
        if user.id == user_id:
            return user
    raise HTTPException(status_code=404, detail="User not found")

@app.put("/users/{user_id}", response_model=User)
async def update_user(user_id: int, user: User):
    for index, u in enumerate(users):
        if u.id == user_id:
            users[index] = user
            return user
    raise HTTPException(status_code=404, detail="User not found")

@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
    for index, u in enumerate(users):
        if u.id == user_id:
            del users[index]
            return {"message": "User deleted"}
    raise HTTPException(status_code=404, detail="User not found")

위 코드는 사용자를 생성, 조회, 수정 및 삭제하는 API를 구현합니다. 각 API는 적절한 HTTP 상태 코드를 반환합니다.

3. 도커파일 작성 및 컨테이너화

3.1 도커 설치

도커를 사용하기 위해서는 먼저 도커를 설치해야 합니다. 공식 웹사이트에서 설치 방법을 참고할 수 있습니다.

3.2 도커파일 작성

도커는 애플리케이션을 컨테이너화하여 쉽게 배포할 수 있게 도와줍니다. FastAPI 애플리케이션을 위한 도커파일을 작성해 보겠습니다. 파일 이름은 Dockerfile로 설정합니다:

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9

COPY ./app /app

# 설정된 작업 디렉토리
WORKDIR /app

# 필요한 의존성 설치
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# 애플리케이션 실행
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

도커파일에서 FROM 지시어는 사용할 기본 이미지를 결정합니다. COPY 지시어는 코드를 컨테이너에 복사하며, RUN 지시어는 필요한 라이브러리를 설치합니다. 마지막으로 CMD 지시어는 컨테이너가 시작될 때 실행되는 명령을 지정합니다.

3.3 요구 사항 파일 작성

다음으로 FastAPI와 UVicorn을 포함하는 requirements.txt 파일을 생성합니다:

fastapi
uvicorn

3.4 도커 이미지 빌드

이제 도커 이미지를 빌드할 차례입니다. 아래 명령어를 사용하여 이미지를 빌드합니다:

docker build -t myfastapiapp .

3.5 컨테이너 실행

컨테이너를 실행하려면 먼저 도커가 실행 중인지 확인한 후 다음 명령어를 입력합니다:

docker run -d --name fastapi-container -p 80:80 myfastapiapp

이렇게 하면 FastAPI 애플리케이션이 도커 컨테이너에서 실행됩니다. 웹 브라우저에서 http://localhost를 열면 API에 접속할 수 있습니다.

결론

이번 강좌에서는 FastAPI를 이용한 서버 개발 방법과 도커파일 작성 및 컨테이너화하는 과정을 살펴보았습니다. FastAPI는 직관적인 문법과 성능 덕분에 많은 개발자에게 사랑받고 있으며, 도커를 사용하면 쉽게 배포할 수 있습니다. 이를 통해 실제 운영 환경에서도 쉽게 사용할 수 있는 백엔드 서버를 구축할 수 있습니다.

FastAPI 서버개발, CORS 설정

FastAPI는 현대적인 웹 API를 쉽게 구축할 수 있도록 돕는 Python 기반의 프레임워크입니다. 이 프레임워크는 높은 성능을 자랑하며, 데이터 검증, 자동 문서화 등의 기능을 제공합니다. 본 글에서는 FastAPI 서버 개발 과정에서 마주칠 수 있는 CORS(Cross-Origin Resource Sharing) 설정에 대해 자세히 설명하고, 이를 통해 다양한 클라이언트(웹 브라우저 등)에서 API를 안전하게 접근할 수 있도록 하는 방법을 다루겠습니다.

CORS란 무엇인가?

CORS(Cross-Origin Resource Sharing)는 웹 브라우저에서 서로 다른 출처(origin)에서 리소스를 요청할 수 있게 하는 보안 기능입니다. 예를 들어, 만약 http://example.com에서 호스팅되는 웹 애플리케이션이 http://api.example.com으로 요청을 보낼 경우, 두 URL의 출처가 다르기 때문에 기본적으로 차단됩니다. 이를 해결하기 위해 CORS를 설정하여 특정 출처에서 API를 접근할 수 있도록 허용할 수 있습니다.

CORS의 필요성

CORS는 보안상의 이유로 구현되어 있습니다. 사용자가 스스로 모르는 사이에 악성 스크립트가 다른 도메인에 있는 데이터에 접근하는 것을 방지하기 위함입니다. 하지만 웹 애플리케이션에서는 여러 서비스와 상호작용을 위해 다른 출처와 연결할 필요가 있습니다. 따라서, 올바른 CORS 정책을 설정하는 것이 중요합니다.

FastAPI에서 CORS 설정하기

FastAPI에서는 fastapi.middleware.cors 모듈의 CORSMiddleware 클래스를 사용하여 쉽게 CORS 정책을 설정할 수 있습니다. 아래의 단계를 통해 FastAPI 애플리케이션에 CORS를 추가하는 방법을 살펴보겠습니다.

1. FastAPI 설치하기

FastAPI 및 기타 필요한 라이브러리를 우선 설치해야 합니다. 아래의 명령어를 터미널에 입력하여 FastAPI와 uvicorn을 설치합니다.

pip install fastapi uvicorn

2. 기본 FastAPI 애플리케이션 생성하기

아래의 코드는 FastAPI 애플리케이션을 간단히 설정하는 예제입니다.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello, FastAPI!"}

3. CORS 미들웨어 추가하기

CORS를 설정하기 위해 CORSMiddleware를 FastAPI 애플리케이션에 추가합니다. `allow_origins` 매개변수를 사용하여 허용할 출처를 지정할 수 있습니다.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# CORS 설정
origins = [
    "http://localhost:3000",
    "https://myfrontend.com",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,  # 허용할 출처
    allow_credentials=True,
    allow_methods=["*"],  # 허용할 HTTP 메서드
    allow_headers=["*"],  # 허용할 헤더
)

@app.get("/")
async def read_root():
    return {"message": "Hello, FastAPI!"}

4. CORS 설정 옵션 설명하기

  • allow_origins: 요청을 허용할 출처를 명시합니다. 도메인 이름이나 와일드카드(*)를 사용할 수 있습니다.
  • allow_credentials: 쿠키 및 인증 정보를 포함한 요청을 허용할지 여부를 설정합니다.
  • allow_methods: 허용할 HTTP 메서드를 설정합니다. 기본값은 GET, POST입니다.
  • allow_headers: 클라이언트가 요청할 수 있는 헤더를 지정합니다.

5. 다양한 환경에서의 CORS 설정 예제

개발 환경, 테스트 환경, 운영 환경에 따라 CORS 설정을 다르게 할 수 있습니다. 예를 들어, 개발 환경에서는 로컬 출처만을 허용하고, 운영 환경에서는 여러 도메인을 허용할 수 있습니다. 아래는 상황에 따라 다르게 설정하는 예제입니다.

import os
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 환경에 따라 CORS 설정을 변경
if os.getenv("ENV") == "production":
    origins = [
        "https://myfrontend.com",
        "https://anotherdomain.com",
    ]
else:
    origins = [
        "http://localhost:3000",
    ]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
async def read_root():
    return {"message": "Hello, FastAPI!"}

6. CORS 관련 문제 해결하기

CORS 설정을 제대로 해도 가끔 원하는 대로 동작하지 않을 수 있습니다. 이때 확인해야 할 몇 가지 사항이 있습니다.

  • 브라우저 콘솔 로그: 브라우저의 개발자 도구를 열고, 콘솔 탭에서 CORS 관련 에러 메시지를 확인합니다.
  • 서버 로그: FastAPI 서버의 로그 파일을 점검하여 요청이 서버에 도달했는지 확인합니다.
  • 네트워크 요청 확인: 개발자 도구의 네트워크 탭에서 요청 헤더와 응답 헤더를 분석하여 문제를 파악합니다.

결론

FastAPI는 CORS 설정을 통해 웹 애플리케이션과 API 간의 안전한 통신을 가능하게 합니다. 올바른 CORS 정책을 설정하여 다양한 출처의 클라이언트가 API를 접근할 수 있도록 하는 것이 중요합니다. 본 글에서 설명한 내용을 통해 FastAPI에서 CORS를 간단하게 설정하고 문제를 해결하는 데 도움이 되길 바랍니다.