feat(backend): 소셜 로그인·JWT 인증과 회원·파일 API 추가

앱의 기록을 서버로 옮기려면 회원과 인증이 먼저 있어야 한다.

- 소셜 로그인: 앱이 SDK 로 받은 토큰을 서버가 제공자에게 직접 확인한다
  (카카오·네이버는 사용자 정보 API, 구글·Apple 은 id_token JWKS 검증)
- 소셜 앱 키가 생기기 전까지 쓰는 개발용 로그인(기기 키) — 운영에서는 닫힌다
- 액세스 JWT(1시간) + 리프레시 토큰(해시 저장·회전·재사용 탐지)
- 전역 JwtAuthGuard — 기본으로 모든 라우트가 로그인을 요구하고 @Public() 으로만 연다
- 내 정보 조회·수정·탈퇴(모든 기록과 파일 정리), 파일 소유자 기록과 내려받기,
  업로드 시 매직 바이트로 내용 형식 검사
- 컬럼은 snake_case 이름 규칙, 테스트 환경은 기동 시 마이그레이션 실행 (CI e2e 는 빈 DB)
- 템플릿 예제 사용자 API(in-memory)를 실제 회원 API 로 교체하고 e2e 계약 테스트를 옮겼다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-11 17:06:43 +09:00
parent 1f7693898c
commit 7e0e4c36b5
53 changed files with 2943 additions and 274 deletions
+21 -1
View File
@@ -9,7 +9,27 @@
# docker-compose 의 env_file 지시자 때문에 파일은 비어 있어도 존재해야 한다.
# ==========================================
# JWT 서명 키 — 인증 도입 시 사용. 환경마다 다른 값을 쓰고 절대 커밋하지 않는다.
# JWT 서명 키 — 환경마다 다른 값을 쓰고 절대 커밋하지 않는다. 운영은 32자 이상 필수.
# 생성 예: node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))"
# (개발에서 비워 두면 개발용 고정 키로 서명한다 — modules/auth/auth.config.ts)
JWT_SECRET=change-me-generate-a-long-random-string
JWT_ACCESS_EXPIRES_IN=1h
JWT_REFRESH_EXPIRES_IN=14d
# ==========================================
# 소셜 로그인 (앱이 SDK 로 받은 토큰을 서버가 제공자에게 확인한다)
#
# 비어 있는 제공자는 로그인을 거절한다(AUTH_001). 값은 각 개발자 콘솔에서 확인한다.
# ==========================================
# 카카오 앱 ID (숫자) — 토큰이 우리 앱에서 발급됐는지 확인한다
KAKAO_APP_ID=
# 네이버 클라이언트 ID — 설정해야 네이버 로그인이 켜진다
NAVER_CLIENT_ID=
# 구글 OAuth 클라이언트 ID (iOS·Android 등 여러 개면 콤마로 구분) — id_token 의 aud
GOOGLE_CLIENT_IDS=
# Apple 번들 ID·서비스 ID (콤마 구분) — id_token 의 aud
APPLE_CLIENT_IDS=
# 개발용 로그인(POST /api/auth/dev-sessions) — 소셜 앱 키 없이 기기 키로 가입한다.
# 운영에서는 이 값과 무관하게 항상 꺼진다. 개발에서도 끄려면 false.
AUTH_DEV_LOGIN=true