FastAPI 서버개발, 사용자 인증 및 권한 부여 기능 추가하기

작성일: 2023년 10월 10일

소개

FastAPI는 Python으로 구축된 웹 프레임워크로, 비동기 프로그래밍과 데이터 검증을 지원하여 빠르고 효율적인 API를 개발할 수 있도록 도와줍니다. 이 글에서는 FastAPI를 사용하여 사용자 인증 및 권한 부여 기능을 구현하는 방법에 대해 자세히 설명하겠습니다.

1. 환경 설정

FastAPI와 관련 라이브러리를 설치하기 위해 Python의 패키지 관리자인 pip를 사용합니다. 다음 명령어를 통해 필요한 패키지를 설치합니다:

pip install fastapi uvicorn python-jose passlib[bcrypt]

각 라이브러리의 역할은 다음과 같습니다:

  • fastapi: 웹 프레임워크
  • uvicorn: ASGI 서버, FastAPI 애플리케이션을 실행하기 위해 사용
  • python-jose: JWT(Json Web Token) 인코딩 및 디코딩을 위한 라이브러리
  • passlib: 비밀번호 해싱을 위한 라이브러리

2. FastAPI 기본 구조

FastAPI 애플리케이션의 기본 구조는 다음과 같습니다:

from fastapi import FastAPI

app = FastAPI()

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

위 코드를 실행하면 기본적인 FastAPI 서버가 생성됩니다. 이를 바탕으로 사용자 인증 및 권한 부여 기능을 추가해보겠습니다.

3. 사용자 모델 정의

사용자 모델을 정의하기 위해 Pydantic을 사용할 것입니다. Pydantic은 데이터 검증을 자동으로 처리해주는 라이브러리로, FastAPI와 잘 연동됩니다.

from pydantic import BaseModel, EmailStr
from typing import Optional
from passlib.context import CryptContext

class User(BaseModel):
    username: str
    email: EmailStr
    full_name: Optional[str] = None
    disabled: Optional[bool] = None

class UserInDB(User):
    hashed_password: str

위의 User 모델은 사용자 정보를 정의하며, UserInDB는 데이터베이스에 저장되기 위해 해싱된 비밀번호를 포함합니다.

4. 비밀번호 해싱

비밀번호를 안전하게 저장하기 위해 해싱을 진행합니다. Passlib 라이브러리를 사용하여 비밀번호를 해싱하는 방법은 다음과 같습니다:

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str) -> str:
    return pwd_context.hash(password)

해싱된 비밀번호는 사용자를 데이터베이스에 저장할 때 사용됩니다.

5. 사용자 등록 API

사용자 등록을 처리할 API 엔드포인트를 생성합니다. 사용자가 입력한 정보를 통해 새로운 사용자를 생성하고, 비밀번호는 해싱하여 저장합니다.

from fastapi import HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

users_db = {}

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.post("/register/")
def register(user: User):
    if user.username in users_db:
        raise HTTPException(status_code=400, detail="Username already registered")
    hashed_password = hash_password(user.password)
    users_db[user.username] = UserInDB(
        username=user.username, email=user.email, full_name=user.full_name, hashed_password=hashed_password
    )
    return {"msg": "User registered successfully!"}

6. JWT 생성 및 검증

JWT(Json Web Token)를 이용하여 사용자 인증 및 권한 부여를 수행합니다. 다음 코드에서는 JWT를 생성하고 검증하는 방법을 보여줍니다:

from datetime import datetime, timedelta
from jose import JWTError, jwt

SECRET_KEY = "mysecretkey"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def verify_token(token: str):
    credentials_exception = HTTPException(status_code=401, detail="Could not validate credentials")
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    return username

7. 로그인 API

사용자가 로그인할 수 있는 API를 구현합니다. 사용자는 사용자명과 비밀번호를 입력하여 JWT를 생성합니다.

@app.post("/token")
def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = users_db.get(form_data.username)
    if not user or not pwd_context.verify(form_data.password, user.hashed_password):
        raise HTTPException(status_code=400, detail="Incorrect username or password")
    access_token = create_access_token(data={"sub": user.username})
    return {"access_token": access_token, "token_type": "bearer"}

8. 인증이 필요한 API 엔드포인트

