Auth — /api/auth/*
회원가입 + JWT access/refresh 발급 + 갱신 + 사용자 프로필 조회 라우트입니다.
공통
- 베이스 경로:
/api/auth - 인증:
register/login/refresh는 인증 불필요.me는 access 토큰 필요. - 비밀번호: bcrypt 해시 저장. 평문은 절대 응답에 포함되지 않음.
POST /api/auth/register
신규 사용자 등록.
요청 (UserRegister)
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
username | string (3–64, ^[a-zA-Z0-9_]+$) | Y | 영숫자 + 언더스코어 |
email | EmailStr | Y | RFC 5322 |
password | string (8–128) | Y | 평문 (서버에서 해시) |
응답 201 (UserResponse)
{
"id": 42,
"username": "alice",
"email": "alice@example.com",
"role": "user",
"is_active": true,
"created_at": "2026-04-26T10:00:00Z"
}
에러
- 409 — username/email 중복
cURL
curl -X POST http://localhost:8000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "alice",
"email": "alice@example.com",
"password": "S3cure!Passw0rd"
}'
TypeScript
import { api } from '@/api/client';
const user = await api.post<UserResponse>('/api/auth/register', {
username: 'alice',
email: 'alice@example.com',
password: 'S3cure!Passw0rd',
});
POST /api/auth/login
비밀번호로 로그인하고 access + refresh 토큰을 받습니다.
요청 (UserLogin)
| 필드 | 타입 | 필수 |
|---|---|---|
username | string | Y |
password | string | Y |
응답 200 (TokenResponse)
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer"
}
access_token: 기본 30분 유효 (AUTH_ACCESS_TOKEN_TTL_MIN)refresh_token: 기본 7일 유효 (AUTH_REFRESH_TOKEN_TTL_DAYS)
에러
- 401 — 비밀번호 불일치 / 사용자 없음
- 403 — 계정 비활성화
cURL
curl -X POST http://localhost:8000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"S3cure!Passw0rd"}'
POST /api/auth/refresh
만료된 access 토큰을 refresh 토큰으로 재발급합니다.
요청 (TokenRefresh)
| 필드 | 타입 | 필수 |
|---|---|---|
refresh_token | string | Y |
응답 200 (TokenResponse)
새 access + refresh 토큰을 함께 반환합니다 (refresh rotation).
에러
- 401 — 만료/무효 refresh 토큰
cURL
curl -X POST http://localhost:8000/api/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token":"eyJhbGciOiJIUzI1NiIs..."}'
GET /api/auth/me
현재 access 토큰의 사용자 프로필을 반환합니다.
인증
Authorization: Bearer <access_token>
응답 200 (UserResponse)
에러
- 401 — 토큰 누락/만료/무효
cURL
curl -H "Authorization: Bearer $JWT" \
http://localhost:8000/api/auth/me
TypeScript
const me = await api.get<UserResponse>('/api/auth/me', {
headers: { Authorization: `Bearer ${jwt}` },
});
멀티유저 격리
- 모든 인증된 라우트는
current_user.id를 기준으로 데이터 필터링 - 토큰 payload의
sub(user_id)는 변조 시 401 - 토큰 payload의
type은access/refresh중 하나여야 함 (잘못된 type 사용 시 401)
비고
AUTH_SECRET_KEY변경 시 모든 발급된 JWT가 무효화됩니다 (서비스 재시작 시 강제 재로그인 발생).- 비밀번호 정책은
password필드의 길이 제약 외에는 적용되지 않으며, 강력한 정책이 필요하면 클라이언트 측에서 추가 검증하세요.