챗봇 공부 노트

[19편] part 3 배포 백엔드/회원가입/정규식/의존성 변경 상세

frontend-diary-log 2026. 2. 13. 17:52

 

🚀 Aura AI 배포 기록 (Part 3)

백엔드 회원가입 API · 정규식 오류 · 의존성 · 서비스 레이어 변경 총정리

이번 글은 FastAPI 기반 백엔드에서 회원가입 기능을 직접 구현하면서 발생한 문제들과 구조 개선 과정을 정리한 기록입니다.

Part 1에서는 서버/배포/운영,
Part 2에서는 프론트/프록시 구조를 다뤘다면,

👉 Part 3는 “백엔드 비즈니스 로직 설계 + 보안 + 검증 + DB 처리” 핵심 파트입니다.

특히 다음 내용을 중점적으로 다룹니다.

  • 회원가입 API 신규 구현
  • 정규식 검증 오류 해결
  • user_service 리팩토링
  • requirements 의존성 추가 이유
  • 전체 회원가입 처리 흐름

✅ Part 3 핵심 목표

🎯 해결 과제

  • Vercel에서 DB 직접 접근 불가
  • 프론트에서 회원가입 처리 시 보안 취약
  • 검증/암호화/저장 로직 분산 문제

🎯 목표 구조

✔ 회원가입 로직 100% 백엔드 처리
✔ 입력 검증 + 암호화 + DB 저장 일원화
✔ OAuth/일반 가입 스키마 통합
✔ 운영 안정성 확보



1️⃣ auth.py — 회원가입 API 추가


❓ 왜 추가했는가?

기존 문제

  • Vercel 서버리스 환경은 MySQL 직접 연결 불가
  • 프론트에서 DB 로직 처리 시 보안 위험
  • 데이터 검증 누락 가능성

즉,

프론트 → DB 직접 접근 ❌ (구조적으로 불가능 + 위험)

✅ 해결 전략

👉 회원가입을 전부 백엔드에서 처리

  • 검증
  • 암호화
  • DB 저장

모든 책임을 서버로 이동


✅ 추가된 핵심 구조

@router.post("/signup")
def signup(body: SignupRequest):
    ...

📌 의미

  • /signup POST JSON 요청 수신
  • 서버에서 입력값 직접 검증
  • 안전하게 DB 저장

👉 회원가입의 단일 진입점(Single Entry Point)



2️⃣ 입력값 검증 로직 (정규식)


✅ 적용된 검증 규칙

EMAIL_REGEX = re.compile(r"^[^\s@]+@[^\s@]+\.[^\s@]+$")
PHONE_REGEX = re.compile(r"^01[016789]-?\d{3,4}-?\d{4}$")
PASSWORD_REGEX = re.compile(r"^(?=.*[A-Za-z])(?=.*\d).{8,}$")

📌 각 정규식 의미

이메일

user@domain.com 형식만 허용

전화번호

010-1234-5678
01012345678
둘 다 허용

비밀번호

8자 이상 + 영문 포함 + 숫자 포함 필수

✅ 효과

✔ 서버 단에서 강력한 입력 검증
✔ 잘못된 데이터 DB 유입 차단
✔ 보안 강화



3️⃣ 정규식 오류 문제 (이메일 검증 실패)


❌ 발생한 이상 현상

정상 이메일도 실패

asdf@naver.com → "이메일 형식이 올바르지 않습니다"

❌ 원인 분석

정규식이 이중 이스케이프 상태로 저장됨

잘못된 코드

EMAIL_REGEX = re.compile(r"^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$")

❗ 문제점

\\s

  • 공백 문자 ❌
  • 문자 "" + "s" 로 인식

즉, 정규식이 완전히 깨진 상태


✅ 수정 후 (정상)

EMAIL_REGEX = re.compile(r"^[^\s@]+@[^\s@]+\.[^\s@]+$")
PHONE_REGEX = re.compile(r"^01[016789]-?\d{3,4}-?\d{4}$")
PASSWORD_REGEX = re.compile(r"^(?=.*[A-Za-z])(?=.*\d).{8,}$")

