[Hot Item] #5. DRF + Swagger 문서 자동화, 커스텀 User 모델, JWT 인증 설정
시리즈: Hot Item 프로젝트 구축기
태그: Django DRF drf-spectacular SimpleJWT AbstractUser Swagger
이 글에서 다루는 내용
- djangorestframework로 REST API 기반 구성하기
- drf-spectacular로 Swagger UI 자동 문서화 적용하기
- accounts 앱 생성 및 AbstractUser를 상속한 커스텀 User 모델 만들기
- SimpleJWT로 JWT 인증 설정하기
- AUTH_USER_MODEL로 Django 기본 유저 모델 교체하기
1. 왜 이 라이브러리들이 필요한가요?
Hot Item은 프론트엔드와 분리된 REST API 서버로 동작합니다. 이를 위해 세 가지 라이브러리를 추가합니다.
라이브러리 역할
| djangorestframework | Django를 REST API 서버로 만드는 핵심 프레임워크 |
| drf-spectacular | API 코드를 분석해 Swagger UI 문서를 자동 생성 |
| djangorestframework-simplejwt | JWT 기반 로그인/인증 처리 |
Spring Boot를 써본 분이라면 drf-spectacular는 SpringDoc(Swagger UI)과 동일한 역할이라고 생각하면 됩니다. API 엔드포인트를 추가하면 문서가 자동으로 갱신되고, 해당 페이지에서 바로 요청을 테스트해볼 수 있습니다.
2. requirements.txt에 라이브러리 추가하기
# Web Framework
Django>=5.0,<5.1
# Database (PostgreSQL)
psycopg[binary]>=3.1.18
# Cache & Queue (Redis)
redis>=5.0.3
# Asynchronous Task (Celery)
celery>=5.3.6
django-environ>=0.11.2
requests>=2.31.0
# REST API
djangorestframework>=3.15.0
drf-spectacular>=0.27.1
djangorestframework-simplejwt>=5.3.1
파일을 저장한 뒤 Dev Container 터미널에서 설치합니다.
pip install -r requirements.txt
3. accounts 앱 생성하기
회원 기능을 담당할 accounts 앱을 생성합니다.
python manage.py startapp accounts
생성된 앱을 settings.py의 INSTALLED_APPS에 등록합니다.
INSTALLED_APPS = [
# Django 기본 앱
'django.contrib.admin',
'django.contrib.auth',
...
# 서드파티
'rest_framework',
'drf_spectacular',
# 로컬 앱
'accounts',
]
💡 앱 등록 순서 관례
INSTALLED_APPS는 Django 기본 앱 → 서드파티 → 로컬 앱 순서로 작성하는 것이 일반적인 관례입니다. 가독성도 좋아지고 의존성 충돌도 줄어듭니다.
4. 커스텀 User 모델 만들기
왜 AbstractUser를 상속하나요?
Django는 기본 User 모델(auth.User)을 제공합니다. 그런데 이 모델은 username, email, password 같은 기본 필드만 있습니다. Hot Item에서는 phone_number 같은 추가 필드가 필요합니다.
이때 선택지는 두 가지입니다.
- AbstractUser 상속: 기존 User 기능(로그인, 권한 등)을 그대로 유지하면서 필드만 추가
- AbstractBaseModel 상속: User 모델을 처음부터 직접 설계 (고급)
Hot Item은 Django 기본 인증 기능을 그대로 활용할 것이므로 AbstractUser를 선택합니다.
accounts/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone_number = models.CharField(max_length=15, null=False)
class Meta:
db_table = 'customers'
AbstractUser를 상속하면 username, email, password, is_active 등 Django 기본 User의 모든 필드와 메서드를 그대로 물려받습니다. 여기에 phone_number 필드만 추가했습니다.
db_table = 'customers'는 실제 DB에 생성될 테이블 이름을 지정합니다. 이 설정이 없으면 Django가 기본으로 accounts_user라는 이름으로 테이블을 만듭니다.
settings.py에 AUTH_USER_MODEL 등록하기
커스텀 User 모델을 만들었다면 반드시 settings.py에 알려줘야 합니다.
AUTH_USER_MODEL = 'accounts.User'
⚠️ 반드시 첫 migrate 전에 설정해야 합니다
AUTH_USER_MODEL은 프로젝트 초기에 딱 한 번만 설정합니다. 이미 migrate를 진행한 후에 변경하면 기존 마이그레이션과 충돌이 발생합니다. 이 프로젝트에서 실제로 이 문제를 겪었고, 해결 과정은 트러블슈팅 #1 포스트에서 자세히 다룹니다.
5. DRF와 SimpleJWT 설정 추가하기
settings.py에 DRF 설정과 JWT 설정을 추가합니다.
from datetime import timedelta
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'AUTH_HEADER_TYPES': ('Bearer',),
}
각 설정의 의미를 살펴봅니다.
REST_FRAMEWORK
- DEFAULT_SCHEMA_CLASS: DRF가 API 스키마를 생성할 때 drf-spectacular의 AutoSchema를 사용하도록 지정합니다. 이 설정 하나로 모든 API가 Swagger 문서에 자동 포함됩니다.
- DEFAULT_AUTHENTICATION_CLASSES: 모든 API 요청의 기본 인증 방식을 JWT로 설정합니다.
SIMPLE_JWT
설정 의미
| ACCESS_TOKEN_LIFETIME | Access Token 유효 시간 (30분) |
| REFRESH_TOKEN_LIFETIME | Refresh Token 유효 시간 (1일) |
| ROTATE_REFRESH_TOKENS | 토큰 갱신 시 Refresh Token도 새로 발급할지 여부 |
| BLACKLIST_AFTER_ROTATION | 이전 Refresh Token을 블랙리스트 처리할지 여부 |
| AUTH_HEADER_TYPES | 요청 헤더의 토큰 접두사 (Authorization: Bearer <token>) |
6. drf-spectacular 설정 추가하기
SPECTACULAR_SETTINGS = {
'TITLE': 'Hot Item API',
'DESCRIPTION': '선착순 대규모 트래픽 처리 시스템 API 문서',
'VERSION': '1.0.0',
'SERVE_INCLUDE_SCHEMA': False,
'SECURITY': [{'jwt': []}],
}
URL 연결은 다음 포스트에서 회원가입 / 로그인 API를 구현하면서 함께 진행합니다.
7. 마이그레이션 실행하기
커스텀 User 모델을 추가했으므로 마이그레이션 파일을 생성하고 적용합니다.
python manage.py makemigrations accounts
python manage.py migrate
정상적으로 적용되면 PostgreSQL에 customers 테이블이 생성됩니다.
Migrations for 'accounts':
accounts/migrations/0001_initial.py
- Create model User
Operations to perform:
Apply all migrations: accounts, admin, auth, contenttypes, sessions
Running migrations:
Applying accounts.0001_initial... OK
Applying admin.0001_initial... OK
...
⚠️ 이 과정에서 InconsistentMigrationHistory 에러가 발생했습니다.
이전 포스트에서 먼저 migrate를 실행한 상태에서 AUTH_USER_MODEL을 변경했기 때문입니다. 해결 과정은 트러블슈팅 #1 포스트에서 자세히 다룹니다.
8. 최종 폴더 구조
hot-item/
├── accounts/ # 회원 앱
│ ├── migrations/
│ │ └── 0001_initial.py
│ ├── models.py # 커스텀 User 모델
│ ├── views.py
│ └── ...
├── config/
│ ├── settings.py # DRF, JWT, Spectacular 설정 추가
│ └── ...
├── requirements.txt # 라이브러리 3개 추가
└── ...
9. 정리
오늘 한 작업을 요약하면:
- djangorestframework로 Django를 REST API 서버로 구성했습니다.
- drf-spectacular로 Swagger UI 자동 문서화 기반을 설정했습니다.
- AbstractUser를 상속한 커스텀 User 모델을 만들고, db_table = 'customers'로 테이블 이름을 지정했습니다.
- SimpleJWT로 JWT 인증 방식을 설정하고, AUTH_HEADER_TYPES: Bearer로 표준 인증 헤더를 적용했습니다.
- AUTH_USER_MODEL = 'accounts.User'로 Django 기본 유저 모델을 교체했습니다.