FastAPI 서버개발, FastAPI의 확장 기능 및 플러그인 개발하기

FastAPI는 빠르고 현대적인 웹 프레임워크로, Python을 기반으로 RESTful API를 만드는데 최적화되어 있습니다. FastAPI는 뛰어난 성능과 직관적인 사용법 덕분에 많은 개발자들에게 사랑받고 있으며, 다양한 기능과 확장성 덕분에 복잡한 애플리케이션을 구축하는 데에도 유용합니다. 이번 글에서는 FastAPI의 확장 기능과 플러그인 개발에 대해 깊이 있게 탐구해 보겠습니다.

1. FastAPI의 기본 구조 이해하기

FastAPI를 사용하면 간단한 HTTP 엔드포인트를 신속하게 만들 수 있습니다. 다음은 FastAPI의 기본 구조를 보여주는 간단한 예제입니다.

from fastapi import FastAPI

app = FastAPI()

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

위의 코드는 가장 기본적인 FastAPI 서버를 설정하는 예제입니다. FastAPI() 객체를 생성하고, @app.get() 데코레이터를 사용하여 GET 요청에 대한 엔드포인트를 구현합니다.

2. FastAPI의 확장성 이해하기

FastAPI는 여러 가지 내장 기능을 제공하지만, 개발자는 종종 추가적인 기능을 필요로 하게 됩니다. FastAPI는 이러한 필요를 충족시키기 위해 다양한 방법으로 확장할 수 있는 구조를 갖추고 있습니다.

2.1. 의존성 주입과 확장

FastAPI는 의존성 주입 시스템을 통해 경량화된 확장을 지원합니다. 의존성을 정의하고 이를 사용할 수 있는 직접적인 방식으로, 다음과 같은 예제가 있습니다.

from fastapi import Depends

def get_query_param(q: str = None):
    return q

@app.get("/items/")
async def read_items(q: str = Depends(get_query_param)):
    return {"q": q}

위의 예에서 get_query_param 함수는 쿼리 파라미터를 가져오는 역할을 하며, Depends를 통해 이를 엔드포인트에 주입합니다.

2.2. Middleware의 활용

FastAPI는 미들웨어를 통해 요청과 응답을 처리하는 로직을 추가할 수 있습니다. 이 기능은 로깅, 인증, CORS 설정 등 다양한 용도로 활용할 수 있습니다. 다음은 미들웨어를 설정하는 예제입니다.

from fastapi.middleware.cors import CORSMiddleware

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

@app.get("/cors/")
async def cors_example():
    return {"message": "CORS 설정이 완료되었습니다."}

위의 코드는 모든 도메인에서 이 API에 대한 요청을 허용하도록 CORS 미들웨어를 설정하는 예입니다.

3. FastAPI 플러그인 개발하기

FastAPI의 확장 기능을 더욱 활용하려면 자체 플러그인을 개발할 수 있습니다. 플러그인은 FastAPI 애플리케이션에 독립적으로 배포 가능하며, 다른 프로젝트에서도 재사용할 수 있는 구성 요소입니다.

3.1. FastAPI 플러그인 구조

플러그인을 만드려면 FastAPI의 APIRouter를 활용해야 합니다. 플러그인을 만들기 위한 기본 구조는 다음과 같습니다.

from fastapi import APIRouter

router = APIRouter()

@router.get("/plugin/")
async def plugin_example():
    return {"message": "플러그인이 작동하고 있습니다."}

위의 코드는 플러그인의 기본적인 구조를 보여줍니다. 여기서 APIRouter를 활용하여 독립적인 엔드포인트를 정의할 수 있습니다.

3.2. 플러그인 통합하기

개발한 플러그인을 FastAPI 애플리케이션에 통합하기 위해서는 다음과 같이 설정할 수 있습니다.

from fastapi import FastAPI
from my_plugin import router as my_plugin_router  # 아까 만든 플러그인 임포트

app = FastAPI()

app.include_router(my_plugin_router)

