Skip to content

[TROUBLE SHOOTING] 마이페이지 자산 조회 및 회원 탈퇴 시 500 Internal Server Error 해결 #1

@sbyy77dev

Description

@sbyy77dev

🐛 [Troubleshooting] 마이페이지 자산 조회 및 회원 탈퇴 시 500 Internal Server Error 해결

📅 일시: 2025.11.19

📂 관련 레포/파일/경로:

  • 레포:cardbenepick-app
    • backend/app/api/endpoints/assets.py
    • backend/app/api/endpoints/users.py

🏷 태그: #FastAPI #SQLModel #Python #NameError #AttributeError


1. 문제 상황 (Context & Problem)

  • 작업 내용: 마이페이지(MyPage) 기능을 구현하면서 **'연동된 자산 목록 조회(GET)'**와 '회원 탈퇴(DELETE)' API를 테스트하고 있었음.

  • 발생 오류: 두 API 모두 호출 시 500 Internal Server Error가 발생함.

    로그 확인 결과:

    1. GET /api/assets/: NameError: name 'select' is not defined
    2. DELETE /api/users/me: db.exec(select(...)).delete() 구문 실행 중 AttributeError 또는 트랜잭션 롤백 발생

2. 시도 및 해결 (Try & Solution)

  • 원인 분석: 1. Import 누락: assets.py에서 sqlmodelselect 함수를 사용하고 있었으나, 상단 import 구문에 포함되지 않음.
    2. SQLModel 문법 오해: db.exec(select(...))는 쿼리 실행 결과(Result 객체)를 반환하는데, 여기에 바로 .delete() 메서드를 체이닝하려고 해서 에러 발생. SQLModel(SQLAlchemy)에서는 조회 쿼리에 바로 delete를 붙일 수 없음.

  • 해결 방법:

    [문제 1: 자산 조회]

    1. assets.py 파일 상단에 from sqlmodel import select 구문 추가하여 해결.

    [문제 2: 회원 탈퇴]

    1. 시도 1 (Bulk Delete): db.exec(delete(CardTransaction).where(...)) 처럼 delete 구문을 직접 사용해 보았으나, 트랜잭션 처리나 버전 호환성 문제로 ROLLBACK이 발생하며 실패.
    2. 최종 해결 (Fetch & Delete): 데이터를 먼저 조회(select)한 뒤, 반복문을 돌며 객체를 하나씩 삭제(db.delete)하는 방식으로 변경하여 안정성 확보.
  • 코드 변경 (회원 탈퇴 로직):

    # 변경 전 (AS-IS): 잘못된 문법
    db.exec(select(CardTransaction).where(CardTransaction.user_id == user_id)).delete()
    
    # 변경 후 (TO-BE): 조회 후 개별 삭제 (안전한 방식)
    transactions = db.exec(select(CardTransaction).where(CardTransaction.user_id == user_id)).all()
    for transaction in transactions:
        db.delete(transaction)

3. 배운 점 (Retrospective)

  • SQLModel의 동작 방식: db.exec()는 실행 결과를 리턴할 뿐, 쿼리 빌더 자체를 리턴하는 게 아니다. ORM을 쓸 때는 메서드 체이닝이 가능한 객체인지 항상 타입을 확인해야 한다.
  • Bulk Delete의 주의점: 한 번에 지우는 쿼리(DELETE FROM table WHERE ...)가 성능은 좋지만, ORM 레벨에서 제약조건이나 Cascade 설정이 복잡할 때는 **'조회 후 삭제'**가 가장 확실하고 디버깅하기 쉬운 방법일 수 있다.
  • Import 확인: 코드를 복사/붙여넣기 하거나 수정할 때, 사용된 함수(select 등)가 제대로 import 되었는지 IDE의 린트 기능을 통해 꼼꼼히 확인하자.

Action Item: 향후 데이터 양이 많아져서 삭제 성능이 중요해지면, SQLModel/SQLAlchemy의 delete() 구문을 정확히 사용하는 방법(Bulk Delete)을 다시 학습하여 리팩토링하기.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions