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
+9
View File
@@ -6,7 +6,9 @@ import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';
import { CacheModule } from '@nestjs/cache-manager';
import { APP_GUARD } from '@nestjs/core';
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
import { RequestIdMiddleware } from '@/common/middleware/request-id.middleware';
import { AuthModule } from '@/modules/auth/auth.module';
import { HealthModule } from '@/modules/health/health.module';
import { UploadModule } from '@/modules/upload/upload.module';
import { UserModule } from '@/modules/user/user.module';
@@ -60,6 +62,7 @@ const THROTTLE_DEFAULT_LIMIT = 100; // 구간당 IP별 최대 요청 수
HealthModule,
UploadModule,
UserModule,
AuthModule,
],
providers: [
ShutdownLogger,
@@ -67,6 +70,12 @@ const THROTTLE_DEFAULT_LIMIT = 100; // 구간당 IP별 최대 요청 수
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
// 전역 인증 — 모든 라우트가 기본으로 로그인을 요구한다. 예외는 @Public() 으로 연다.
// (rate limit 이 먼저 돌아 토큰 없는 대량 요청도 한도에 걸린다)
{
provide: APP_GUARD,
useClass: JwtAuthGuard,
},
],
})
export class AppModule implements NestModule {