인증이 필요한 엔드포인트를 추가하는 방법에 대해 설명합니다. OAuth2PasswordBearer 를 사용하여 API에 인증 기능을 추가할 수 있습니다.

from fastapi import Security

@app.get("/users/me", response_model=User)
def read_users_me(token: str = Depends(oauth2_scheme)):
    username = verify_token(token)
    user = users_db.get(username)
    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return user

9. 권한 부여 기능 추가하기

사용자 권한 부여 기능을 추가할 수 있습니다. 이를 통해 특정 사용자에게만 접근 허용하는 API 엔드포인트를 만들 수 있습니다.

def get_current_active_user(token: str = Depends(oauth2_scheme)):
    username = verify_token(token)
    user = users_db.get(username)
    if user is None or user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return user

@app.get("/users/me/role")
def read_user_role(current_user: User = Depends(get_current_active_user)):
    return {"username": current_user.username, "role": "admin"}

10. FastAPI 서버 실행하기

FastAPI 서버를 실행하기 위해 uvicorn를 사용합니다. 다음 명령어로 서버를 실행할 수 있습니다:

uvicorn main:app --reload

서버가 실행되면, /docs 경로로 접속하여 Swagger UI를 통해 API를 테스트할 수 있습니다.

결론

FastAPI를 사용하여 사용자 인증 및 권한 부여 기능을 성공적으로 구현했습니다. FastAPI의 강력한 기능을 통해 효율적인 웹 API를 구축할 수 있으며, JWT를 활용한 인증 방식은 보안과 성능 모두를 고려할 수 있는 좋은 선택입니다. 앞으로 FastAPI의 다양한 기능을 탐색해 보시기 바랍니다.

FastAPI 서버개발, 도커를 사용한 배포

현대의 웹 서버 개발에 있어 FastAPI는 빠른 속도와 직관적인 API 설계를 제공하는 프레임워크로 인기를 얻고 있습니다. 본 강좌에서는 FastAPI를 사용하여 기본적인 서버를 개발하는 방법과 그 서버를 도커를 통해 쉽게 배포하는 방법에 대해 설명하겠습니다.

1. FastAPI란?

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, Starlette을 기반으로 하며 Pydantic으로 데이터 유효성 검사를 제공합니다. 빠른 성능과 직관적인 문서화, 자동화된 API 문서 생성 기능 덕분에 많은 개발자들에게 선택받고 있습니다.

1.1 FastAPI의 주요 특징

  • 빠른 성능: ASGI 기반으로, 비동기 프로그래밍을 지원하여 높은 성능을 자랑합니다.
  • 자동화된 문서화: Swagger UI와 Redoc을 통한 자동 문서화 기능이 내장되어 있습니다.
  • Pydantic: 데이터 모델링 및 유효성 검사에 Pydantic을 사용합니다.
  • 비동기 지원: Python의 비동기 프로그래밍을 통해 I/O 작업을 효율적으로 처리할 수 있습니다.

2. FastAPI 서버 개발하기

2.1 환경 설정

FastAPI 서버를 만들기 위해 Python 3.6 이상이 필요합니다. 아래의 명령어를 사용하여 FastAPI와 Uvicorn을 설치합니다:

pip install fastapi uvicorn

2.2 기본적인 FastAPI 서버 작성

다음은 기본적인 FastAPI 서버의 코드 예제입니다:

from fastapi import FastAPI

app = FastAPI()

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

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "query": q}

이 코드는 두 개의 GET 엔드포인트를 가진 FastAPI 서버를 정의합니다. 첫 번째 엔드포인트는 루트 URL에 대한 응답으로 “Hello, FastAPI!” 메시지를 반환합니다. 두 번째 엔드포인트는 아이템 ID와 쿼리 파라미터를 받아 그 값을 반환합니다.

2.3 서버 실행하기

서버를 실행하기 위해 다음 명령어를 사용합니다:

uvicorn main:app --reload

이 명령은 FastAPI 서버를 로컬호스트 8000번 포트에서 실행합니다. 웹 브라우저에서 http://127.0.0.1:8000/docs로 접속하면 자동으로 생성된 Swagger UI를 통해 API를 탐색할 수 있습니다.

3. 도커를 사용한 배포