위의 경우, my_plugin에서 정의한 라우터를 메인 애플리케이션에 통합하고 있습니다.

3.3. 플러그인에서 의존성 주입 사용하기

플러그인 내에서 의존성 주입을 활용하는것도 가능합니다. 아래는 플러그인에서 의존성을 사용하는 예제입니다.

def common_query_param(q: str = None):
    return q

@router.get("/plugin_with_dependency/")
async def plugin_with_dependency(q: str = Depends(common_query_param)):
    return {"message": f"수신된 쿼리: {q}"}

위의 예제는 플러그인 내에서 의존성 주입을 통해 쿼리 파라미터를 수신하는 방법을 보여줍니다.

4. FastAPI의 오픈API와 문서화

FastAPI는 OpenAPI를 지원하여 자동으로 API 문서를 생성할 수 있습니다. Swagger UI와 ReDoc와 같은 인터페이스를 통해 API를 테스트하고 문서화할 수 있습니다. 설정은 다음과 같습니다.

app = FastAPI(title="My API", description="이 API는 FastAPI로 만들어졌습니다.", version="1.0.0")

@app.get("/api/docs")
async def get_docs():
    return {"message": "문서화된 API에 접근합니다."}

위의 코드를 통해 API의 documentation URL을 설정하고, API 엔드포인트를 문서화하는 방법을 알 수 있습니다.

5. FastAPI와 데이터베이스 통합

FastAPI를 데이터베이스와 통합하는 것은 웹 애플리케이션 개발에서 중요한 부분입니다. SQLAlchemy와 같은 ORM(Object Relational Mapping)을 사용하여 데이터베이스와의 상호작용을 간편하게 구현할 수 있습니다.

5.1. SQLAlchemy와 FastAPI

다음은 SQLAlchemy를 FastAPI와 연결하는 기본 예제입니다.

from fastapi import FastAPI, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session

DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class Item(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)

Base.metadata.create_all(bind=engine)

app = FastAPI()

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

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

위의 예제는 SQLite 데이터베이스를 사용하여 CRUD(Create, Read, Update, Delete) 작업을 수행하는 FastAPI 서버를 설정하는 방법을 보여줍니다.

6. FastAPI와 비동기 프로그래밍

FastAPI는 비동기 프로그래밍을 지원하여 높은 성능을 제공합니다. 데이터베이스 쿼리와 서버 간의 연결을 비동기로 처리하는 예제는 다음과 같습니다.

import asyncpg
from fastapi import FastAPI

app = FastAPI()

async def connect_db():
    conn = await asyncpg.connect(user='user', password='password', database='db', host='127.0.0.1')
    return conn

@app.get("/async-example/")
async def async_example():
    conn = await connect_db()
    row = await conn.fetch("SELECT * FROM items;")
    await conn.close()
    return row

위의 예제는 asyncpg 라이브러리를 사용하여 PostgreSQL과 비동기적으로 연결하는 예제입니다.

7. 결론

FastAPI는 RESTful API를 신속하게 개발할 수 있는 강력한 프레임워크입니다. 이번 글에서는 FastAPI의 확장 기능과 플러그인 개발 방법에 대해 살펴보았습니다. 의존성 주입, 미들웨어, 플러그인 구조 및 데이터베이스 통합, 비동기 프로그래밍 등 다양한 기능을 통해 FastAPI를 더욱 효과적으로 활용할 수 있습니다. 이러한 지식을 바탕으로 여러분의 프로젝트에서 FastAPI를 적용하고, 멋진 웹 애플리케이션을 만들어 보시기 바랍니다.

FastAPI와 함께 할 멋진 개발 경험을 쌓으시길 바랍니다!

FastAPI 서버개발, 서버리스(SERVERLESS) 아키텍처에서 FastAPI 사용하기

최근 몇 년 동안, 서버리스 아키텍처는 개발자들 사이에서 인기를 얻고 있습니다. 이는 전통적인 서버 구축과 관리의 복잡함에서 벗어나, 코드를 작성하고 배포하는 데 집중할 수 있게 해줍니다. 본 글에서는 FastAPI를 활용하여 서버리스 아키텍처를 구축하는 방법에 대해 자세히 설명하겠습니다.

