ID: key_26_22_05_25_P1_1_2 Created date: 5월 25 2026 월요일
연관 문서
개발 일정 > Phase 1 서버 개발 | 서버 (befw-app-server)
개요
JWT 기반 인증/인가 시스템을 구현한다. 로그인, 회원가입, 토큰 갱신 API를 제공한다.
- 예상 소요: 3~5일
- 선행 조건: 1-1_DB-DDL-Flyway-마이그레이션, P5_CLAUDE-md-서버 완료
- 완료 기준: Postman으로 로그인 → Access Token 수신 → 인증 필요 API 호출 성공
API 목록
| Method | Path | 설명 | 인증 |
|---|---|---|---|
| POST | /api/v1/auth/register | 회원가입 | 불필요 |
| POST | /api/v1/auth/login | 로그인 (JWT 발급) | 불필요 |
| POST | /api/v1/auth/logout | 로그아웃 (토큰 무효화) | 필요 |
| POST | /api/v1/auth/refresh | Access Token 갱신 | Refresh Token |
| GET | /api/v1/users/me | 내 프로필 조회 | 필요 |
| PUT | /api/v1/users/me | 내 프로필 수정 | 필요 |
Claude Code 작업 수행서
목표
JWT 기반 인증 API 전체를 구현한다. Access Token + Refresh Token 이중 토큰 전략을 사용한다.
작업 지시
CIRA 서버에 JWT 인증 API를 구현해줘. CLAUDE.md 컨벤션을 반드시 준수해.
[프로젝트 경로]
- C:\workspace\tsh\boilerplate\be\befw-lib-core\src\main\java\com\tsh\starter\befw\lib\core
[토큰 전략]
- Access Token: JWT, 만료 15분, Authorization 헤더 (Bearer)
- Refresh Token: Opaque 토큰 (UUID), 만료 7일, HttpOnly Cookie
- Refresh Token은 DB에 저장하지 않고 Redis에 저장 (없으면 임시로 DB users 테이블 컬럼 추가)
[수행 작업]
1. 의존성 추가 (maven)
- spring-boot-starter-security
- jjwt-api, jjwt-impl, jjwt-jackson (io.jsonwebtoken)
- spring-boot-starter-data-redis (Refresh Token 저장)
2. 도메인 패키지 구성
com.tsh.starter.befw.lib.core/
├── interfaces/rest/auth/AuthController.java
├── apService/auth/AuthService.java
├── apService/auth/JwtService.java
├── apService/auth//RefreshTokenService.java
├── apService/auth/dto/
│ ├── LoginRequest.java (email, password)
│ ├── LoginResponse.java (accessToken, tokenType, expiresIn)
│ ├── RegisterRequest.java (email, name, password)
│ └── RefreshRequest.java
└── config/security/
├── JwtAuthenticationFilter.java
├── SecurityConfig.java
└── CustomUserDetailsService.java
com.tsh.starter.befw.lib.core/
├── interfaces/rest/auth/UserController.java
├── apService/auth/UserService.java
└── apService/auth/dto/
├── UserResponse.java
└── UpdateProfileRequest.java
3. JwtService 구현
- generateAccessToken(UserDetails): String
- generateRefreshToken(): String
- validateToken(String token): boolean
- extractEmail(String token): String
- 비밀키: application.yml jwt.secret (256-bit 이상)
4. SecurityConfig 구현
- 허용 경로: POST /api/v1/auth/login, POST /api/v1/auth/register, POST /api/v1/auth/refresh
- 나머지 전체 인증 필요
- CORS 설정 (허용 Origin: NEXT_PUBLIC_URL)
- CSRF 비활성화 (JWT 사용)
- JwtAuthenticationFilter를 UsernamePasswordAuthenticationFilter 앞에 등록
5. 각 API 구현
POST /auth/register:
- 이메일 중복 체크
- 비밀번호 BCrypt 해시
- users 테이블 INSERT
- 201 CREATED 반환
POST /auth/login:
- 이메일/비밀번호 검증
- Access Token 생성
- Refresh Token 생성 → Redis 저장 (key: refresh:{token}, value: userId, TTL: 7일)
- Refresh Token → HttpOnly Cookie 설정
- Access Token → 응답 body
POST /auth/refresh:
- Cookie에서 Refresh Token 추출
- Redis에서 유효성 검증
- 새 Access Token 발급
- (선택) Refresh Token Rotation 구현
POST /auth/logout:
- Redis에서 Refresh Token 삭제
- Cookie 만료 처리
6. 단위 테스트 작성
- AuthService 로그인 성공/실패 테스트
- JwtService 토큰 생성/검증 테스트
- 통합 테스트: POST /auth/login → 200 + accessToken 필드 존재
[준수 사항]
- 비밀번호는 BCryptPasswordEncoder 사용 (강도 12)
- 에러 응답은 ErrorCode 사용 (AUTH_INVALID_CREDENTIALS, AUTH_TOKEN_EXPIRED 등)
- 모든 민감 정보는 application.yml placeholder 처리 (실제값 하드코딩 금지)
완료 기준
| 항목 | 기준 |
|---|---|
| 회원가입 API | 201 반환, users 테이블 INSERT 확인 |
| 로그인 API | 200 + accessToken, Cookie에 refreshToken 설정 |
| 토큰 갱신 | 만료된 Access Token → Refresh로 새 발급 |
| 인증 필터 | 유효한 토큰으로 /users/me 200 반환 |
| 단위 테스트 | 전체 통과 |
후행 작업
- 1-3_서버-이슈-CRUD-API — 인증 미들웨어 재사용
- 1-5_UI-인증-페이지 — next-auth 연동 대상