도커를 사용하면 FastAPI 서버의 배포를 간편하게 할 수 있습니다. 도커는 애플리케이션을 컨테이너 형태로 패키징하여 이식성과 관리성을 향상시키는 도구입니다.

3.1 도커 설치

도커를 설치하려면, 운영체제에 맞는 도커 설치 방법을 참조하여 설치합니다. 도커가 설치되면, 컨테이너를 쉽게 만들고 관리할 수 있는 환경을 갖추게 됩니다.

3.2 도커 파일 생성

FastAPI 애플리케이션을 도커로 배포하기 위해 도커 파일을 생성해야 합니다. 프로젝트 디렉토리에 Dockerfile이라는 이름의 파일을 생성하고 아래 내용을 추가합니다:

FROM python:3.9

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

# 의존성 파일 복사
COPY requirements.txt .

# 의존성 설치
RUN pip install --no-cache-dir -r requirements.txt

# 애플리케이션 코드 복사
COPY . .

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

3.3 요구 사항 파일

또한, requirements.txt 파일을 생성하여 애플리케이션의 의존성을 명시해야 합니다. 아래는 contents of requirements.txt의 예시입니다:

fastapi
uvicorn

3.4 도커 이미지 빌드하기

도커 파일을 준비했으면 다음 명령어를 사용하여 도커 이미지를 빌드할 수 있습니다:

docker build -t fastapi-app .

이 명령은 현재 디렉토리 (.)에 있는 Dockerfile을 읽어 fastapi-app라는 이름의 이미지를 생성합니다.

3.5 도커 컨테이너 실행하기

이미지를 빌드한 후, 다음 명령어로 컨테이너를 실행할 수 있습니다:

docker run -d --name my-fastapi-app -p 80:80 fastapi-app

이 명령은 my-fastapi-app라는 이름으로 컨테이너를 백그라운드에서 실행하며, 호스트의 포트 80을 컨테이너의 포트 80에 매핑합니다.

4. 도커와 함께하는 FastAPI의 장점

FastAPI를 도커와 함께 사용하면 다음과 같은 장점이 있습니다:

  • 이식성: 도커 컨테이너는 어떤 환경에서도 동일하게 실행됩니다.
  • 관리 용이성: 의존성 문제를 해결할 수 있으며, 컨테이너 관리를 통해 배포 및 롤백이 간편합니다.
  • 스케일링: 컨테이너를 쉽게 복제할 수 있으므로 수평 확장이 용이합니다.

5. 결론

FastAPI와 도커를 사용하여 웹 API를 개발하고 배포하는 과정은 매우 효율적입니다. FastAPI의 간결한 코드 작성법과 도커의 관리의 용이성을 결합하면 강력한 웹 애플리케이션을 쉽게 만들 수 있습니다.

이 강좌를 통해 FastAPI의 기본적인 사용법과 도커를 통한 배포 방법에 대해 이해할 수 있었기를 바랍니다. 다음 단계로는 FastAPI의 추가 기능이나 보안, 데이터베이스 연동 등을 탐색해보면 좋을 것입니다.

FastAPI 서버개발, FastAPI 성능 분석 및 모니터링 도구

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 높은 성능과 쉬운 사용성을 제공합니다. 비동기 I/O를 지원하며, Python 타입 힌트를 활용해 API 문서화를 자동으로 처리합니다. 이번 글에서는 FastAPI 서버를 개발하는 방법과 성능 분석 및 모니터링을 위한 도구에 대해 자세히 다루겠습니다.

1. FastAPI 서버 개발

1.1 FastAPI 설치

FastAPI를 사용하기 위해서는 먼저 필요한 패키지를 설치해야 합니다. 다음 명령어를 사용하여 FastAPI와 ASGI 서버인 Uvicorn을 설치할 수 있습니다.

pip install fastapi uvicorn

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

FastAPI 애플리케이션을 생성하는 것은 매우 간단합니다. 아래는 간단한 “Hello, World!” 애플리케이션의 예입니다.

from fastapi import FastAPI

app = FastAPI()

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

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

uvicorn main:app --reload

서버가 실행되면 http://127.0.0.1:8000/docs 에서 자동으로 생성된 API 문서를 확인할 수 있습니다.

1.3 경로 매개변수와 쿼리 매개변수

