์์ธํ ์ฝ๋๋ ์ ํ ํฌ API๋ฅผ ์ฐธ๊ณ ํ์๊ธธ ๋ฐ๋๋๋ค.
๊ธฐ๋ณธ์ ์ธ ๋ด์ฉ์ ์ ํ ํฌ Fastapi์ ๋ด์ฉ์ ๊ณต๋ถํ๋ฉฐ ์๊ฒ ๋ ๋ด์ฉ๋ค์ ์ค๋ช ํ๋ค. ๊ตฌ๊ธ์ ๊ฒ์ํ์ฌ ๊ณต๋ถํด๋ณด๋ฉด ์๊ฒ ์ง๋ง, ํผ์์ ๋ฐ๋ผํ ์ ์์ผ๋ฉฐ, ์์ฑ๋ ์ฝ๋๋ค์ด ์ฃผ์ด์ง๋ค๋ ์ ์์, ๊ฒฐ๊ณผ๋ฌผ์ ๋น ๋ฅด๊ฒ ๋ณผ ์ ์๋ ์ฅ์ ์ด ์๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ์ฑ ์ ๋์ค๋ ์ฃผ์ ์ ๊ตญํํ์ฌ ๊ฐ๋ฐ์ ํ ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์, ๊ธฐ๋ฅ๋ค์ด ์ผ๋ง๋ ๋ฒ์ฉ์ฑ ์๊ฒ ์ฐ์ผ ์ ์๋์ง๋ฅผ ๋ณด์์ผํ๊ณ , FLASK์์ ์๋์ฐจ์ด๊ฐ ๋งค์ฐ ์ ์๋ฏธํ ์ ๋๋ก ๋๊ธฐ ๋๋ฌธ์, ์ด๋ ๋ถ๋ถ์์ ์ด ํ๋ ์์ํฌ๊ฐ ํจ์จ์ ์ธ ์์ ์ ๋ณด์ฌ์ฃผ๋์ง, ์ด๋ ๋ถ๋ถ์์ ๋ถํธํ์ง๋ฅผ ์ธ์งํ๋ฉด, ๊ธฐ์กด์ ๋ง๋ค์๋ FLASK ๊ฐ์ธ ํ๋ก์ ํธ์ ๋ํ ์ฌ๊ตฌ์ฑ์ ํ๋๋ฐ ๋์์ด ๋ ๊ฒ ๊ฐ๋ค.
ํด๋น ํฌ์คํ ์ ์์ฑํ๋ฉฐ, ์๊ณ ์ถ์ ๋ถ๋ถ๋ค์, ์ด์ ํฌ์คํ ์์ flask๋ก ํ์๊ฐ์ ํผ์ ์์ฑํ์๋ ๊ธฐ๋ฅ๋ค์ Fastapi๋ก ์ด๋ป๊ฒ ๊ตฌํํ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ด๋ค ๊ธฐ๋ฅ๋ค์ด ์ด๋ค ์ญํ ์ ํ๊ณ ์๋์ง์ ์ค์ ์ ๋๊ณ ์์ฑํ์๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ํ์๊ฐ์ ํผ์ด ์ด๋ค ์๋ฆฌ๋ก ์๋ํ๊ณ , ์นํ์ด์ง์ ์ํธ์์ฉํ๋ฉฐ, ํ์ํ ๋ฐ์ดํฐ๋ค์ ๋ฌด์์ด๊ณ , ์ฒ๋ฆฌ๊ณผ์ ์์ ์ด๋ค ๊ฒ๋ค์ ๊ฒ์ฌํ์ฌ์ผ ํ๋์ง์ ๋ํ ์ฌ์ ์ ๋ณด๊ฐ ์์ผ๋ฉด ํด๋น๊ธ์ ์ดํดํ๋๋ฐ ๋์์ด ๋ ๊ฒ์ด๋ค. Flaks ์ Fastapi๋ ๋น์ทํ ์ ์ด ๊ต์ฅํ ๋ง๋ค๋ ์ ์ ์ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
์ด๋ฆ๋ถํฐ ๊ต์ฅํ ๋น ๋ฅด๋ค๊ณ ๋งํด์ค๋ค. ๋ง๋ค. ๋งค์ฐ ๋น ๋ฅด๋ค. ์๋๊ฐ ๋๋ฆฐ๊ฒ ๋จ์ ์ด๋ผ๊ณ ๋ฌธ์ ๋ฅผ ์ง์ ๋ฐ๋ ํ์ด์ฌ์ ์ ์ฅ์์ ์ด๊ฒ์ ํ์ ์ ์ธ ๋ด์ฉ์ด ์๋ ์ ์๋ค. ์ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํด๋ ๋์ค๊ฒ ์ง๋ง, ๊ธฐ๋ณธ์ ์ธ ์๋๋ ๋ด๊ฐ ์ฌ์ฉํ๋ flask์ ๋๋ฐฐ๋ ์๋๊ณ ๋ช ๋ฐฐ๋ค ๋ช ๋ฐฐ. ๊ต์ฅํ ๋ง์ด ์ฐจ์ด๊ฐ ๋๊ธฐ๋ ํ๊ณ , flask์ ์ ์ฌํ๋ค๋ผ๋ ์ ์์ ๊ณต๋ถ๋ฅผ ํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ ํฌ์คํ ์ ํ๊ฒ ๋์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก FastAPI import
๋ flaks
์์ Flask import
ํ๋๊ฑฐ๋ ๋๊ฐ๋ค๊ณ ๋ณด๋ฉด๋๋ค.
from fastapi import APIRouter, Depends, HTTPException, FastAPI
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from starlette import status
from database import get_db
from domain.question import question_schema, question_crud
# ์ผ๋จ ์ํฌํธ ๊ด๋ จ ์๋ฌ ๋ฐ์ค๋๋๊ฑด ๋ค๋ฌด์ํ๋ฉด ๋ ๋ฏ
router = APIRouter(
prefix="/api/question",
)
# ๋ผ์ฐํ
์ด๋ FastAPI๊ฐ ์์ฒญ๋ฐ์ URL์ ํด์ํ์ฌ ๊ทธ์ ๋ง๋ ํจ์๋ฅผ ์คํํ์ฌ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๋ ํ์๋ฅผ ๋งํ๋ค.
'''
db: Session ๋ฌธ์ฅ์ ์๋ฏธ๋ db ๊ฐ์ฒด๊ฐ Session ํ์
์์ ์๋ฏธ
FAST API์ Depends๋ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ฐ์ ํจ์๋ฅผ ์คํ์ํจ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๋ค. db ๊ฐ์ฒด์๋ get_db ์ ๋ค๋ ์ด์
์ ์ํด ์์ฑ๋
๊ฐ์ฒด๊ฐ ์ฃผ์
๋๋ค. get_db ํจ์์ ์๋์ผ๋ก contextmanager๊ฐ ์ ์ฉ๋๊ธฐ ๋๋ฌธ์(Depends์์ ์ ์ฉํ๊ฒ๋ ์ค๊ณ๋์ด์๋ค) database์
get_db ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฉํ (@contextlib.contextmanager ์ด๋
ธํ
์ด์
์ ์ ๊ฑฐํด์ผํ๋ค)
--
@router.get ์ด๋
ธํ
์ด์
์ response_model ์ถ๊ฐ
question_list ํจ์์ ๋ฆฌํด ๊ฐ์ Question schema๋ก ๊ตฌ์ฑ๋ ๋ฆฌ์คํธ์์ ๋ปํ๋ค.
'''
@router.get("/list", response_model=list[question_schema.Question])
def question_list(db: Session = Depends(get_db)):
# ์ค๋ฅ ์ฌ๋ถ์ ์๊ด์์ด with๋ฌธ์ ๋ฒ์ด๋๋ ์๊ฐ db.close()๊ฐ ์คํ๋๋ฏ๋ก ๋ณด๋ค ์์ ํ ์ฝ๋๋ก ๋ณ๊ฒฝ๋ ๊ฒ์ด๋ค.
_question_list = question_crud.get_question_list(db)
return _question_list
@router.get("/detail/{qeustion_id}", response_model=question_schema.Question)
def question_detail(question_id: int, db: Session = Depends(get_db)):
question = question_crud.get_question(db, question_id=question_id)
return question
@router.post("/create", status_code=status.HTTP_204_NO_CONTENT)
def question_create(_question_create: question_schema.QuestionCreate,
db: Session = Depends(get_db)):
question_crud.create_question(db=db, question_create=_question_create)
Flask
์์๋ blueprint
๋ฅผ ์ฌ์ฉํ์ฌ, ๋ผ์ฐํ
์ ๊ตฌ๋ถํ๊ณ , ๋ฉ์ธ ์ฑ์ผ๋ก ํด๋น๊ธฐ๋ฅ์ ๋ถ๋ฌ์์ ์ฌ์ฉํ๋๋ฐ, ๊ทธ ๊ธฐ๋ฅ๋ค์ fastapi์์๋ router
๋ฅผ ์ด์ฉํด์ ์กฐ์ ์ด ๊ฐ๋ฅํ๋ค. ๋ณ๋์ ์ด๋ฆ์ง์ ๋ ํ์ ์์ด, url_prefix
๊ธฐ๋ฅ๋ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ต์ฅํ ํธ๋ฆฌํ ๊ฒ ๊ฐ๋ค. (ํด๋น ๊ธฐ๋ฅ์ ๋ํ ๋ด์ฉ์ flask์ค๋ช
๋ถ๋ถ์ ๋์์์ผ๋ ์ฐธ์กฐํ๋๋ก ํ์). blueprint ๋ฒํผ ๋ถ๋ฌ์ค๋ ๊ฒ์ ๊ตฌ๋ถํ ํ์ ์์ด, ๋ฉ์ธํจ์์์ inlcude_router
๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๋๋ ์ฐธ์กฐํ๋๋ก ํ์.
์์คํ ์ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ํน๋ณํ ๋๊ตฌ์ด๋ค. ์์กด์ฑ ์ฃผ์ ์ ํจ์๋ ํด๋์ค ๋ฉ์๋์ ๋ค๋ฅธ ๊ฐ์ฒด, ํจ์ ๋๋ ํด๋์ค๋ฅผ ์ฃผ์ ํ์ฌ ์ฝ๋๋ฅผ ๋ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์์กด์ฑ์ ๊ด๋ฆฌํ๋ ๋ฐ ๋์์ ์ค๋ค.
์๋๋ FastAPI ๊ณต์๋ฌธ์ ์์์ฝ๋์ด๋ค.
from typing import Union
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(
q: Union[str, None] = None, skip: int = 0, limit: int = 100
):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
async๋ ๋น๋๊ธฐ ๋ผ๋ ๊ฒ์ธ๋ฐ, ํด๋น ๊ฐ๋
์ ์ง๊ธ ์ค์ํ๊ฒ ์๋๋ฏ๋ก ๋๊ฒจ๋๋๋กํ์.
Depends์ ๋ํ ์ดํด:
๊ฒ์์ ์๋ก ๋ค์ด๋ณด์. ์๋ฅผ ๋ค์ด, A๋ผ๋ ์คํฌ์ ์ฐ๊ธฐ ์ํด์๋ ๋ฐ๋์ B๋ผ๋ ์คํฌ์ด ์ ํ๋์ด์ผํ๊ณ , ๋ด๊ฐ ๊ฐ์ง ์คํฌ์ ๋งค์ฐ๋ง๋ค.
๋ง์ฝ Depends
๋ฅผ ์ฌ์ฉํ์ง ์์๋ค๋ฉด, A๋ผ๋ ๊ธฐ์ ์ ์ฌ์ฉํ๊ธฐ ์ํด, ์ผ์ผ์ด B์คํฌ์ ์ปค๋งจ๋๋ฅผ ์
๋ ฅํด์ผํ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ Depends
๋ฅผ ํตํด, A ๊ธฐ์ ์ B ๊ธฐ์ ์ ์์กด์ํค๋ฉด, ๋ด๊ฐ A ๊ธฐ์ ์ ์ฌ์ฉํ์ ๋, ์์์ B ๊ธฐ์ ์ด ๋๊ฐ๊ณ A ๊ธฐ์ ์ด ๋๊ฐ๋ ๊ฒ์ด๋ค.
B A B A B A ์์๋๋ก ์ฐ๋ ์ด๋ฐ ๋ถํ์ํ ์์
๋ค์ Depends
์ ์ํด
A A A A๋ก ๋ฐ๋๋ ๊ฒ์ด๋ค. ์ด ์ผ๋ง๋ ํธ๋ฆฌํ๊ฐ??
๋ณ๊ฑฐ ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ์ง๋ง, ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์ ์๊ฐ๋ณด๋ค ๋ช๊ฐ์ง ์๋๋ ์ ์ ์ ์ ๋ณด๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉํด์ผํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ์ ์ฉํ๋ค๋ ๊ฒ์ด๋ค.
์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉํ๋ ๋์ค, ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ํด๋น ์ค๋ฅ์ฝ๋์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๋์์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค.
Copy code
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 42:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
๋ง์ฝ ์ ๋ ฅ๋ฐ์ item_idrk 42์ผ ๊ฒฝ์ฐ์ 404 ์ํ์ฝ๋์ "Item not found"๋ฌธ๊ตฌ๊ฐ ํจ๊ป ํด๋ผ์ด์ธํธ๋ก ๋ฐํ์ด ๋๋ค.
ํด๋น ์์ ์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ฝ๋๋ก sqlalchemy์ sqlalchemy.orm์ ์ฌ์ฉํ์๋ค.
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์์ฃผ์
SQLALCHEMY_DATABASE_URL = 'sqlite:///./myapi.db'
'''
create_engine sessionmaker ๋ ๋ฐ๋ผ์ผํ ์ ํด์ง ๊ท์น์ด์ง๋ง
autocommit์ ์ ์์์ผํ๋ค. autocommit=False ๋ผ๊ณ ์ ์ฅํ๋ฉด
commit์ด๋ผ๋ ์ฌ์ธ์ ์ค ๋๋ง ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ค. ๊ทธ๋ฆฌ๊ณ rollback์ด ๊ฐ๋ฅํ๋ค.
auto commit=True ์ผ ๊ฒฝ์ฐ์๋ rollback ์ ์๋ํ์ง ์๋๋ค
'''
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# base ํด๋์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ ์์ฑ์ ์ธ ๊ฐ์ฒด์ด๋ค.
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
SQLAlchemy์์ ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๋๋ฐ ์ฌ์ฉ๋๋ ํจ์. ๋ฐ์ดํฐ๋ฒ ์ด์ค URL์ ์ธ์๋ก ๋ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฐ๊ฒฐํ๊ณ ์ํธ์์ฉํ๋ ์ญํ ์ ํ๋ค. ํ๋ง๊ณผ ์ค๋ ๋ฉ๋ฑ ๊ณ ๊ธ ์ค์ ์ ์ง์ํ๋ค.
SQLAlchemy์ ORM(Object-Relational Mapping)์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ์ ์ ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค. declarative_base ํจ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ์ ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์์ฑ, ์ด ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์์ํ์ฌ ์ ์ํ๊ณ ์ด๋ฅผ ํตํด ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ ํด๋์ค๋ฅผ ์์ฑํ ์ ์๋ค.
ORM ์ ๊ฒฝ์ฐ SQL๋ฌธ๋ฒ์ ๋ฐฐ์ฐ์ง ์์๋ ๋๋ค๋ ์ฅ์ ์ด ์๋ค. ํ์ง๋ง ์ฅ์ ์ด ์์ผ๋ฉด ๋จ์ ๋ ์๊ฒ ์ฃ ? ใ ใ
Session = sessionmaker(bind=engine)
bind์ engine์ ์ด๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฐ๊ฒฐํ ์ง ์ ํ๋ ๋ถ๋ถ์ด๊ณ sessionmaker
๋ฅผ ํตํด, ์ธ์
๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ค.
session
์ ๋ฐ์ดํฐ ๋ฒ ์ด์ค์ ํธ๋์ญ์
์ ๋ํ๋ด๋ ๊ฐ์ฒด์ด๋ค. ํด๋น sessionmaker๋ก ๋ง๋ค์ด์ง ๊ฒ์ ์ธ๋ ค๋ฉด
session = Session()
์ฒ๋ผ ์ ์ธํด์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๋ฉด ๋๋ค.
session์ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๋ ๋ฑ์ ์ฌ๋ฌ๊ฐ์ง ๊ธฐ๋ฅ๋ค์ ํ ์ ์๋ค.
BaseModel
์ ๋ชจ๋ธ์ ์ ์ํ ๋ ์ฌ์ฉ๋๋ค. ์ด๋ฅผ ์์ํ๊ณ ํ๋๋ฅผ ํด๋์ค ๋ณ์๋ก ์ ์ธํ๋ค. ๋ฐ์ดํฐ ๋ชจ๋ธ ํ๋์ ํ์
ํํธ์ ๊ธฐ๋ณธ ๊ฐ ์ค์ ์ด ๊ฐ๋ฅํ๋ค
from pydantic import BaseModel
class User(BaseModel):
username: str
email: str
์๋ง๋ c๋ c++ ์จ๋ดค๋ ์ฌ๋๋ค์ ์ต์ํ ๋งํ ์๋ฃํ ์ ์ธ๋ค์ ํ ์ ์๋ค.
@validator
๋ฐ์ฝ๋ ์ดํฐ ํ์์ผ๋ก ์ ์ธํ์ฌ, ๋ฐ์ดํฐ ๋ชจ๋ธ ํ๋์ ๋ํด ์ฌ์ฉ์ ์ง์ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ๊ฐ๋ฅํ๋ค.
from pydantic import BaseModel, validator
class User(BaseModel):
username: str
email: str
@validator('email')
def validate_email(cls, value):
if not value.endswith('@example.com'):
raise ValueError('์ด๋ฉ์ผ ์ฃผ์๋ example.com ๋๋ฉ์ธ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.')
return value
@validator('email')
๋ฐ์ฝ๋ ์ดํฐ๋ email ํ๋์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ ๊ท์น์ ์ ์ํ๋ฉฐ, ์ด๋ฉ์ผ ์ฃผ์๊ฐ example.com ๋๋ฉ์ธ์ผ๋ก ๋๋์ง ์์ผ๋ฉด ์์ธ๋ฅผ ๋ฐ์์ํค๋ ์ญํ ์ ํ๊ณ ์๋ค.
cls
๋ ํด๋์ค ์์ฒด, value
๋ email ํ๋์ ํ ๋น๋ ๊ฐ์ ๋งํ๋ค.
ํ์ฌ ์์์์๋
ํด๋์ค๋ User๊ฐ ๋๋ ๊ฒ์ด๊ณ value๋ email ํ๋์ ๋ค์ด์๋ ๊ฐ์ด๋ค. value๋ฅผ ํตํด ์ ํจ์ฑ ์์
์ด ์ด๋ฃจ์ด์ง๋ค.
์ด ๋ ์ ๋๋ฌธ์ ์ ์ข ๋จน์๋ค. ์ ๋๋ก ์ดํดํ์ง ์๊ณ ๊ฐ๋ค๋ฉด, ํ์ FastAPI๋ก ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ์งํํ ๋ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ ๋ถ๋ถ์ผ ๊ฒ ๊ฐ๋ค. ๋์ํ๋ url๊ณผ ๊ด๋ จํ ๋ฏผ๊ฐํ ๋ถ๋ถ์ด๋ค.
์ฐ์ ์์์ฝ๋์ด๋ค.
from starlette.middleware.cors import CORSMiddleware
from starlette import status
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # ๋ณํ(*)๋ ๋ชจ๋ ๋๋ฉ์ธ์์์ ์์ฒญ์ ํ์ฉ
allow_credentials=True, # ์๊ฒฉ ์ฆ๋ช
์ ๋ณด (์: ์ฟ ํค, ์ธ์ฆ)๋ฅผ ํ์ฉ
allow_methods=["*"], # ๋ชจ๋ HTTP ๋ฉ์๋ ํ์ฉ
allow_headers=["*"], # ๋ชจ๋ HTTP ํค๋ ํ์ฉ
expose_headers=["Content-Disposition"], # ๋ธ๋ผ์ฐ์ ์ ๋
ธ์ถํ ํค๋ ์ง์
)
@app.post("/api/some_endpoint", status_code=status.HTTP_201_CREATED)
async def create_resource():
# ์ฌ๊ธฐ์ ์์ ์์ฑ ๋
ผ๋ฆฌ๋ฅผ ๊ตฌํ
return {"message": "Resource created successfully"}
CORSMiddleware
:
Cross-Origin Resource Sharing (CORS)๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฏธ๋ค์จ์ด์ด๋ค.
CORS๋ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ค๋ฅธ ๋๋ฉ์ธ์ผ๋ก๋ถํฐ์ HTTP ์์ฒญ์ ํ์ฉํ๋๋ก ํ๋ ๋ณด์ ๊ธฐ๋ฅ์
๋๋ค. ์ฆ, ์น ์ ํ๋ฆฌ์ผ์ด์
์ด ์๋ก ๋ค๋ฅธ ๋๋ฉ์ธ์ ์์์ ์์ฒญํ ๋ ๋ธ๋ผ์ฐ์ ์์ ๋ณด์ ์ ์ฑ
์ ์ค์ํ๋๋ก ๋๋ ๊ธฐ๋ฅ์ ํ๋ค. ์ผ์ข
์ ๋ณด์๊ณผ ๊ด๋ จ๋ ๋ถ๋ถ์ธ๋ฐ, ์ ํํฌ FASTAPI๋ฅผ ๋ฐ๋ผ์ค๋ค ๋ณด๋ฉด ์๋ง orgin๋ถ๋ถ์์ ๋ฌธ์ ๋ฅผ ๋ง์ฃผํ๊ฒ ๋ ๊ฒ ์ด๋ค. ์๋ ๋ชจ๋ ๋๋ฉ์ธ์ ์์ฒญ์ ํ๋ฝํ์ง ์๊ณ ,
orgins [
#์ฌ๊ธฐ๋ ์ฌ์ฉ์๊ฐ ํ์ฉํ URL๋ค์ ๋ฃ์ต๋๋ค.
]
์ด๋ ๊ฒ orgins ๋ณ์๋ฅผ ๋ฐ๋ก ์ ์ธํ์ฌ, allow_orgins=orgins ํ์์ผ๋ก ์ฌ์ฉํ๋ค. ์์ ์ฝ๋์์๋, 127.0.0.1:5173์ ๋ํ orgin์ ํ์ฉํ์ผ๋, ๋์ค์ svelte๋ฅผ ์ฌ์ฉํด๋ณด๋ฉด ์๋๋ฐ localhost:5173์ ๋ํ ํ์ฉ์ ํด๋์ง ์์์, ์ ์๋ฌด๋ฆฌ svelte๋ฅผ ์คํ์์ผ ๋ณด์๋, ์ค์จ๊ฑฐ๋ฅผ ํตํด ๋ฃ์ ๋ฐ์ดํฐ๊ฐ ์ง์ง
์ฃฝ์๋ค ๊นจ์ด๋๋ ์๋ณด์ด๋๋ผ
๊ทธ๋ฌ๋ ํน์ ํ๋ค๊ฐ ๋งํ๋ฉด ์ด๋ถ๋ถ์ ๋ฐ๋์ ์ ์ฉํด๋ณด๊ธธ ๋ฐ๋๋ค... ๋ฌผ๋ก ํ์๋ง์ ๋ฐ๋กํด๋ณด์ง๋ ๋ง๊ณ , ์ค์จ๊ฑฐ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ์ฃผ๊ณ ๋ฐ๋์ง ํ์ธํ ํ, ํด๋ณด๊ธธ ์ถ์ฒํ๋ค.
status
:
์ด ์น๊ตฌ๋ ์ต์ํ ๊ฒ์ด๋ค. http ์๋ต์ํ ์ฝ๋๋ฅผ ์ ์ํ๋ ์์๋ค. ์ด๊ฑด ๊ฐ๋
๋ณด๋ค ๋ณธ์ธ์ด ์ง์ ์ค๋ฅ๋ค์ ๋ง์ฃผํ๋ฉฐ, ์ฌ๋ฌ๊ฐ์ง ์ํ์ฝ๋๋ฅผ ๋ง์ฃผํด๋ณด๊ธธ ์ ๊ทน ๊ถ์ฅํ๋ค. ํนํ 404error(Not Found)๋ ์๋ง ์ผ์์ํ์์๋ ํํ ๊ฒฝํํ๋ ์ฝ๋์ผ ๊ฒ.
๊ทธ๋ฅ ์จ๋ด๋ผ
์ ๋ฐ ์ข ์จ๋ด๋ผ
์ ๋ฐ
API๋ฅผ ํธ์ถํ๊ณ ํ ์คํธํ๋ ๋ฐ ์ง์ ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์์๋๋ ์๋ต์ ๋ฏธ๋ฆฌ ํ์ธํ ์ ์๋ ์์ฃผ ํ๊ฒฉ์ ์ธ ๊ธฐ๋ฅ์ด๋ค. ๊ทธ๋ฅ ๋งค์ฐ๋งค์ฐ๋งค์ฐ ๋งค์ฐ์ฐ์ฐ์ฐ์ฐํธ๋ฆฌํ๋ค๊ณ ์๊ฐํ๋ฉด๋๋ค. ์์ธํ ๋์๊ณผ์ ์ ์์งํ ์๋ ค์ฃผ๊ธฐ์ ๋๋ฌด ์ฝ๋ค. ์์ ๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉด์ ๊ผญ ํด๋ณด๊ธธ ๋ฐ๋๋ค.