백엔드 기초집: Python FastAPILESSON 21
비밀번호 해싱과 사용자 회원가입
난이도초급
예상 시간35분
선수지식이전 강의
21강. 비밀번호 해싱과 사용자 회원가입
1. 이번 강의에서 해결할 문제
회원가입 비밀번호를 그대로 DB에 저장하면 유출 시 즉시 계정 피해로 이어집니다. 복호화할 수 없는 password hash만 저장합니다.
2. 학습 목표
3. 핵심 개념
비밀번호는 복호화할 이유가 없으므로 salt가 포함된 느린 단방향 해시로 저장합니다. FastAPI 공식 JWT 예제는 현재 pwdlib의 권장 설정을 사용하며 Argon2를 지원합니다. 로그인에서는 평문을 다시 hash해 문자열 비교하지 않고 verify(plain, hash)를 호출합니다.
4. 단계별 코드 예시
파일 경로: game-ranking-api/app/schemas/user.py
app/schemas/user.py
from pydantic import BaseModel, ConfigDict, Field
class UserCreate(BaseModel):
username: str = Field(min_length=3, max_length=50, pattern=r"^[a-zA-Z0-9_]+$")
password: str = Field(min_length=12, max_length=128)
class UserRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
username: str
role: str
파일 경로: game-ranking-api/app/security.py
app/security.py
from pwdlib import PasswordHash
password_hash = PasswordHash.recommended()
def hash_password(password: str) -> str:
return password_hash.hash(password)
def verify_password(password: str, encoded_hash: str) -> bool:
return password_hash.verify(password, encoded_hash)
파일 경로: game-ranking-api/app/routers/auth.py
app/routers/auth.py
from fastapi import APIRouter, HTTPException, status
from sqlalchemy import select
from app.models.user import User
from app.schemas.user import UserCreate, UserRead
from app.security import hash_password
router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/register", response_model=UserRead, status_code=status.HTTP_201_CREATED)
def register(payload: UserCreate, db: DbSession) -> User:
username = payload.username.lower()
if db.scalar(select(User).where(User.username == username)):
raise HTTPException(status_code=409, detail="이미 사용 중인 사용자 이름입니다")
user = User(username=username, password_hash=hash_password(payload.password))
db.add(user)
db.commit()
db.refresh(user)
return user
실행 위치: game-ranking-api/
python -m uvicorn app.main:app --reload
Invoke-RestMethod -Method Post http://127.0.0.1:8000/auth/register -ContentType 'application/json' -Body '{"username":"player_one","password":"correct-horse-battery"}'
5. 코드가 동작하는 이유
회원가입 입력의 password는 함수 안에서만 사용되고 DB에는 Argon2 형식 hash가 저장됩니다. UserRead에는 password_hash 필드가 없으므로 응답에서 필터링됩니다. username을 소문자로 정규화해 대소문자만 다른 중복을 줄입니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
MINI QUIZ
0 / 2비밀번호 해싱과 사용자 회원가입 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
LESSON STATUS
21강. 비밀번호 해싱과 사용자 회원가입 미완료 상태학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.