FastAPI에서는 경로 매개변수와 쿼리 매개변수를 손쉽게 정의할 수 있습니다. 아래는 두 가지 매개변수를 사용하는 예시입니다.

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

1.4 데이터 모델링

FastAPI는 Pydantic을 사용하여 데이터 모델을 정의합니다. 이를 통해 입력 데이터의 유효성을 검사할 수 있습니다.

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

2. FastAPI 성능 분석

FastAPI는 기본적으로 비동기적으로 동작하여 높은 성능을 자랑합니다. 하지만 성능을 더욱 향상시키기 위해 여러 가지 방법을 사용할 수 있습니다.

2.1 성능 테스트 도구

성능을 분석하기 위해 다양한 도구를 사용할 수 있습니다. 가장 흔히 사용되는 도구는 LocustApache Benchmark입니다.

Locust 설치 및 사용 예제

pip install locust

아래는 Locust를 사용하여 FastAPI 애플리케이션의 부하 테스트를 수행하는 예제입니다.

from locust import HttpUser, task

class FastAPIUser(HttpUser):
    @task
    def index(self):
        self.client.get("/")

위 코드를 locustfile.py 파일로 저장한 후, 다음 명령어로 Locust를 실행할 수 있습니다.

locust -f locustfile.py

웹 브라우저에서 http://localhost:8089에 접속하여 원하는 수의 사용자를 설정하고 테스트를 진행할 수 있습니다.

2.2 APM(애플리케이션 성능 모니터링) 도구

애플리케이션의 성능을 모니터링하기 위해 APM 도구를 사용하는 것이 효과적입니다. 대표적인 APM 도구로는 New Relic, Datadog, Sentry가 있습니다.

New Relic 설치 및 설정

New Relic을 사용하기 위해서는 먼저 계정을 생성한 후, 아래의 명령어로 New Relic Python 에이전트를 설치해야 합니다.

pip install newrelic

설치 후, newrelic-admin generate-config YOUR_NEW_RELIC_LICENSE_KEY newrelic.ini 명령어를 통해 설정 파일을 생성합니다. 이후 FastAPI 애플리케이션을 실행할 때 아래와 같이 설정할 수 있습니다.

NEW_RELIC_CONFIG_FILE=newrelic.ini newrelic-admin run-program uvicorn main:app --reload

3. FastAPI 모니터링 도구

서버의 상태를 모니터링하기 위해 다양한 도구를 사용할 수 있습니다. 여러 유형의 로그 및 메트릭을 수집하는 것이 중요합니다.

3.1 Prometheus와 Grafana

Prometheus는 시계열 데이터베이스로, 데이터를 수집하고 쿼리할 수 있는 역량을 제공합니다. Grafana는 그 데이터를 시각화하는 도구입니다.

FastAPI와 Prometheus 연동

먼저, prometheus_fastapi_instrumentator 패키지를 설치합니다.

pip install prometheus-fastapi-instrumentator

다음으로, FastAPI 애플리케이션에 Prometheus 미들웨어를 추가하는 예제입니다.

from prometheus_fastapi_instrumentator import Instrumentator

instrumentator = Instrumentator()

@app.on_event("startup")
def startup():
    instrumentator.instrument(app).expose(app)

이렇게 설정한 후, Prometheus는 FastAPI 애플리케이션의 상태를 자동으로 수집합니다.

3.2 ELK 스택(Elasticsearch, Logstash, Kibana)

ELK 스택은 저장된 로그 데이터의 검색 및 분석을 가능하게 합니다. FastAPI 애플리케이션의 로그 데이터를 ELK 스택과 연결하는 방법은 다음과 같습니다.

FastAPI 로깅 설정

파이썬의 logging 모듈을 사용하여 FastAPI의 로그를 설정할 수 있습니다.

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.get("/")
async def read_root():
    logger.info("Root endpoint accessed")
    return {"Hello": "World"}

이렇게 설정한 로그를 Logstash를 통해 Elasticsearch로 전송하고, Kibana를 통해 분석할 수 있습니다.

결론

FastAPI는 빠르고 효율적인 API 서버 개발을 지원하며, 성능 분석 및 모니터링 도구와의 연동을 통해 애플리케이션의 상태를 실시간으로 확인할 수 있습니다. 이 글에서는 FastAPI 서버 개발을 위한 기본적인 내용과 각종 성능 분석 및 모니터링 도구를 소개했습니다. 이를 통해 더 나은 FastAPI 애플리케이션을 개발해보시기 바랍니다.