1. 서버리스 아키텍처란?

서버리스 아키텍처는 개발자가 서버를 직접 관리하지 않고 클라우드 서비스 제공업체에 의해 자동으로 스케일링되고 관리되는 웹 애플리케이션을 구축하는 방법입니다. 이 때 사용되는 서버는 일시적이며 불필요한 서버 관리 작업으로부터 해방될 수 있습니다.

서버리스 아키텍처의 장점은 다음과 같습니다:

  • 비용 효율성: 사용한 만큼만 지불하므로, 유지비용이 적고 비용을 절감할 수 있습니다.
  • 자동 확장: 트래픽이 증가할 때 자동으로 리소스를 할당하므로 수요에 맞춰 조정이 가능합니다.
  • 빠른 배포: 개발자는 비즈니스 로직에 집중하고 인프라 관리에서 벗어날 수 있습니다.

2. FastAPI란?

FastAPI는 Python을 사용하여 API를 구축하기 위한 매우 효율적인 웹 프레임워크입니다. 이는 비동기 프로그래밍을 지원하고, 자동으로 OpenAPI 및 JSON Schema 문서를 생성하며, 빠른 성능을 자랑합니다. FastAPI를 선택하는 이유는 다음과 같습니다:

  • 높은 성능: Starlette를 기반으로 하여 높은 처리량을 자랑합니다.
  • 쉬운 사용법: 기초적인 Python 지식만으로도 쉽게 API를 구축할 수 있습니다.
  • 유효성 검사: Pydantic을 사용하여 데이터 유효성을 자동으로 검사합니다.

3. FastAPI와 서버리스: AWS Lambda로 시작하기

FastAPI를 서버리스 아키텍처에서 사용할 수 있는 곳 중 하나는 AWS Lambda입니다. AWS Lambda는 이벤트 기반으로 서버 코드가 실행되는 컴퓨팅 서비스입니다. 이 연재에서는 FastAPI 애플리케이션을 AWS Lambda에서 실행하는 방법을 설명하겠습니다.

3.1. AWS Lambda와 API Gateway 설정하기

FastAPI 애플리케이션을 AWS Lambda에서 실행할 수 있도록 하기 위해, AWS Lambda와 Amazon API Gateway를 설정해야 합니다.

  1. AWS 계정을 만들고 AWS Management Console에 로그인합니다.
  2. 서비스 목록에서 “Lambda”를 선택한 후 “함수 생성”을 클릭합니다.
  3. 함수 이름을 입력하고 런타임을 “Python 3.x”로 설정 후 “함수 생성”을 클릭합니다.
  4. 함수가 생성되면, “API Gateway” 트리거를 추가합니다.

3.2. FastAPI 애플리케이션 코드 작성하기

FastAPI 애플리케이션을 작성해 보겠습니다. 아래 코드는 기본적인 FastAPI 앱의 예입니다.


from fastapi import FastAPI

app = FastAPI()

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

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

위 코드는 FastAPI 앱을 생성하고 두 개의 엔드포인트를 정의합니다. 첫 번째 엔드포인트는 루트 URL로 요청받을 때 “Hello, World!” 메시지를 반환하며, 두 번째 엔드포인트는 아이템 ID와 쿼리 파라미터를 받아 해당 정보를 반환합니다.

3.3. AWS Lambda에 FastAPI 배포하기

AWS Lambda에 FastAPI 애플리케이션을 배포하려면, Zappa라는 도구를 사용할 수 있습니다. Zappa는 Python 웹 애플리케이션을 서버리스 환경에서 손쉽게 배포할 수 있게 도와주는 프레임워크입니다. 아래 단계로 진행해 보겠습니다.

  1. Zappa 설치하기:
  2. pip install zappa
  3. Zappa 설정 파일 생성하기:
  4. zappa init
  5. 배포하기:
  6. zappa deploy

