flask๋ฅผ ์จ๋ดค๋ค๋ฉด ์กฐ๊ธ ์ต์ํ ์๋ ์๋ค.
์์ ์ฐธ๊ณ
https://github.com/tiangolo/full-stack-fastapi-template
๋์ ๊ฒฝ์ฐ์๋ ๋ค์๊ณผ ๊ฐ์ด ์งฐ๋ค.
.
โโโ app
โ โโโ __init__.py
โ โโโ main.py
โ โโโ database.py
โ โโโ models.py
โ โโโ schemas.py
โ โโโ crud.py
โ โโโ routers -(๊ฐ์ข
๋ผ์ฐํฐ๋ค)
โ โโโ __init__.py
โ โโโ japanese.py
โ โโโ known.py
โโโ tests
โ โโโ __init__.py
โ โโโ test_database.py
โ โโโ test_main.py
โโโ requirements.txt
โโโ .env
โโโ README.md
- requirements.txt
์ผ๋จ ๊ฐ์ํ๊ฒฝ์ ์์ฑํ ํ, ํ์ํ ํจํค์ง๋ค์ ์ค์นํ๋ค.
์ด๋ค์ requirements.txt๋ก ๊ด๋ฆฌํ๋ค
fastapi
uvicorn
sqlalchemy
mysqlclient
python-dotenv
pydantic
- FastAPI์ ํจ๊ป MySQL์ ์ฌ์ฉํ๋ ค๋ฉด, mysqlclient๋ aiomysql ๊ฐ์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋๋ผ์ด๋ฒ๊ฐ ํ์ํฉ๋๋ค. python-dotenv๋ ํ๊ฒฝ ๋ณ์๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค. SQLAlchemy๋ ORM์ ์ ๊ณตํฉ๋๋ค.
- .env
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ํ์ํ ์ ๋ณด๋ฅผ ์ ์ฅ
DATABASE_URL=mysql://user:password@localhost/dbname
์ฃผ์ ๊ตฌ์ฑ ์์ ์ค๋ช
- "app" ํด๋๋ ๋ชจ๋ ์์ค ์ฝ๋๋ฅผ ํฌํจํฉ๋๋ค.
- app/main.py: FastAPI ์ฑ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ๋ผ์ฐํฐ๋ฅผ ํฌํจํ๋ ํ์ผ์ ๋๋ค. ์ด ํ์ผ์์ ์ฑ ์ค์ ์ ์งํํฉ๋๋ค.
- app/database.py: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ๊ณผ ์ธ์ ๊ด๋ฆฌ๋ฅผ ์ํ ์ค์ ์ ํฌํจํฉ๋๋ค. SQLAlchemy๋ฅผ ์ฌ์ฉํ๋ ์์์ ๋๋ค.
- app/models.py: ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ SQLAlchemy ๋ชจ๋ธ๋ก ์ ์ํฉ๋๋ค. ์ด ์์์์๋ japanese ๋ฐ known ํ ์ด๋ธ์ ํด๋นํ๋ ๋ชจ๋ธ์ ์ ์ํฉ๋๋ค.
- app/schemas.py: ํด๋ผ์ด์ธํธ์์ ๋ฐ์ดํฐ ๊ตํ์ ์ฌ์ฉ๋๋ Pydantic ๋ชจ๋ธ(์คํค๋ง)์ ์ ์ํฉ๋๋ค. ์์ฒญ ๋ฐ ์๋ต ์คํค๋ง๋ฅผ ์ ์ํ๋ ๊ณณ์ ๋๋ค.
- app/crud.py: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ CRUD ์ฐ์ฐ์ ์ํํ๋ ํจ์๋ค์ ์ ์ํฉ๋๋ค. ์ด ํจ์๋ค์ ์ผ๋ฐ์ ์ผ๋ก ๋ชจ๋ธ๊ณผ ์คํค๋ง๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ํธ์์ฉ์ ์บก์ํํฉ๋๋ค.
- app/routers/: ๊ฐ ๊ธฐ๋ฅ๋ณ๋ก ๊ฒฝ๋ก ์ฐ์ฐ์ ๋๋์ด ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ผ์ฐํฐ ํ์ผ๋ค์ ํฌํจํ๋ ๋๋ ํ ๋ฆฌ์ ๋๋ค. ์๋ฅผ ๋ค์ด, japanese ๊ด๋ จ ๊ฒฝ๋ก๋ japanese.py์, known ๊ด๋ จ ๊ฒฝ๋ก๋ known.py์ ์ ์ํฉ๋๋ค.
- tests/: FastAPI ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธ ์ฝ๋๋ฅผ ํฌํจํ๋ ๋๋ ํ ๋ฆฌ์ ๋๋ค. ์ฌ๊ธฐ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ํ ์คํธ, API ์๋ํฌ์ธํธ ํ ์คํธ ๋ฑ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
- requirements.txt: ํ๋ก์ ํธ์ ํ์ํ Python ํจํค์ง ๋ชฉ๋ก์ ๋๋ค. ์๋ฅผ ๋ค์ด, fastapi, uvicorn, pydantic, SQLAlchemy, mysql-connector-python ๋ฑ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
- database.py
MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๋ ์ฝ๋์ ๋๋ค. SQLAlchemy create_engine ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ง์ ์์ฑํ๊ณ , SessionLocal ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ์ ์ ๊ด๋ฆฌํฉ๋๋ค.
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os
from dotenv import load_dotenv
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
- models.py
๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ์ SQLAlchemy ORM์ ์ฌ์ฉํ์ฌ ์ ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, Japanese์ Known ํ ์ด๋ธ์ ์ ์ํ ์ ์์ต๋๋ค.
from sqlalchemy import Column, Integer, String, Date
from .database import Base
class Japanese(Base):
__tablename__ = "japanese"
id = Column(Integer, primary_key=True, index=True)
word = Column(String, index=True)
meaning = Column(String)
class Known(Base):
__tablename__ = "known"
id = Column(Integer, primary_key=True, index=True)
word_id = Column(Integer, index=True)
review_date = Column(Date)