FastAPI 서버개발, 의존성 주입의 개념 및 FastAPI에서의 구현

FastAPI는 현대적인 Python 웹 프레임워크로, 비동기 프로그래밍 기능과 데이터 유효성 검사를 매우 효율적으로 처리할 수 있는 강력한 도구입니다. 이 글에서는 FastAPI에서의 의존성 주입(Dependency Injection, DI)의 개념과 이를 구현하는 방법에 대해 심도 있게 다루겠습니다.

1. 의존성 주입(Dependency Injection) 개념

의존성 주입은 소프트웨어 개발에서 객체의 의존성을 관리하는 패턴입니다. 이는 객체가 필요한 의존성을 스스로 생성하는 것이 아니라, 외부에서 주입받는 방식입니다. 이러한 접근 방식은 코드의 재사용성을 높이고, 테스트 용이성을 향상시키며, 유지보수성을 강화합니다.

1.1 의존성 주입의 장점

  • 유지보수성: 의존성을 외부로 분리함으로써 코드의 유동성을 증가시키고, 변경의 영향을 최소화합니다.
  • 테스트 용이성: 의존성을 주입받기 때문에, 모의 객체(mock object)를 사용하여 단위 테스트를 쉽게 작성할 수 있습니다.
  • 재사용성: 각 구성 요소가 독립적으로 설계되므로, 코드의 재사용성이 높아집니다.

2. FastAPI에서의 의존성 주입 구현

FastAPI는 의존성 주입을 지원하는 강력한 기능을 제공합니다. FastAPI에서 의존성을 정의하려면 다음의 세 가지 단계로 나눌 수 있습니다:

  1. 의존성 함수 정의하기
  2. 의존성을 라우트에 주입하기
  3. 의존성을 사용하는 서비스 구현하기

2.1 의존성 함수 정의하기

의존성 함수는 다른 라우트에서 재사용할 수 있는 공통적인 기능을 정의합니다. 아래의 예제에서는 데이터베이스 연결을 의존성으로 설정하는 방법을 보여줍니다:

from fastapi import Depends, FastAPI

app = FastAPI()

# 의존성 함수 정의
def get_db():
    db = "데이터베이스 연결"
    try:
        yield db
    finally:
        print("데이터베이스 연결 종료")

2.2 의존성을 라우트에 주입하기

의존성 함수를 정의한 후, 이를 라우트에서 사용할 수 있습니다. 아래의 샘플 코드에서는 앞서 정의한 get_db 함수를 라우트에 주입합니다:

@app.get("/items/")
async def read_items(db: str = Depends(get_db)):
    return {"message": "항목 정보를 가져왔습니다.", "db_connection": db}

2.3 의존성을 사용하는 서비스 구현하기

의존성 주입을 통해 서비스 계층을 구성할 수 있습니다. FastAPI에서는 이러한 서비스를 쉽게 구현할 수 있게 도와줍니다. 다음 예제에서는 의존성 주입을 통해 사용자 정보를 처리하는 서비스를 제공합니다:

class UserService:
    def __init__(self, db: str):
        self.db = db

    def get_user(self, user_id: int):
        # 사용자 정보를 데이터베이스에서 가져오는 로직
        return {"user_id": user_id, "db_connection": self.db}

@app.get("/users/{user_id}")
async def read_user(user_id: int, db: str = Depends(get_db)):
    service = UserService(db)
    return service.get_user(user_id)

3. FastAPI에서의 의존성 주입 사용 예제

3.1 예제: 간단한 게시판 API

아래는 FastAPI를 사용하여 간단한 게시판 API를 구현하는 예제입니다. 이 예제에서는 의존성 주입을 사용하여 데이터베이스 연결과 게시물 서비스를 관리합니다.

from fastapi import FastAPI, Depends
from typing import List

app = FastAPI()

# 가상 데이터베이스
posts_db = []

# 의존성 함수
def get_db():
    return posts_db

# 게시물 모델
class Post:
    id: int
    title: str
    content: str