3.4. CORS 설정하기

서버리스 아키텍처에서 FastAPI 애플리케이션이 다른 도메인에서 요청을 받을 수 있도록 CORS(Cross-Origin Resource Sharing) 설정이 필요할 수 있습니다. FastAPI에서는 CORS 미들웨어를 쉽게 추가할 수 있습니다.


from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 허용할 도메인 목록
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
    

4. FastAPI와 데이터베이스 연동하기

FastAPI와 데이터베이스를 연결하여 실제 애플리케이션을 만드는 것도 가능합니다. SQLAlchemy를 사용하여 FastAPI와 관계형 데이터베이스를 쉽게 연동할 수 있습니다.

4.1. SQLAlchemy 설치하기

pip install sqlalchemy databases

4.2. FastAPI로 데이터베이스 CRUD 작업 구현하기


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 Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    price = Column(Integer)

Base.metadata.create_all(bind=engine)

@app.post("/items/")
async def create_item(item: Item):
    db = SessionLocal()
    db.add(item)
    db.commit()
    db.refresh(item)
    db.close()
    return item
    

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

FastAPI는 비동기 작업을 지원하므로, 데이터베이스 연결 시 비동기 ORM 라이브러리를 사용할 수도 있습니다. databases 라는 라이브러리를 활용하여 비동기로 데이터베이스와 연결해 보겠습니다.


import databases

database = databases.Database(DATABASE_URL)

@app.on_event("startup")
async def startup():
    await database.connect()

@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()

@app.post("/async-items/")
async def create_async_item(item: Item):
    query = Item.__table__.insert().values(name=item.name, price=item.price)
    last_record_id = await database.execute(query)
    return {**item.dict(), "id": last_record_id}
    

5. 테스트 및 디버깅

FastAPI는 내장된 테스트 클라이언트를 제공하여 API를 쉽게 테스트할 수 있습니다. pytest와 함께 사용해 보겠습니다. FastAPI 앱을 테스트하려면, 다음과 같이 작성할 수 있습니다.


from fastapi.testclient import TestClient

client = TestClient(app)

def test_read_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello, World!"}
    

6. 결론

FastAPI와 서버리스 아키텍처는 함께 사용될 때 고성능의 비즈니스 로직을 처리할 수 있는 훌륭한 조합이 됩니다. AWS Lambda와 같은 서버리스 플랫폼을 활용하여, 트래픽 변화에 따른 유연한 리소스 관리가 가능합니다. FastAPI의 간결한 문법과 빠른 개발 속도로 인해, 개발자들은 애플리케이션의 구현에 더욱 집중하고 개선할 수 있습니다.

오늘 다룬 내용을 바탕으로 실습을 진행하고, 여러분의 프로젝트에 FastAPI와 서버리스 아키텍처를 접목해 보시기 바랍니다. 빠른 성장과 혁신을 위한 좋은 선택이 될 것입니다.

FastAPI 서버개발, GCP 배포의 개요

FastAPI는 최신 웹 프레임워크로, Python으로 작성된 API를 만드는 데 매우 효율적입니다. 이 강좌에서는 FastAPI를 사용하여 기본적인 백엔드 서버를 개발하고 Google Cloud Platform(GCP)에 배포하는 과정을 단계별로 안내할 것입니다.

1. FastAPI란?

FastAPI는 Python으로 작성된 비동기 웹 프레임워크로, RESTful API를 쉽게 제작할 수 있게 해줍니다. FastAPI의 주요 특징은 높은 성능, 쉬운 사용법, 자동화된 문서화 기능입니다. Starlette를 기반으로 하며, Pydantic을 사용하여 데이터 검증과 직렬화를 지원합니다.

1.1 FastAPI의 주요 기능

  • 비동기 지원: FastAPI는 비동기 프로그래밍을 지원하여 높은 성능을 제공합니다.
  • 자동 문서화: OpenAPI를 기반으로 한 자동 API 문서화 기능을 제공합니다.
  • 유효성 검사: Pydantic을 이용하여 데이터 유효성 검사와 직렬화를 간편하게 처리할 수 있습니다.
  • 경량화: 기본적인 사용법이 간단하여 작은 규모의 애플리케이션부터 대규모 서비스까지 적합합니다.

