TOP
본문 바로가기
[파이썬 Projects]/<파이썬 웹개발>

[파이썬] FastAPI - 메모 앱 프로젝트 7: 보완(회원가입 등)

by 기록자_Recordian 2025. 5. 10.
728x90
반응형
이전 내용
 

[파이썬] FastAPI - 메모 앱 프로젝트 6: 프론트엔드 페이지 개선

이전 내용 [파이썬] FastAPI - 메모 앱 프로젝트 5: 웹페이지 개선이전 내용 [파이썬] FastAPI - 메모 앱 프로젝트 4: 사용자별 메모 관리(feat. Almebic)이전 내용 [파이썬] FastAPI - 메모 앱 프로젝트 3: 사용

puppy-foot-it.tistory.com


예외 케이스 보완
1. 회원가입 username 중복 검사

 

회원가입 시 동일한 username을 가진 사용자가 이미 존재하는 경우를 처리하기 위해 main.py의 회원가입 부분 코드를 수정하여 중복 검사를 수행하고, 필요한 경우 적절한 에러 메시지 반환

# 회원 가입
@app.post("/signup")
async def signup(signup_data: UserCreate, db: Session=Depends(get_db)):
    # username 중복 확인
    existing_user = db.query(User).filter(User.username == signup_data.username).first()
    if existing_user:
        raise HTTPException(status_code=400, detail="이미 존재하는 사용자 이름 입니다.")
    hashed_password = get_password_hash(signup_data.password) # 비밀번호 해시 기능
    new_user = User(username=signup_data.username, email=signup_data.email, hashed_password=hashed_password)
    db.add(new_user)
    
    try:
        db.commit()
    except Exception as e:
        db.rollback() # 에러 발생 시 롤백
        raise HTTPException(status_code=500, detail="회원 가입 실패. 다시 시도해 주세요.")
    db.refresh(new_user)
    return {"message": "회원가입을 성공하였습니다."}
  • signup() 함수 내에서 입력된 username이 데이터베이스에 이미 존재하는지 검사하여, 존재하는 경우 400 (Bad Request) 에러 발생 (raise HTTPException)
  • 사용자 추가 후 commit을 시도하며, 에러 발생 시 rollback()을 수행하여 데이터베이스 상태를 이전 상태로 되돌리고 에러 메시지 반환

아이디와 비밀번호 규칙 설정

 

보안 문제를 위해 회원가입 시, 아이디와 비밀번호 규칙을 설정한다.

  • id: 영어 소문자 + 숫자(선택)
  • 비밀번호: 영어(대소문자), 숫자, 하나 이상의 특수문자 조합으로 10자 이상

이를 위해 정규표현식을 써야 하는데, 파이썬 내장 함수인 re 모듈을 import 한다.

import re
# 회원 가입
@app.post("/signup")
async def signup(signup_data: UserCreate, db: Session=Depends(get_db)):
    # ID 규칙 확인: 영어 소문자와 숫자만 허용
    if not re.fullmatch(r"[a-z0-9]+", signup_data.username):
        raise HTTPException(status_code=400, detail="사용자 이름은 영어 소문자와 숫자로만 구성되어야 합니다.")

    # 비밀번호 규칙 확인
    password_regex = re.compile(r"""
        (?=.*[a-z])          # 적어도 하나의 소문자
        (?=.*[A-Z])          # 적어도 하나의 대문자
        (?=.*\d)             # 적어도 하나의 숫자
        (?=.*[@$!%*?&\-_+=<>]) # 적어도 하나의 특수문자
        .{10,}               # 길이는 10자 이상
    """, re.VERBOSE)

    if not password_regex.match(signup_data.password):
        raise HTTPException(status_code=400, detail="비밀번호는 최소 10자 이상이며, 대문자, 소문자, 숫자 및 특수문자가 포함되어야 합니다.")
    # username 중복 확인
    existing_user = db.query(User).filter(User.username == signup_data.username).first()
    if existing_user:
        raise HTTPException(status_code=400, detail="이미 존재하는 사용자 이름 입니다.")
    hashed_password = get_password_hash(signup_data.password) # 비밀번호 해시 기능
    new_user = User(username=signup_data.username, email=signup_data.email, hashed_password=hashed_password)
    db.add(new_user)
    
    try:
        db.commit()
    except Exception as e:
        db.rollback() # 에러 발생 시 롤백
        raise HTTPException(status_code=500, detail="회원 가입 실패. 다시 시도해 주세요.")
    db.refresh(new_user)
    return {"message": "회원가입을 성공하였습니다."}

예외 케이스 보완
2. 로그인 에러 반환 메시지 수정

 

API 응답 메시지를 변경하는 것은 사용자 경험(UX)을 개선하는 좋은 방법이다. 따라서, 사용자가 로그인 실패 시 반환받는 메시지를 수정하기 위해 HTTPException의 detail 인수를 수정한다.

# 로그인
@app.post("/login")
async def login(request: Request, signin_data: UserLogin, db: Session=Depends(get_db)):
    user = db.query(User).filter(User.username == signin_data.username).first()
    if user and verify_password(signin_data.password, user.hashed_password):
        request.session["username"] = user.username
        return {"message": "로그인 성공!"}
    else:
        raise HTTPException(status_code=401, detail="로그인이 실패하였습니다.")

테스트

 

main.py 파일을 실행하여 서버를 실행하고 웹 브라우저에서 회원가입을 시도해 본다.

testuser4의 계정을 생성하려고 했으나, 비밀번호가 4자리 이기 때문에 가입이 불가하다.

 

비밀번호 규칙을 준수한 Aa!12345678 (영어대문자, 영어소문자, 특수문자, 숫자) 로 입력하여 회원가입을 했더니, 성공하였다.

 

앞서 생성했던 testuser4 라는 사용자 이름으로 계정을 생성하려고 하면 이미 존재하는 사용자 이름이라며 가입이 실패한다.


[참고]

가장 빠른 풀스택을 위한 플라스크 & FastAPI

 


다음 내용

 

728x90
반응형