🚀 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/일반 가입 통합
- 운영 안정성 확보
'챗봇 공부 노트' 카테고리의 다른 글
| [20편] 배포 후 오류 수정 (0) | 2026.02.25 |
|---|---|
| [19편] part 4 배포 배포 명령어/의미 + 오류 로그 대응표 + 체크리스트 (0) | 2026.02.13 |
| [19편] part 2 배포 프론트/프록시 구조 변경 상세 정리 (0) | 2026.02.13 |
| [19편] part 1 배포 전체 흐름 + 장애 대응 + 서버 유지 (0) | 2026.02.13 |
| [18편] Part 2 마이페이지 코드 + 설계의도 (0) | 2026.02.06 |