2. FastAPI 서버 개발하기

이번 섹션에서는 FastAPI를 이용하여 간단한 REST API 서버를 구축해 보겠습니다. 예제를 통해 FastAPI의 기본적인 사용법을 익힐 수 있습니다.

2.1 FastAPI 설치하기

FastAPI와 Uvicorn(ASGI 서버)을 설치하기 위해 다음 명령어를 사용합니다:

pip install fastapi uvicorn

2.2 간단한 API 예제

다음은 기본적인 FastAPI 서버 코드입니다. 이 코드는 간단한 GET 및 POST 요청을 처리하는 API를 정의하고 있습니다.


from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# 데이터 모델 정의
class Item(BaseModel):
    name: str
    price: float
    is_offer: bool = None

# GET 요청 처리
@app.get("/")
def read_root():
    return {"Hello": "World"}

# POST 요청 처리
@app.post("/items/")
def create_item(item: Item):
    return {"item": item}

위 코드는 FastAPI를 사용하여 기본적인 API를 설정하는 방법을 보여줍니다. Item이라는 데이터 모델을 만들고, GET 요청과 POST 요청을 처리하는 두 개의 엔드포인트를 설정했습니다.

2.3 서버 실행하기

다음 명령어를 사용하여 FastAPI 서버를 실행할 수 있습니다:

uvicorn main:app --reload

서버가 시작되면 http://localhost:8000/docs에서 자동 생성된 API 문서를 확인할 수 있습니다.

3. Google Cloud Platform에 배포하기

이제 FastAPI 서버를 GCP에 배포하는 방법을 알아보겠습니다. GCP의 Cloud Run 서비스를 사용하면 컨테이너화된 애플리케이션을 간편하게 배포할 수 있습니다.

3.1 GCP 프로젝트 생성

GCP에 접속하여 새로운 프로젝트를 생성합니다. 다음 단계로 진행하기 전에 GCP에서 결제 계정을 설정해야 할 수도 있습니다.

3.2 Dockerfile 작성하기

FastAPI 애플리케이션을 컨테이너화하기 위해 Dockerfile을 작성합니다. 다음은 간단한 Dockerfile 예제입니다:


# 베이스 이미지 선택
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8

# 애플리케이션 디렉토리 설정
WORKDIR /app

# requirements.txt 복사
COPY requirements.txt .

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

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

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

3.3 requirements.txt 파일 작성

requirements.txt 파일은 다음과 같이 작성합니다:


fastapi
uvicorn
pydantic

3.4 Docker 이미지 빌드하기

Docker 이미지를 빌드하기 위해 다음 명령어를 실행합니다:

docker build -t my-fastapi-app .

3.5 GCP에 Docker 이미지 푸시

GCP의 Container Registry에 Docker 이미지를 푸시해야 합니다. 먼저 GCP에 로그인한 후, 다음 명령어를 실행하여 이미지 푸시를 진행합니다:


# GCP에 로그인
gcloud auth configure-docker

# 이미지 태깅
docker tag my-fastapi-app gcr.io/[PROJECT_ID]/my-fastapi-app

# 이미지 푸시
docker push gcr.io/[PROJECT_ID]/my-fastapi-app

3.6 Cloud Run에 배포하기

이제 Cloud Run을 통해 애플리케이션을 배포합니다. 다음 명령어를 사용하여 GCP Cloud Run에 배포합니다:


gcloud run deploy my-fastapi-app --image gcr.io/[PROJECT_ID]/my-fastapi-app --platform managed

배포가 완료되면 URL이 제공됩니다. 제공된 URL을 통해 FastAPI 애플리케이션에 접근할 수 있습니다.

4. 결론

