📕 목차
1. What is Fast API
2. 설치
3. MySQL 연결
4. API 생성
1. What is Fast API
📌 Fast API
파이썬 3.6부터 제공하는 경량 프레임 워크라고 한다.
보통 파이썬에서 경량 프레임워크 하면 Flask, 보다 많은 기능이 필요하면 Django를 사용했는데
조작법도 단순하고 성능면으로 우수한 Fast API가 등장했다(고 한다)
📌 특징
- API 문서 자동 생성
- 의존성 주입 위주의 설계를 통한 DB 등에 대한 관리 용이
- 비동기 처리
- Pydantic을 사용한 유효성 검사
아래는 그냥 혼자 만져보면서 실습해본 내용.
파이썬으로 개발하는 게 오랜만이라 살짝 쫄았는데, 말도 안 되게 편하다.
장고랑 스프링 부트 쓰다가 Fast API 써보니 학습 곡선 찢어버리고 개발 생산성 극대화..
2. 설치
📌 가상환경 설치
python -m venv 가상환경_이름
source 가상환경_이름/Scripts/activate
예전에 장고했던 짬밥이 있어서, 바로 가상환경부터 만들어주고 시작.
이렇게 안 하면 프로젝트가 운영 환경이랑 자꾸 충돌한다.
📌 fastapi 설치
pip3 install fastapi
pip3 install uvicorn
uvicorn은 async/swait 기반의 비동기 프로그래밍을 지원해준다.
퍼포먼스가 가장 좋다고 알려진 ASGI라는데, 솔직히 대충 찾아봐서 거기까진 모르겠다.
📌 실행
root에 main.py를 만들고 대충 코드를 작성해주자.
import uvicorn
from fastapi import FastAPI
app = FastAPI()
if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
uvicorn main:app
위 명령어를 터미널에 입력해주면 실행이 된다.
3. MySQL 연결
📌 패키지 설치
python3 -m pip install sqlalchemy
python3 -m pip install pymysql
sqlalchemy는 파이썬 ORM 패키지 중 가장 많이 사용된다고 한다. (대충 주워온 내용이라 팩트 체크 안 함)
연결 정보를 수정하기 위해pymysql도 설치해주었다.
📌 config 작성
from pathlib import Path
from dotenv import load_dotenv
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(os.path.join(BASE_DIR, ".env"))
DB_URL = f'mysql+pymysql://{os.environ["DB_USERNAME"]}:{os.environ["DB_PASSWORD"]}@{os.environ["DB_HOST"]}:{os.environ["DB_PORT"]}/{os.environ["DB_NAME"]}'
class DatabaseConfig:
def __init__(self):
self.engine = create_engine(DB_URL, pool_recycle=500) # SQLAlchemy 엔진 초기화. 500초마다 재연결
def create_session(self): # 세션 생성. 데이터베이스에 대한 모든 쿼리 및 트랜잭션 처리를 위함
Session = sessionmaker(bind=self.engine, autocommit=False, autoflush=False)
session = Session()
return session
def connect_db(self): # 데이터베이스 연결
return self.engine.connect()
루트 디렉토리에 .env 파일을 만들고 환경 변수를 입력해준 다음, 해당 정보를 기반으로 DB_URL 상수를 만들었다.
클래스를 만들어서 연결 정보를 설정하는 게 좋은 건지는 잘 모르겠다.
사용해야 할 때마다 인스턴스를 만들어야 하는 건데..그럼 싱글톤으로 만들어야 하나.
참고로 .env 파일은 다음과 같이 작성하면 된다.
DB_USERNAME=hello
DB_PASSWORD=1q2w3e4r!
DB_HOST=localhost
DB_PORT=3306
DB_NAME=test
📌 User Entity 작성
# models/user.py
from sqlalchemy import Column, TEXT, INT, BIGINT, DATETIME, BOOLEAN, VARCHAR, CHAR
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(BIGINT, primary_key=True, autoincrement=True)
username = Column(VARCHAR, nullable=False)
name = Column(VARCHAR, nullable=False)
password = Column(VARCHAR, nullable=True)
password_updated_at = Column(DATETIME, nullable=True)
profile_image_url = Column(VARCHAR, nullable=True)
phone = Column(VARCHAR, nullable=False)
role = Column(CHAR, nullable=False)
profile_visibility = Column(CHAR, nullable=False)
locked = Column(BOOLEAN, nullable=False)
account_book_notify = Column(BOOLEAN, nullable=False)
feed_notify = Column(BOOLEAN, nullable=False)
chat_notify = Column(BOOLEAN, nullable=False)
created_at = Column(DATETIME, nullable=False)
updated_at = Column(DATETIME, nullable=False)
deleted_at = Column(DATETIME, nullable=True)
사실 나는 기존에 하던 프로젝트의 테이블을 가져왔다.
어차피 로컬이니까 괜찮겄지 뭐 허허
📌 인스턴스 생성
from config.database_config import DatabaseConfig
engine = DatabaseConfig()
session = engine.create_session()
나중에 세션을 사용해야 하는 곳에서 위와 같이 선언해놓고 시작하면 된다.
4. API 생성
📌 DTO
초간단 API를 만들기 전에 DTO를 만들어주자.
from pydantic import BaseModel
class UserInfo(BaseModel):
id: int
username: str
name: str
role: str
profile_visibility: str
phone: str
# 정적 팩토리 메서드
@staticmethod
def from_(user):
return UserInfo(
id=user.id,
username=user.username,
name=user.name,
role=user.role,
profile_visibility=user.profile_visibility,
phone=user.phone
)
변수명 앞에 `__`를 붙이면 private로 사용 가능한 건 알지만, 연습용으로 대충 만드는 거니까 무시했다.
지저분하게 생성자 쓰기 싫어서 정적 팩토리 메서드 하나 만들어줬다.
📌 API
from fastapi import FastAPI
from apis.user.user_api import user_req
app = FastAPI()
app.include_router(user_req)
`@app.get(...)`으로 만들어도 되지만, APIRouter가 재밌어보여서 써봤다.
# apis.user.user_api.py
from fastapi import APIRouter, status
from typing import List, Dict, Any
from config.database_config import DatabaseConfig
from models.user import User
from schemas.user_dto import UserInfo
engine = DatabaseConfig()
session = engine.create_session()
user_req = APIRouter(prefix='/users')
@user_req.get(path = "", tags=['user'], status_code=status.HTTP_200_OK, response_model=List[UserInfo])
async def getUsers() -> List[UserInfo]:
users = session.query(User).all()
user_dto = []
for user in users:
user_dto.append(UserInfo.from_(user))
return user_dto
접두사로 `/users` 넣어주고 getter 메서드 빠르게 만들어주었다.
Fast API는 스웨거 문서를 알아서 만들어주더라....미쳤당. 그래서 어노테이션 안에 설명도 열심히 넣어봤다.
📌 요청 해보기
엄청나게 빠른 개발이 가능하다..
생각보다 너무 재밌는데, 이거나 공부해볼까
Python이 오랜만이라 컨벤션 찾아가면서 작성하느라 시간이 좀 걸렸지, 순수 코드 작성은 처음 만져보는데 불구하고 10분 정도밖에 안 걸렸다.