# 게시물 서비스
class PostService:
    def __init__(self, db: List[Post]):
        self.db = db

    def create_post(self, title: str, content: str):
        post = Post(id=len(self.db) + 1, title=title, content=content)
        self.db.append(post)
        return post
    
    def get_posts(self):
        return self.db

# 게시물 생성 API
@app.post("/posts/", response_model=Post)
async def create_post(title: str, content: str, db: List[Post] = Depends(get_db)):
    service = PostService(db)
    return service.create_post(title, content)

# 모든 게시물 조회 API
@app.get("/posts/", response_model=List[Post])
async def read_posts(db: List[Post] = Depends(get_db)):
    service = PostService(db)
    return service.get_posts()

4. 테스트와 활용

의존성 주입을 활용하여 각 성공적인 테스트를 작성할 수 있습니다. 예를 들어, PostService의 인스턴스를 모의 객체로 주입하여, 데이터베이스와의 의존성을 줄이면서도 서비스 로직을 테스트할 수 있습니다.

4.1 pytest를 활용한 테스트 예제

리얼 데이터베이스 대신 간단한 목(mock) 데이터를 사용해 테스트하는 방법을 보여드립니다:

from fastapi.testclient import TestClient

client = TestClient(app)

def test_create_post():
    response = client.post("/posts/", json={"title": "테스트 제목", "content": "테스트 내용"})
    assert response.status_code == 200
    assert response.json()["title"] == "테스트 제목"

def test_read_posts():
    response = client.get("/posts/")
    assert response.status_code == 200
    assert len(response.json()) > 0

5. 결론

FastAPI에서의 의존성 주입은 애플리케이션의 구조를 명확히 하고, 코드의 가독성을 높이며, 유지보수 및 테스트를 쉽게 만들어 줍니다. 의존성 주입의 개념을 이해하고, 이를 FastAPI에서 효과적으로 활용할 수 있도록 하는 것이 중요합니다. 본 글에서 제공한 예제와 개념들이 여러분의 웹 애플리케이션 개발에 많은 도움이 되길 바랍니다. FastAPI를 통한 서버 개발을 통하여 여러분의 프로젝트를 한 단계 더 발전시켜 보세요!

FastAPI 서버개발, docker compose를 사용하는 이유

현대 웹 개발에서는 빠르고 효율적인 애플리케이션을 구축하는 것이 점점 더 중요해지고 있습니다. FastAPI는 Python을 기반으로 하여 비동기 웹 프레임워크로서 높은 성능과 사용 편의성을 제공합니다. 그러나, 실제 애플리케이션을 배포하고 운영하기 위해서는 여러 가지 환경 설정 및 관리 작업이 필요합니다. 이러한 설정을 보다 간편하게 해주는 도구 중 하나가 바로 Docker와 Docker Compose입니다. 이번 글에서는 FastAPI 서버를 Docker Compose와 함께 사용하는 이유에 대해 자세히 설명하고, 예제 코드를 통해 이해를 돕겠습니다.

1. FastAPI란?

FastAPI는 Python 3.6 이상에서 사용할 수 있는 비동기 웹 프레임워크로, RESTful API를 구축하는 데 최적화되어 있습니다. FastAPI는 Pydantic을 기반으로 한 데이터 유효성 검사, 자동 문서화, 그리고 높은 성능(Starlette 프레임워크 기반) 등의 장점을 제공합니다. FastAPI를 사용하면 개발자는 API를 빠르게 구축하고, 배포하며 스케일링할 수 있습니다.

FastAPI의 주요 특징

  • 비동기 IO 지원: FastAPI는 비동기 프로그래밍 모델을 지원하여 높은 성능을 제공합니다.
  • 자동 문서화: Swagger UI와 ReDoc을 사용한 자동 API 문서화를 지원합니다.
  • 데이터 유효성 검사: Pydantic을 통해 데이터 모델의 유효성을 검사할 수 있습니다.
  • 유연성: 다양한 인증 및 보안 메커니즘을 쉽게 추가할 수 있습니다.

2. Docker란?

Docker는 컨테이너 기술을 기반으로 하는 오픈 소스 플랫폼으로, 애플리케이션을 신속하고 일관되게 배포할 수 있도록 도와줍니다. Docker를 사용하면 애플리케이션과 그 종속성이 포함된 이미지를 생성하고, 이를 통해 동일한 환경에서 실행할 수 있습니다. 이를 통해 “작동하는 내 머신에서 되지 않는” 문제를 해결할 수 있습니다.