이번 강좌에서는 FastAPI를 이용하여 기본적인 REST API 서버를 개발하고, 이를 Google Cloud Platform에 배포하는 방법을 알아보았습니다. FastAPI는 강력하고 사용하기 쉬운 웹 프레임워크로, GCP와의 통합을 통해 강력한 클라우드 기반 애플리케이션을 구축할 수 있습니다. 더 많은 기능과 고급 기술을 익히는 데 있어 FastAPI의 공식 문서를 참조해 보시기 바랍니다.

© 2023 FastAPI & GCP 배포 강좌. 모든 권리 보유.

FastAPI 서버개발, FastAPI에서 Jinja를 사용하는 방법

최근 몇 년간 웹 개발의 트렌드는 변화해왔으며, Python 언어의 인기도 그에 힘입어 나란히 증가하고 있습니다. FastAPI는 비동기 프로그래밍을 지원하는 현대적인 웹 프레임워크로, 성능과 사용 편의성을 모두 갖춘 특징을 가지고 있습니다. 본 강좌에서는 FastAPI를 이용하여 백엔드 서버를 개발하는 방법과 함께, Jinja 템플릿 엔진을 사용하여 동적인 HTML 페이지를 생성하는 방법에 대해 깊이 있게 다루어보겠습니다.

목차

  • 1. FastAPI 개요
  • 2. Jinja 템플릿 엔진 이해하기
  • 3. FastAPI와 Jinja 연동하기
  • 4. 실제 예제: 기본 FastAPI 서버 구축하기
  • 5. Jinja를 활용한 동적 HTML 페이지 생성하기
  • 6. 결론 및 향후 학습 방향

1. FastAPI 개요

FastAPI는 Python 3.6+부터 사용할 수 있는 웹 프레임워크로, RESTful API를 쉽게 개발할 수 있도록 도와줍니다. FastAPI는 다음과 같은 주요 특징들이 있습니다:

  • 자동 문서화: Swagger UI를 통해 API 문서를 자동으로 생성합니다.
  • 높은 성능: Starlette를 기반으로 하여 비동기 러닝을 지원합니다.
  • 타입 힌트: Python의 타입 힌트를 활용하여 코드의 가독성과 안전성을 향상시킵니다.

2. Jinja 템플릿 엔진 이해하기

Jinja는 Python에서 사용할 수 있는 가장 인기 있는 템플릿 엔진으로, HTML 페이지를 동적으로 생성하는 데 유용합니다. Jinja의 주된 기능은 다음과 같습니다:

  • 템플릿 상속: 기본 구조를 설정하고, 필요에 따라 자식 템플릿에서 이를 상속받아 사용할 수 있습니다.
  • 조건문 및 반복문 지원: Jinja는 데이터의 조건에 따라 HTML을 구성할 수 있는 기능을 제공합니다.
  • 필터 기능: 템플릿에서 데이터를 원하는 형태로 변환할 수 있는 다양한 필터를 제공합니다.

3. FastAPI와 Jinja 연동하기

FastAPI는 Jinja 템플릿 엔진과의 통합이 용이하여, HTML 페이지를 생성하는 데 필요한 설정이 간단합니다. 다음은 FastAPI와 Jinja를 연동하는 기본적인 방법입니다:

3.1. FastAPI 설치하기

pip install fastapi uvicorn jinja2

3.2. 기본 프로젝트 구조

프로젝트의 기본 폴더 구조는 다음과 같이 설정합니다:

  • /your_project
    • main.py
    • /templates
      • index.html

3.3. FastAPI 앱과 Jinja 설정하기

이제 FastAPI 애플리케이션을 설정하고 Jinja 템플릿 엔진을 등록해 보겠습니다:

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi import Request

app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

4. 실제 예제: 기본 FastAPI 서버 구축하기

이제 기본 FastAPI 서버를 구축하는 방법을 알아보겠습니다. 이전에 설정한 main.py 파일에 아래의 코드를 추가하면 됩니다:

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi import Request

app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

# 예외 처리
@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

