디렉토리 구조도 잡았으니 이제 본격적으로 API를 만들어본다.
FastAPI 디렉토리 구조에서 언급한 것처럼, pydantic의 BaseModel만 request body로 인식하기 때문에, schemas/user.py에서 request body의 type을 먼저 설정한다
# schemas/user.py
from pydantic import BaseModel
class UserCreate(BaseModel):
email: str
password: str
gender: str
phone: str
birth: str사이드 목적상 많은 개인정보는 필요없고, 나이와 성별정도로만 데이터를 저장해보려고한다. 지역구를 저장하는게 의미가 있을 수도 있지만, 정확하게 받아올 수 있는 정보가 아니니 생략한다.
routers/user.py에 클라이언트로부터 request를 받을 인터페이스를 설정한다.
# routers/user.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from schemas import user as user_schema
from .deps import get_db, Message
# 각 router/XXX.py에 선언한 router들을 routers.py에서 import한 후, 해당 router를 main.py에서 import한다.
router = APIRouter()
# 아래와 같이 response 종류들을 선언해줘야 swagger에 나타난다.
signup_responses = {
201: {'model': Message, 'description': '회원가입 성공'},
409: {'model': Message, 'description': 'email 또는 phone이 중복되는 경우'},
}
@router.post("/signup", status_code=201, responses={**signup_responses})
def signup(
signup_info: user_schema.UserCreate,
db: Session = Depends(get_db),
):
# bcrypt를 사용해서 비밀번호를 단방향 hashing하는 과정을 거친다. 코드는 공식문서 참고
# signup_info.password를 덮어쓰는 이유는 crud/user.py에서도 UserCreate schema를 사용하기 때문이다.
signup_info.password = get_password_hash(signup_info.password)
# db에 저장한다.
create_user(signup_info, db)
# 특이하게 dicitionary로 리턴해도 정상 작동한다.
return {'msg': 'SIGNUP_SUCCESS'}이제 sqlalchemy를 사용해서 데이터베이스에 저장하는 과정을 살펴본다.
# crud/user.py
def create_user(
signup_info: UserCreate,
db: Session,
) -> User:
db_obj = User(
username = signup_info.username,
password = signup_info.password,
phone = signup_info.phone,
gender = signup_info.gender,
birth = signup_info.birth
)
db.add(db_obj)
db.commit()
return db.add()를 하면 깃헙으로 따지면 스테이징이 되고, db.commit()을 해야 실제로 디비에 INSERT된다. 공식문서 예제에서는 .commit() 후에 .refresh()를 해준다.
.refresh()를 하는 이유는, 다른 어딘가에서 데이터베이스에 커밋이 발생했을 때, 내가 원하는 객체가 변경될 수 있기 때문이다(회원가입에는 크게 해당하지 않지만 누군가 갑자기 사용자 정보를 바꾼다던지의 문제)
그렇다면 해당 객체가 내가 원하는 상태의 객체가 아닐 수 있기 때문에 데이터베이스를 read해서 최신화 하는 것이다.
회원가입 후 사용자 정보를 따로 클라이언트에 리턴하는 절차가 없기 때문이 refresh는 생략한다.
curl로 시도해보면 잘 작동하는 것을 볼 수 있다.

서버 로그도 잘 찍히는 것을 볼 수 있다.

이제 API가 하나 만들어졌으니, 클라이언트를 만들어보도록 하겠다.