Docker의 주요 특징

  • 환경 일관성: 개발, 테스트, 운영 환경에서 동일한 컨테이너를 사용할 수 있습니다.
  • 리소스 효율성: 가상 머신보다 가볍고 성능 저하가 적습니다.
  • 신속한 배포: 이미지를 사용하여 빠르게 애플리케이션을 배포할 수 있습니다.
  • 스케일링: 여러 인스턴스를 쉽게 실행하고 관리할 수 있습니다.

3. Docker Compose란?

Docker Compose는 여러 개의 Docker 컨테이너를 정의하고 실행할 수 있는 도구입니다. 복잡한 애플리케이션 환경을 간편하게 설정하고 관리할 수 있도록 도와줍니다. Compose는 YAML 파일을 사용하여 애플리케이션의 서비스, 네트워크 및 볼륨을 구성할 수 있습니다.

Docker Compose의 사용 장점

  • 서비스 정의: 여러 서비스를 하나의 YAML 파일에 정의할 수 있습니다.
  • 일괄 실행: 단일 명령어로 모든 서비스를 시작하거나 중지할 수 있습니다.
  • 환경 변수 지원: 다양한 설정을 환경 변수로 쉽게 관리할 수 있습니다.
  • 상태 관리: 컨테이너의 상태를 자동으로 관리합니다.

4. FastAPI와 Docker Compose를 함께 사용하는 이유

FastAPI 애플리케이션을 Docker Compose로 관리하면 다음과 같은 여러 가지 이점이 있습니다:

  • 개발 환경 일관성: 팀원 간에 동일한 개발 환경을 공유할 수 있습니다.
  • 자동화: 배포 과정에서 반복적인 작업을 자동화할 수 있습니다.
  • 스케일링 용이성: 추가 서비스를 쉽게 배포하고 관리할 수 있습니다.
  • 테스트와디버깅: Docker 컨테이너 내에서의 빠른 테스트나 디버깅이 가능합니다.

5. FastAPI 애플리케이션을 Docker Compose로 설정하기

그럼 FastAPI 애플리케이션을 Docker Compose로 설정하는 방법에 대해 단계별로 알아보겠습니다.

5.1. FastAPI 애플리케이션 코드 작성

먼저, FastAPI 애플리케이션을 작성하겠습니다. `app.py`라는 파일을 생성하고 아래의 코드를 입력합니다:

from fastapi import FastAPI

app = FastAPI()

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

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

5.2. Dockerfile 작성

다음으로, 비슷한 디렉토리에 `Dockerfile`을 생성하고 아래 내용을 추가합니다:

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

COPY ./app /app

# 의존성 설치
RUN pip install fastapi
RUN pip install uvicorn

5.3. Docker Compose 설정

이제 `docker-compose.yml` 파일을 생성하고 아래와 같이 작성합니다:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8000:80"
    volumes:
      - ./app:/app
    environment:
      - MODULE_NAME=app.main

5.4. Docker Compose 명령어 실행

이제 Docker Compose를 통해 애플리케이션을 실행해봅시다. 아래의 명령어를 입력하여 Docker Compose를 실행합니다:

docker-compose up --build

이제 웹 브라우저를 열고 http://localhost:8000으로 접근하면 FastAPI가 정상적으로 동작하는 것을 확인할 수 있습니다. Swagger UI는 http://localhost:8000/docs에서 확인할 수 있습니다.

6. 결론

FastAPI는 현대 웹 API 구축에 적합한 고성능 프레임워크이며, Docker와 Docker Compose는 이러한 애플리케이션을 관리하는 데 큰 도움이 됩니다. 컨테이너화 및 서비스 관리를 통해 복잡한 환경에서도 일관성을 유지할 수 있으며, 개발 과정에서의 효율성이 크게 향상됩니다. FastAPI와 Docker Compose의 조합은 개발자에게 편리하고 강력한 도구를 제공합니다.

앞으로 FastAPI 및 Docker Compose를 적극적으로 활용하여 보다 품질 높은 애플리케이션을 개발할 수 있기를 바랍니다. 이 글이 FastAPI와 Docker Compose를 이해하는 데 도움이 되었기를 바랍니다.