위 코드는 FastAPI 애플리케이션을 설정하고, 두 개의 경로를 정의하는 작업을 수행합니다. 첫 번째 경로는 루트 경로이고, 두 번째 경로는 동적 경로로, 특정 item ID를 입력받아 해당 값을 JSON 형태로 반환합니다.

5. Jinja를 활용한 동적 HTML 페이지 생성하기

이제 Jinja 템플릿을 활용하여 HTML 페이지를 동적으로 생성해보겠습니다. templates/index.html 파일을 아래와 같이 생성합니다:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>FastAPI와 Jinja 예제</title>
</head>
<body>
    <h1>안녕하세요, FastAPI와 Jinja를 사용하여 동적으로 생성된 페이지입니다.</h1>
    <p>현재 접속한 경로: {{ request.url.path }}</p>
</body>
</html>

이 HTML 파일은 FastAPI에서 전달한 request 객체의 URL 경로를 출력합니다. 이제 FastAPI 서버를 실행하고 웹 브라우저에서 확인해보겠습니다:

uvicorn main:app --reload

이제 http://127.0.0.1:8000/ 에 접근할 수 있습니다. 위에서 설정한 HTML 페이지가 렌더링 되어 표시될 것입니다. 또한, /items/1와 같은 경로에 접근하면 JSON 형태로 아이템 ID를 확인할 수 있습니다.

6. 결론 및 향후 학습 방향

FastAPI와 Jinja 템플릿 엔진을 활용하여 동적인 웹 페이지를 쉽게 구축하는 방법에 대해 살펴보았습니다. FastAPI의 강력한 기능은 REST API 개발 뿐만 아니라 효율적인 웹 애플리케이션 작성에도 큰 도움을 줍니다. 향후 이 주제로 더 깊이 있는 학습을 원하신다면, 다음과 같은 주제를 고려해 보시기 바랍니다:

  • FastAPI의 OAuth2 및 JWT 인증
  • 데이터베이스와의 통합 (SQLAlchemy, Tortoise-ORM 등)
  • 비동기 작업 처리 (Celery 등)

최신 트렌드에 맞추어 FastAPI의 기능을 활용하여 더욱 발전하는 웹 개발자가 되어보시기 바랍니다!

FastAPI 서버개발, 로그인 라우트 변경

작성일: 2023년 10월 1일

소개

FastAPI는 현대의 웹 API를 빠르고 쉽게 개발할 수 있게 해주는 파워풀한 프레임워크입니다.
Python 3.6 이상을 지원하며, 자동 문서 생성, 데이터 검증, 비동기 프로그래밍 등 다양한 기능을 제공합니다.
이번 글에서는 FastAPI를 이용해 로그인 API를 만들고, 이후에 이를 변경하는 방법에 대해 상세히 설명하겠습니다.
우리는 기본적인 사용자 인증 로직을 구현한 후, 이를 안전하게 변경하는 방법에 대해 단계별로 살펴보겠습니다.

FastAPI 시작하기

FastAPI를 설치하기 위해서는 Python이 설치되어 있어야 합니다. 아래의 명령어를 터미널에 입력하여 FastAPI와 Uvicorn을 설치할 수 있습니다:

pip install fastapi uvicorn

설치가 완료되면, 아래와 같이 기본적인 FastAPI 애플리케이션을 생성할 수 있습니다:

from fastapi import FastAPI

app = FastAPI()

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

이 코드를 main.py라는 파일에 저장하고, 아래의 명령어를 통해 서버를 실행해볼 수 있습니다:

uvicorn main:app --reload

로그인 라우트 구현하기

이제 사용자가 이메일과 비밀번호를 통해 로그인할 수 있는 API 라우트를 구현해보겠습니다. 먼저, 사용자 정보를 저장하기 위한 간단한 데이터 모델을 만들어야 합니다.

from pydantic import BaseModel

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

다음으로, 로그인 API를 추가합니다:

@app.post("/login")
async def login(user: User):
    # 일반적으로 데이터베이스와의 상호작용이 필요합니다.
    fake_db = {"user@example.com": "hashed_password"}
    
    if user.email in fake_db and user.password == fake_db[user.email]:
        return {"message": "로그인 성공!"}
    return {"message": "잘못된 이메일 또는 비밀번호입니다."}

