FastAPI 서버개발, aiomysql 설치

FastAPI는 파이썬으로 작성된 현대적인 웹 프레임워크로, APIs를 빠르게 구축하고 문서화하는 데 있어 효율성을 제공합니다. 이 글에서는 FastAPI를 사용하여 백엔드 서버를 개발하는 방법과 함께 비동기 MySQL 데이터베이스 클라이언트인 aiomysql의 설치 및 활용 방법에 대해 알아보겠습니다.

1. FastAPI 소개

FastAPI는 비동기 지원을 제공하며, Starlette 및 Pydantic을 기반으로 개발되었습니다. 이 프레임워크의 가장 큰 장점 중 하나는 데이터 검증 및 직렬화가 자동으로 이루어진다는 점입니다. 이는 개발자가 API를 개발하는 데 드는 시간을 크게 단축시켜 줍니다.

1.1 FastAPI의 주요 특징

  • 비동기 지원: 매우 빠른 성능을 제공합니다.
  • 자동 API Documentation: Swagger와 ReDoc을 통해 문서화가 자동으로 이루어집니다.
  • 데이터 검증: Pydantic을 사용해 데이터 검증이 자동으로 이루어집니다.
  • 의존성 주입: 쉽게 의존성을 설정하고 관리할 수 있습니다.

2. FastAPI 설치

FastAPI를 설치하기 위해서는 pip를 사용하여 간단히 설치할 수 있습니다. 다음 명령어를 입력해 설치해 주세요:

pip install fastapi[all]

3. 기본 FastAPI 애플리케이션 만들기

FastAPI를 설치한 후, 기본 애플리케이션을 만들어 보겠습니다. 아래 예제 코드를 사용하여 main.py라는 파일을 생성하고, 다음 코드를 붙여 넣습니다:

from fastapi import FastAPI

app = FastAPI()

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

위 코드는 기본 FastAPI 애플리케이션을 설정하는 코드로, 루트 endpoint에 GET 요청을 보내면 {"Hello": "World"}라는 JSON 응답을 반환합니다. FastAPI 서버를 실행하려면 다음 명령어를 터미널에 입력하세요:

uvicorn main:app --reload

여기서 --reload 옵션은 코드 변경 시 서버를 자동으로 재시작해 주는 기능을 제공합니다. 서버가 실행되면 http://127.0.0.1:8000 주소에서 애플리케이션을 확인할 수 있습니다.

4. aiomysql 설치

이제 FastAPI 애플리케이션에 MySQL 데이터베이스를 연결하기 위해 aiomysql을 설치해 보겠습니다. aiomysql은 asyncio 기반의 MySQL 클라이언트로, 비동기적으로 MySQL과 상호작용할 수 있도록 해줍니다. aiomysql을 설치하기 위해 아래 명령어를 실행합니다:

pip install aiomysql

5. MySQL 데이터베이스 설정

설치가 완료되면 MySQL 서버를 준비해야 합니다. MySQL 서버를 실행하고, 아래 명령어를 사용하여 새 데이터베이스를 생성합니다:

CREATE DATABASE fastapi_db;

5.1 데이터베이스 테이블 생성

데이터베이스 안에 사용할 테이블을 생성해보겠습니다. 예를 들어 Users라는 테이블을 생성하고, 사용자 정보를 저장해보겠습니다:

CREATE TABLE Users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        email VARCHAR(100) NOT NULL UNIQUE
    );

6. FastAPI와 aiomysql 통합

이제 FastAPI 애플리케이션에서 MySQL에 연결해 보겠습니다. 아래 코드는 FastAPI와 aiomysql을 사용하여 데이터베이스에 연결하고, 데이터를 삽입하고 조회하는 기본적인 API를 만드는 방법을 보여줍니다. 아래 코드를 main.py에 추가하세요:

import aiomysql
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional

app = FastAPI()

# MySQL 데이터베이스 연결 설정
DB_CONFIG = {
    "host": "localhost",
    "port": 3306,
    "user": "your_username",
    "password": "your_password",
    "db": "fastapi_db"
}

# 데이터 모델 정의
class User(BaseModel):
    name: str
    email: str

# 비동기 함수: 데이터베이스 연결
async def get_db_connection():
    conn = await aiomysql.connect(**DB_CONFIG)
    return conn

# 사용자 추가
@app.post("/users/", response_model=User)
async def create_user(user: User):
    conn = await get_db_connection()
    async with conn.cursor() as cursor:
        await cursor.execute("INSERT INTO Users (name, email) VALUES (%s, %s)", (user.name, user.email))
        await conn.commit()
        user_id = cursor.lastrowid
    conn.close()
    return {**user.dict(), "id": user_id}

# 사용자 목록 조회
@app.get("/users/", response_model=List[User])
async def read_users():
    conn = await get_db_connection()
    async with conn.cursor(aiomysql.DictCursor) as cursor:
        await cursor.execute("SELECT * FROM Users")
        result = await cursor.fetchall()
    conn.close()
    return result
    

6.1 API 테스트

이제 FastAPI 애플리케이션을 다시 실행한 후 API를 테스트해보세요. 예를 들어, 사용자 추가를 위해 다음과 같은 POST 요청을 보낼 수 있습니다:

curl -X POST "http://127.0.0.1:8000/users/" -H "Content-Type: application/json" -d "{\"name\": \"John\", \"email\": \"john@example.com\"}"

이 후, 사용자 목록 조회를 위해 다음 GET 요청을 보낼 수 있습니다:

curl -X GET "http://127.0.0.1:8000/users/"

7. 에러 핸들링

FastAPI에서의 에러 핸들링은 매우 간단합니다. 예를 들어, 사용자가 이메일을 중복해서 추가하려 할 경우를 처리하기 위한 기능을 추가해 보겠습니다:

from fastapi import HTTPException

@app.post("/users/", response_model=User)
async def create_user(user: User):
    conn = await get_db_connection()
    async with conn.cursor() as cursor:
        await cursor.execute("SELECT * FROM Users WHERE email = %s", (user.email,))
        existing_user = await cursor.fetchone()
        if existing_user:
            raise HTTPException(status_code=400, detail="Email already registered")
        await cursor.execute("INSERT INTO Users (name, email) VALUES (%s, %s)", (user.name, user.email))
        await conn.commit()
        user_id = cursor.lastrowid
    conn.close()
    return {**user.dict(), "id": user_id}
    

8. 마치며

FastAPI는 간단하면서도 매우 강력한 웹 프레임워크입니다. aiomysql을 통해 비동기적으로 MySQL과 연결하는 방법을 배웠습니다. 이를 통해 데이터를 효율적으로 관리하고 빠른 성능을 구현할 수 있습니다. 추가적으로, FastAPI의 다양한 기능(예: 의존성 주입, 더 복잡한 데이터 모델 등)을 탐구하며 더 발전된 애플리케이션을 만들어보길 바랍니다.

감사합니다!