✅ 수정 이유

핵심 포인트

  • Raw string(r"")에서는
  • \s, \. 그대로 사용해야 함
  • 이중 이스케이프 불필요

💡 원인 추정

  • JSON 직렬화
  • 복붙 과정
  • 문자열 escape 중복

으로 텍스트가 깨진 것으로 판단


✅ 결과

✔ 이메일 검증 정상 동작
✔ 회원가입 성공



4️⃣ user_service.py 변경


❓ 왜 변경했는가?

기존 구조는:

OAuth 로그인 시에만 INSERT

즉,

👉 일반 회원가입 로직이 존재하지 않음


✅ 추가된 핵심 기능

def create_user(...):
    # 중복 이메일/닉네임 확인
    # 비밀번호 해시 저장
    # provider = "credentials"

📌 동작 의미

1️⃣ 중복 검사

  • 이메일 중복 체크
  • 닉네임 중복 체크

2️⃣ 비밀번호 암호화

  • 평문 저장 ❌
  • 해시 저장 ⭕

3️⃣ provider 설정

credentials

일반 가입 구분


✅ 구조적 장점

⭐ 가장 중요한 포인트

👉 OAuth / 일반 가입 모두 하나의 users 테이블 사용


효과

✔ 스키마 통일
✔ 유지보수 쉬움
✔ 인증 방식 추가 쉬움
✔ DB 단순화



5️⃣ requirements.txt 변경 (의존성 추가)


✅ 추가된 패키지

bcrypt
python-multipart

📌 각각 왜 필요한가?

🔹 bcrypt

비밀번호 해시 암호화

password → hash → DB 저장

보안 필수 요소


🔹 python-multipart

파일 업로드 처리용

  • 프로필 이미지
  • FormData 요청

에서 필수


❌ 실제 발생한 에러

bcrypt 누락

ModuleNotFoundError: No module named 'bcrypt'

multipart 누락

Form data requires "python-multipart"

✅ 해결

pip install -r requirements.txt

💡 교훈

👉 FastAPI + 파일 업로드 = python-multipart 거의 필수



6️⃣ main.py 변경


❓ 왜 수정했는가?

라우터를 만들어도 등록하지 않으면 동작하지 않습니다.


✅ 추가 코드

from routers.auth import router as auth_router
app.include_router(auth_router)

의미

  • auth.py 연결
  • /signup 엔드포인트 실제 활성화


7️⃣ 회원가입 전체 흐름 정리


✅ 최종 동작 순서

① 프론트

/api/signup 호출

② Vercel

/signup → EC2 프록시

③ FastAPI auth.py

  • 입력 검증
  • 정규식 검사
  • bcrypt 해시

④ user_service.py

  • 중복 검사
  • DB INSERT

⑤ 성공 응답

{ "message": "회원가입 완료" }


8️⃣ 왜 이 구조가 가장 효율적인가?


❌ 프론트 처리 방식

  • 보안 취약
  • 로직 노출
  • DB 직접 접근 위험
  • 유지보수 지옥

✅ 백엔드 처리 방식 (현재 구조)

✔ 보안 강화
✔ 검증/저장 통합
✔ 비즈니스 로직 집중
✔ OAuth/일반 가입 통합
✔ 확장성 ↑


💡 결론

👉 회원가입은 반드시 서버 책임으로 처리하는 것이 정석 아키텍처



✅ Part 3 전체 요약

이번 파트에서 수행한 작업

✔ auth.py 회원가입 API 구현
✔ 정규식 검증 추가
✔ 이중 이스케이프 버그 수정
✔ user_service 생성 로직 추가
✔ bcrypt / multipart 의존성 추가
✔ 라우터 등록


🎯 최종 결과

  • 안전한 회원가입 시스템 구축
  • 비밀번호 암호화 완료
  • OAuth/일반 가입 통합
  • 운영 안정성 확보