위 코드는 기본적인 로그인 검증을 수행하고, 성공 여부에 따라 다른 메시지를 반환합니다.

보안 강화

로그인 API의 보안을 강화하기 위해 비밀번호를 해싱하여 저장하면 사용자 정보를 보다 안전하게 보호할 수 있습니다. 비밀번호 해싱에는 bcrypt 라이브러리를 사용할 수 있습니다. 아래를 통해 설치합니다:

pip install bcrypt

그리고 아래와 같이 비밀번호를 해싱하고 확인하는 함수를 구현합니다:

import bcrypt

def hash_password(password: str) -> str:
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

def verify_password(plain_password: str, hashed_password: str) -> bool:
    return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))

로그인 라우트에서는 이제 해시된 비밀번호를 사용하여 비밀번호 확인을 수행합니다:

@app.post("/login")
async def login(user: User):
    fake_db = {"user@example.com": hash_password("securepassword")}
    
    if user.email in fake_db and verify_password(user.password, fake_db[user.email]):
        return {"message": "로그인 성공!"}
    return {"message": "잘못된 이메일 또는 비밀번호입니다."}

라우트 변경하기

이제 로그인 라우트를 변경하는 방법을 설명하겠습니다. 예를 들어, 사용자 인증을 JWT(JSON Web Token)를 통해 처리하도록 변경할 수 있습니다. JWT는 클라이언트와 서버 간의 안전한 통신을 가능하게 해주는 토큰 기반 인증 시스템입니다.

우선, 필요한 라이브러리인 pyjwt를 설치합니다:

pip install pyjwt

JWT 토큰을 생성하고 검증하는 유틸리티 함수를 만듭니다:

import jwt
from datetime import datetime, timedelta

SECRET_KEY = "your_secret_key"  # 안전하게 보관해야 합니다.
ALGORITHM = "HS256"

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

def verify_token(token: str):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except jwt.PyJWTError:
        return None

이제 로그인 라우트를 변경하여 JWT를 반환하도록 하겠습니다:

@app.post("/login")
async def login(user: User):
    fake_db = {"user@example.com": hash_password("securepassword")}
    
    if user.email in fake_db and verify_password(user.password, fake_db[user.email]):
        access_token = create_access_token(data={"sub": user.email})
        return {"access_token": access_token, "token_type": "bearer"}
    return {"message": "잘못된 이메일 또는 비밀번호입니다."}

토큰 인증을 위한 보호 라우트

이제 JWT를 사용한 보호 라우트를 추가해보겠습니다. 사용자가 로그인 후 발급받은 토큰을 통해 접근할 수 있는 API 엔드포인트를 만들어볼 것입니다.

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

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def get_current_user(token: str = Depends(oauth2_scheme)):
    payload = verify_token(token)
    if payload is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="유효하지 않은 토큰입니다.",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return payload

@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
    return current_user

위 코드는 사용자가 JWT를 통해 인증된 경우에만 사용자 정보를 반환하는 방법을 보여줍니다.

결론 및 요약

이 글에서는 FastAPI를 이용하여 로그인 API를 구현하고, 이를 JWT를 통해 변경하는 방법을 단계별로 설명했습니다. 보안이 중요한 현대의 웹 애플리케이션에서 사용자 인증은 필수적이며, FastAPI는 이를 간편하게 처리할 수 있는 다양한 기능을 제공합니다. 다음 단계로는 데이터베이스와의 연동, 사용자 등록 등의 기능을 추가하여 보다 복잡한 시스템을 구축하는 것일 수 있습니다.

FastAPI는 직관적이고 강력한 API 개발을 가능하게 하며, 다양한 라이브러리와의 통합으로 이를 더욱 확장할 수 있습니다. 이 글을 통해 FastAPI의 기능과 JWT를 활용한 인증 방법에 대한 이해가 깊어지기를 바랍니다.