ViewSet์ ์ฌ์ฉํ์ฌ Django REST Framework API๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์. ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ๋ถํฐ ๊ณ ๊ธ ์ฌ์ฉ์ ์ ์๊น์ง ์ค์ฉ์ ์ธ ์์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ ๊ณตํฉ๋๋ค.
Django REST Framework ViewSets: API ์๋ํฌ์ธํธ ๊ตฌ์ฑ ๋ง์คํฐํ๊ธฐ
ํ๋ ์น ๊ฐ๋ฐ์์ ๊ฐ๋ ฅํ๊ณ ์ ๊ตฌ์ฑ๋ API๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. Django REST Framework (DRF)๋ Django๋ก RESTful API๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๊ฐ๋ ฅํ ํดํท์ ๋๋ค. DRF๋ API ์๋ํฌ์ธํธ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๋ค์ํ ๋๊ตฌ๋ฅผ ์ ๊ณตํ์ง๋ง, ViewSets๋ ๊ด๋ จ ๋ณด๊ธฐ๋ฅผ ๋จ์ผ ํด๋์ค๋ก ๊ตฌ์ฑํ๋ ์ฐ์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ฌ ๋ ๊น๋ํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ๋ง๋ญ๋๋ค. ์ด ์ข ํฉ ๊ฐ์ด๋๋ ViewSets์ ์ด์ , ์ฌ์ฉ๋ฒ ๋ฐ ๊ณ ๊ธ ์ฌ์ฉ์ ์ ์ ๊ธฐ์ ์ ํฌํจํ์ฌ ์์ธํ ์ดํด๋ด ๋๋ค.
ViewSet์ด๋ ๋ฌด์์ ๋๊น?
ViewSet์ list
, create
, retrieve
, update
๋ฐ destroy
์ ๊ฐ์ ํ์ค ์์
์ ๋ํ ๊ตฌํ์ ์ ๊ณตํ๋ ํด๋์ค ๊ธฐ๋ฐ View์
๋๋ค. ๊ฐ ์์
์ ๋ํด ๋ณ๋์ ๋ณด๊ธฐ๋ฅผ ์ ์ํ๋ ๋์ ViewSet์ ์ด๋ฌํ ์์
์ ๋จ์ผ ํด๋์ค๋ก ๊ฒฐํฉํ์ฌ API ๊ตฌ์กฐ๋ฅผ ๋จ์ํํ๊ณ ์ฝ๋ ์ค๋ณต์ ์ค์
๋๋ค. ViewSets๋ ์ด๋ฌํ ํ์ค ์์
์ด ์ผ๋ฐ์ ์ผ๋ก ํ์ํ ๋ชจ๋ธ ๊ธฐ๋ฐ API๋ก ์์
ํ ๋ ํนํ ์ ์ฉํฉ๋๋ค. ViewSet์ ํน์ ๋ฆฌ์์ค์ ๋ํ ์์
์ ๋
ผ๋ฆฌ์ ๊ทธ๋ฃน์ผ๋ก ์๊ฐํ์ญ์์ค.
ViewSet ์ฌ์ฉ์ ์ด์
- ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ: ViewSets๋ ์ผ๋ฐ์ ์ธ API ๋ก์ง์ ๋จ์ผ ํด๋์ค์ ์บก์ํํ์ฌ ์ฝ๋ ์ฌ์ฌ์ฉ์ ์ด์งํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ค๋ณต์ฑ์ด ์ค์ด๋ค๊ณ ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์ ์ง ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
- ๊ฐ์ํ๋ ๋ผ์ฐํ : ViewSets๋ ๊ด๋ จ ๋ณด๊ธฐ๋ฅผ ๋จ์ผ URL ์ ๋์ฌ๋ก ๊ทธ๋ฃนํํ์ฌ ๋ผ์ฐํ ์ ๋จ์ํํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ ๊น๋ํ๊ณ ๊ตฌ์ฑ๋ URL ๊ตฌ์กฐ๊ฐ ๋ฉ๋๋ค.
- ๊ฐ์๋ ์์ฉ๊ตฌ: ViewSets๋ ์ผ๋ฐ์ ์ธ API ์์ ์ ๋ํ ๊ธฐ๋ณธ ๊ตฌํ์ ์ ๊ณตํ์ฌ ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ์ค์ ๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ํ ์ฌ์ฉ์ ์ง์ ๋ก์ง ๊ตฌํ์ ์ง์คํ ์ ์์ต๋๋ค.
- ํฅ์๋ ๊ฐ๋ ์ฑ: ViewSets๋ ๊ด๋ จ ๋ณด๊ธฐ๋ฅผ ๋จ์ผ ํด๋์ค๋ก ๊ตฌ์ฑํ์ฌ ์ฝ๋ ๊ฐ๋ ์ฑ์ ํฅ์์ํต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด API ๊ตฌ์กฐ๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ๊ณ ํ์ํ ์ ์์ต๋๋ค.
- ์ผ๊ด์ฑ: ViewSets๋ ํ์ค ์์ ๋ฐ ๊ท์น ์ธํธ๋ฅผ ์ ์ฉํ์ฌ API ์ ์ฒด์ ์ผ๊ด์ฑ์ ๋ณด์ฅํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด API๊ฐ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์์ง๋๋ค.
ViewSet์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
ViewSet์ ์ฌ์ฉํ์ฌ ์ ํ ๊ด๋ฆฌ๋ฅผ ์ํ API๋ฅผ ๋ง๋๋ ๊ฐ๋จํ ์์ ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค. ๋จผ์ ๋ชจ๋ธ์ ์ ์ํฉ๋๋ค.
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
๋ค์์ผ๋ก Product
๋ชจ๋ธ์ ๋ํ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ ์ํฉ๋๋ค.
# serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
์ด์ Product
๋ชจ๋ธ์ ๋ํ ViewSet์ ๋ง๋ญ๋๋ค.
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
๋ง์ง๋ง์ผ๋ก URL ๋ผ์ฐํ ์ ๊ตฌ์ฑํฉ๋๋ค.
# urls.py
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'products', views.ProductViewSet)
urlpatterns = [
path('', include(router.urls)),
]
์ด ๊ตฌ์ฑ์ ๋ค์ API ์๋ํฌ์ธํธ๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
/products/
(GET: list, POST: create)/products/{id}/
(GET: retrieve, PUT: update, PATCH: partial_update, DELETE: destroy)
ModelViewSet
์ ๋ชจ๋ ํ์ค CRUD ์์
์ ๋ํ ๊ธฐ๋ณธ ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค. queryset
์์ฑ์ ViewSet์ด ์๋ํด์ผ ํ๋ ๊ฐ์ฒด ์ธํธ๋ฅผ ์ง์ ํ๊ณ serializer_class
์์ฑ์ ๋ฐ์ดํฐ๋ฅผ ์ง๋ ฌํํ๊ณ ์ญ์ง๋ ฌํํ๋ ๋ฐ ์ฌ์ฉํ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ง์ ํฉ๋๋ค.
ViewSet ์ ํ
DRF๋ ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก์ ๋ง๋ ์ฌ๋ฌ ๋ด์ฅ ViewSet ํด๋์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
ViewSet
: ๋ชจ๋ ViewSet์ ๊ธฐ๋ณธ ํด๋์ค์ ๋๋ค. ์์ฒญ ๋ฐ ์๋ต ์ฒ๋ฆฌ๋ฅผ ์ํ ๊ธฐ๋ณธ ์ธํ๋ผ๋ฅผ ์ ๊ณตํฉ๋๋ค.ReadOnlyModelViewSet
: ์ฝ๊ธฐ ์ ์ฉ ์์ (list
๋ฐretrieve
)์ ์ ๊ณตํ๋ ViewSet์ ๋๋ค. ๋ฐ์ดํฐ ๊ฒ์๋ง ํ์ฉํ๋ API์ ์ ์ฉํฉ๋๋ค.ModelViewSet
: ๋ชจ๋ ํ์ค CRUD ์์ (list
,create
,retrieve
,update
๋ฐdestroy
)์ ์ ๊ณตํ๋ ViewSet์ ๋๋ค. ๋ชจ๋ธ ๊ธฐ๋ฐ API์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ViewSet์ ๋๋ค.GenericViewSet
: ์ผ๋ฐ์ ์ธ API ์์ ์ ๋ํ ์ผ๋ฐ ๊ตฌํ์ ์ ๊ณตํ๋ ViewSet์ ๋๋ค. ์ฌ์ฉ์ ์ง์ ViewSet์ ๋ง๋๋ ๋ฐ ๊ธฐ๋ณธ ํด๋์ค๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ๋ฐ๋ฅธ ViewSet ์ ํ์ API์ ํน์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. ์ฝ๊ธฐ ์ ์ฉ ์์
๋ง ํ์ํ ๊ฒฝ์ฐ ReadOnlyModelViewSet
์ ์ฌ์ฉํฉ๋๋ค. ๋ชจ๋ ํ์ค CRUD ์์
์ด ํ์ํ ๊ฒฝ์ฐ ModelViewSet
์ ์ฌ์ฉํฉ๋๋ค. API ๋์์ ๋ํ ๋ ๋ง์ ์ ์ด๊ฐ ํ์ํ ๊ฒฝ์ฐ GenericViewSet
๋๋ ViewSet
์์ ์์ํ์ฌ ์ฌ์ฉ์ ์ง์ ViewSet์ ๋ง๋ค ์ ์์ต๋๋ค.
ViewSet ์ฌ์ฉ์ ์ ์
๋ด์ฅ ViewSet์ API๋ฅผ ๋ง๋๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง๋ง ํน์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๊ธฐ ์ํด ํด๋น ๋์์ ์ฌ์ฉ์ ์ ์ํด์ผ ํ ์ ์์ต๋๋ค. DRF๋ ๋ฉ์๋ ์ฌ์ ์, ์ฌ์ฉ์ ์ง์ ์์ ์ถ๊ฐ ๋ฐ ์ฌ์ฉ์ ์ง์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ ์ฌ์ฉ์ ํฌํจํ์ฌ ViewSet์ ์ฌ์ฉ์ ์ ์ํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
๋ฉ์๋ ์ฌ์ ์
ViewSet ํด๋์ค์์ ์ด๋ฆ์ด ๊ฐ์ ๋ฉ์๋๋ฅผ ์ ์ํ์ฌ ํ์ค API ์์
์ ๊ธฐ๋ณธ ๊ตฌํ์ ์ฌ์ ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์ ํ์ ์ฌ์ฉ์ ์ง์ ๋ก์ง์ ์ถ๊ฐํ๊ธฐ ์ํด create
๋ฉ์๋๋ฅผ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.response import Response
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
# Add custom logic here before creating the object
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
์ด ์์ ์์ create
๋ฉ์๋๋ ๊ธฐ๋ณธ ๊ตฌํ์ ์ฌ์ ์ํ๊ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์ ์ ์ฌ์ฉ์ ์ง์ ๋ก์ง์ ์ถ๊ฐํฉ๋๋ค. perform_create
๋ฉ์๋๋ ์ค์ ๋ก ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์ํด ํธ์ถ๋๊ณ ์๋ต์ 201 Created
์ํ ์ฝ๋๋ก ๋ฐํ๋ฉ๋๋ค.
์ฌ์ฉ์ ์ง์ ์์ ์ถ๊ฐ
@action
๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ViewSet์ ์ฌ์ฉ์ ์ง์ ์์
์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ฌ์ฉ์ ์ง์ ์์
์ ์ฌ์ฉํ๋ฉด ViewSet์์ ๊ด๋ฆฌํ๋ ๋ฆฌ์์ค์ ๋ํด ํน์ ์์
์ ์ํํ๋ ์ API ์๋ํฌ์ธํธ๋ฅผ ์ ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ ํ์ ์ถ์ฒ ์ ํ์ผ๋ก ํ์ํ๋ ์์
์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
@action(detail=True, methods=['post'])
def feature(self, request, pk=None):
product = self.get_object()
product.is_featured = True
product.save()
serializer = self.get_serializer(product)
return Response(serializer.data)
์ด ์์ ์์ @action
๋ฐ์ฝ๋ ์ดํฐ๋ ์ ํ์ ์ถ์ฒ ์ ํ์ผ๋ก ํ์ํ๋ ์ API ์๋ํฌ์ธํธ /products/{id}/feature/
๋ฅผ ์ ์ํฉ๋๋ค. detail=True
์ธ์๋ ์์
์ด ๋ชจ๋ธ์ ํน์ ์ธ์คํด์ค์์ ์๋ํจ์ ๋ํ๋
๋๋ค. methods=['post']
์ธ์๋ ์์
์ด POST ์์ฒญ๋ง ์๋ฝํ๋๋ก ์ง์ ํฉ๋๋ค.
์ฌ์ฉ์ ์ง์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ ์ฌ์ฉ
์ฌ์ฉ์ ์ง์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ฌ ViewSet์์ ๋ฐ์ดํฐ๋ฅผ ์ง๋ ฌํํ๊ณ ์ญ์ง๋ ฌํํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค. ์ด๋ ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ฌ์ฉ์ ์ง์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํํด์ผ ํ ๋ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์ ์ง์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ฌ API ์๋ต์ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ ์ ์์ต๋๋ค.
# serializers.py
from rest_framework import serializers
from .models import Product, Category
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id', 'name']
class ProductSerializer(serializers.ModelSerializer):
category = CategorySerializer(read_only=True)
class Meta:
model = Product
fields = '__all__'
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
์ด ์์ ์์ ProductSerializer
๋ ๊ด๋ จ ์นดํ
๊ณ ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์ง๋ ฌํํ๊ธฐ ์ํด CategorySerializer
๋ฅผ ํฌํจํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋จ์ผ API ์์ฒญ์์ ์ ํ ์ ๋ณด์ ํจ๊ป ์นดํ
๊ณ ๋ฆฌ ์ ๋ณด๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค.
๊ณ ๊ธ ViewSet ๊ธฐ์
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ ๋ฐ ์ฌ์ฉ์ ์ ์ ์ธ์๋ ViewSets๋ ์ ๊ตํ API๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ๊ณ ๊ธ ๊ธฐ์ ์ ์ ๊ณตํฉ๋๋ค.
ํํฐ๋ง
DRF๋ ์์ฒญ ๋งค๊ฐ๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฟผ๋ฆฌ ์งํฉ์ ํํฐ๋งํ ์ ์๋ ๊ฐ๋ ฅํ ํํฐ๋ง ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. filter_backends
์์ฑ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉํ ํํฐ๋ง ๋ฐฑ์๋๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด SearchFilter
๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ์ด๋ฆ ๋๋ ์ค๋ช
์ผ๋ก ์ ํ์ ๊ฒ์ํ ์ ์๋๋ก ํ ์ ์์ต๋๋ค.
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework import filters
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['name', 'description']
์ด ์์ ์์ filter_backends
์์ฑ์ SearchFilter
๋ฅผ ์ฌ์ฉํด์ผ ํจ์ ์ง์ ํฉ๋๋ค. search_fields
์์ฑ์ ๊ฒ์ํด์ผ ํ๋ ํ๋๋ฅผ ์ง์ ํฉ๋๋ค.
ํ์ด์ง ๋งค๊น
DRF๋ ์ฟผ๋ฆฌ ์งํฉ์ ๋ ์์ ํ์ด์ง๋ก ๋๋ ์ ์๋ ํ์ด์ง ๋งค๊น ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ฒ๋ฆฌํ ๋ ์ ์ฉํฉ๋๋ค. pagination_class
์์ฑ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉํ ํ์ด์ง ๋งค๊น ํด๋์ค๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด PageNumberPagination
์ ์ฌ์ฉํ์ฌ ํ์ด์ง ๋ฒํธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ํ์ด์ง ๋งค๊นํ ์ ์์ต๋๋ค.
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.pagination import PageNumberPagination
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = PageNumberPagination
์ด ์์ ์์ pagination_class
์์ฑ์ PageNumberPagination
์ ์ฌ์ฉํด์ผ ํจ์ ์ง์ ํฉ๋๋ค. ์ฌ์ฉ์ ์ง์ ํ์ด์ง ๋งค๊น ํด๋์ค๋ฅผ ๋ง๋ค์ด ํ์ด์ง ๋งค๊น ๋์์ ์ฌ์ฉ์ ์ ์ํ ์๋ ์์ต๋๋ค.
์ธ์ฆ ๋ฐ ๊ถํ
DRF๋ API ์๋ํฌ์ธํธ์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ์ดํ ์ ์๋ ์ ์ฐํ ์ธ์ฆ ๋ฐ ๊ถํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. authentication_classes
๋ฐ permission_classes
์์ฑ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉํ ์ธ์ฆ ๋ฐ ๊ถํ ํด๋์ค๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด TokenAuthentication
์ ์ฌ์ฉํ์ฌ ํ ํฐ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๊ณ IsAuthenticated
๊ถํ์ ์ฌ์ฉํ์ฌ ์ธ์ฆ๋ ์ฌ์ฉ์๋ง API์ ์ก์ธ์คํ๋๋ก ํ ์ ์์ต๋๋ค.
# views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
์ด ์์ ์์ authentication_classes
์์ฑ์ TokenAuthentication
์ ์ฌ์ฉํด์ผ ํจ์ ์ง์ ํ๊ณ permission_classes
์์ฑ์ IsAuthenticated
๊ถํ์ ์ฌ์ฉํด์ผ ํจ์ ์ง์ ํฉ๋๋ค.
ViewSet ์ฌ์ฉ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
ViewSet์ด ์ ์ค๊ณ๋๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ๋๋ก ํ๋ ค๋ฉด ๋ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด์ญ์์ค.
- ViewSet์ ์ง์ค์ ์ผ๋ก ์ ์งํ์ญ์์ค: ๊ฐ ViewSet์ ๋จ์ผ ๋ฆฌ์์ค ๋๋ ๋ฐ์ ํ๊ฒ ๊ด๋ จ๋ ๋ฆฌ์์ค ์ธํธ๋ฅผ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค. ์ฌ๋ฌ ๊ฐ์ ๊ด๋ จ ์๋ ์์ ์ ์ฒ๋ฆฌํ๋ ์ง๋์น๊ฒ ๋ณต์กํ ViewSet์ ๋ง๋ค์ง ๋ง์ญ์์ค.
- ์ ์ ํ ViewSet ์ ํ์ ์ฌ์ฉํ์ญ์์ค: API์ ์๊ตฌ ์ฌํญ์ ๊ฐ์ฅ ์ ํฉํ ViewSet ์ ํ์ ์ ํํ์ญ์์ค. ์ฝ๊ธฐ ์ ์ฉ API์๋
ReadOnlyModelViewSet
์ ์ฌ์ฉํ๊ณ , CRUD API์๋ModelViewSet
์ ์ฌ์ฉํ๊ณ , ์ฌ์ฉ์ ์ง์ API์๋GenericViewSet
๋๋ViewSet
์ ์ฌ์ฉํ์ญ์์ค. - RESTful ์์น์ ๋ฐ๋ฅด์ญ์์ค: RESTful ์์น์ ๋ฐ๋ผ API ์๋ํฌ์ธํธ๋ฅผ ์ค๊ณํ์ญ์์ค. ํ์ค HTTP ๋ฉ์๋(GET, POST, PUT, PATCH, DELETE)๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค์ ๋ํ ์์ ์ ์ํํ์ญ์์ค.
- ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ญ์์ค: API๋ก ๋ณด๋ด๊ณ API์์ ๋ฐ๋ ๋ฐ์ดํฐ๋ฅผ ์ ํจ์ฑ ๊ฒ์ฌํ๋ ๋ฐ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ญ์์ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๊ณ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
- ์ ์ ํ ์ธ์ฆ ๋ฐ ๊ถํ์ ๊ตฌํํ์ญ์์ค: ์ ์ ํ ์ธ์ฆ ๋ฐ ๊ถํ์ ๊ตฌํํ์ฌ API ์๋ํฌ์ธํธ๋ฅผ ๋ณดํธํ์ญ์์ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฌด๋จ ์ก์ธ์ค๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
- ํฌ๊ด์ ์ธ ํ ์คํธ๋ฅผ ์์ฑํ์ญ์์ค: ViewSet์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด ํฌ๊ด์ ์ธ ํ ์คํธ๋ฅผ ์์ฑํ์ญ์์ค. ์ด๋ ๊ฒ ํ๋ฉด ํ๊ท๋ฅผ ๋ฐฉ์งํ๊ณ ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์ ์ง ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
๊ตญ์ ํ(i18n) ๋ฐ ํ์งํ(l10n) ๊ณ ๋ ค ์ฌํญ
๊ธ๋ก๋ฒ ๋์์ ์ํ API๋ฅผ ๊ตฌ์ถํ ๋ ๊ตญ์ ํ(i18n) ๋ฐ ํ์งํ(l10n)๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค. ViewSet์ ์ฌ๋ฌ ์ธ์ด์ ์ง์ญ์ ์ง์ํ๋๋ก ์กฐ์ ํ ์ ์์ต๋๋ค.
- ์ง๋ ฌํ ํ๋ก๊ทธ๋จ ํ๋: ๋ฒ์ญ๋ ํ๋ ๋ ์ด๋ธ๊ณผ ๋์๋ง ํ
์คํธ๋ฅผ ํ์ํ๊ธฐ ์ํด ์ ์ ํ ๋ฒ์ญ ๊ธฐ๋ฅ(์: Django์ i18n ํ๋ ์์ํฌ์
gettext
)์ด ์๋ DRF์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ ํ๋๋ฅผ ์ฌ์ฉํ์ญ์์ค. - ์ค๋ฅ ๋ฉ์์ง: API์์ ๋ฐํ๋ ์ค๋ฅ ๋ฉ์์ง๊ฐ ์ฌ์ฉ์์ ์ ํธํ๋ ์ธ์ด๋ก ๋ฒ์ญ๋์๋์ง ํ์ธํ์ญ์์ค.
- ๋ ์ง ๋ฐ ์๊ฐ ํ์: ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ ํ ๋ ์ง ๋ฐ ์๊ฐ ํ์์ ์ฌ์ฉํ์ญ์์ค. DRF๋ ๋ ์ง ๋ฐ ์๊ฐ ํ์์ ์ฌ์ฉ์ ์ ์ํ๊ธฐ ์ํ ์ต์ ์ ์ ๊ณตํฉ๋๋ค.
- ํตํ ํ์: ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ๋ฐ๋ผ ํตํ ๊ฐ์ ํ์ํํ์ญ์์ค. ํตํ ํ์ ์ง์ ์ ์ํด
babel
๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค. ์๋ฅผ ๋ค์ด USD์ 1234.56 ๊ฐ๊ฒฉ์ ๋ฏธ๊ตญ์์๋ $1,234.56์ผ๋ก ํ์์ด ์ง์ ๋ ์ ์์ง๋ง ์ผ๋ถ ์ ๋ฝ ๊ตญ๊ฐ์์๋ 1.234,56 $๋ก ํ์์ด ์ง์ ๋ ์ ์์ต๋๋ค. - ์๊ฐ๋: ์๊ฐ๋๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ญ์์ค. ๋ ์ง์ ์๊ฐ์ UTC๋ก ์ ์ฅํ๊ณ ํ์ํ ๋ ์ฌ์ฉ์์ ํ์ง ์๊ฐ๋๋ก ๋ณํํ์ญ์์ค.
์๋ฅผ ๋ค์ด ์ ํ์๋ ๋ฒ์ญํด์ผ ํ๋ ์ค๋ช ์ด ์์ ์ ์์ต๋๋ค. ์ง๋ ฌํ ํ๋ก๊ทธ๋จ ๋ด์์ Django์ ๋ฒ์ญ ์์คํ ์ ์ฌ์ฉํฉ๋๋ค.
# serializers.py
from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
description = serializers.CharField(help_text=_("Product description"))
class Meta:
model = Product
fields = '__all__'
๊ทธ๋ฆฌ๊ณ ์ด ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ๋ ํ ํ๋ฆฟ ๋๋ ์ฝ๋์์ ์ ์ ํ ์ธ์ด๊ฐ ํ์ฑํ๋์๋์ง ํ์ธํ์ญ์์ค.
์์ : ๊ตญ์ ์ง์์ด ์๋ ์ ์ ์๊ฑฐ๋ API
์ ์ธ๊ณ์ ์ผ๋ก ์ ํ์ ํ๋งคํ๋ ์ ์ ์๊ฑฐ๋ API๋ฅผ ์์ํด๋ณด์ญ์์ค. Product
๋ชจ๋ธ์๋ name
, description
, price
๋ฐ image
์ ๊ฐ์ ํ๋๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค. API๋ ์ฌ๋ฌ ์ธ์ด์ ํตํ๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค.
ViewSet์ ์ ํ์ ๋ํ ๊ธฐ๋ณธ CRUD ์์ ์ ์ฒ๋ฆฌํฉ๋๋ค. ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์ ํ ์ด๋ฆ๊ณผ ์ค๋ช ์ ๋ฒ์ญ์ ์ง์ํ๋๋ก ์ฌ์ฉ์ ์ ์๋ฉ๋๋ค. API์๋ ์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ์ ํ์ ๊ฒ์ํ๊ณ , ๊ฐ๊ฒฉ ๋ฒ์๋ณ๋ก ์ ํ์ ํํฐ๋งํ๊ณ , ํค์๋๋ก ์ ํ์ ๊ฒ์ํ๊ธฐ ์ํ ์๋ํฌ์ธํธ๋ ํฌํจ๋ฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ ๊ตญ์ ํ, ํนํ ์ธ์ด ๊ฐ์ ๋ค๋ฅผ ์ ์๋ ๊ฒ์์ด ๋ฐ ์ ํ ์ค๋ช ๊ณผ ๊ด๋ จํ์ฌ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์์ URL:
/en/products/
- ์์ด๋ก ๋ ์ ํ ๋ชฉ๋ก/fr/products/
- ํ๋์ค์ด๋ก ๋ ์ ํ ๋ชฉ๋ก/en/products/?currency=USD
- USD๋ก ๋ ์ ํ ๋ชฉ๋ก/fr/products/123/?currency=EUR
- ํ๋์ค์ด๋ก ๋ ์ ํ 123์ ์ธ๋ถ ์ ๋ณด, EUR๋ก ํ์๋ ๊ฐ๊ฒฉ
๊ฒฐ๋ก
Django REST Framework ViewSets๋ API ์๋ํฌ์ธํธ๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ๋ ฅํ๊ณ ์ฐ์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๊ด๋ จ ๋ณด๊ธฐ๋ฅผ ๋จ์ผ ํด๋์ค์ ์บก์ํํจ์ผ๋ก์จ ViewSets๋ ์ฝ๋ ์ฌ์ฌ์ฉ์ ์ด์งํ๊ณ ๋ผ์ฐํ ์ ๋จ์ํํ๋ฉฐ ์ฝ๋ ๊ฐ๋ ์ฑ์ ํฅ์์ํต๋๋ค. ๋ฉ์๋ ์ฌ์ ์, ์ฌ์ฉ์ ์ง์ ์์ ์ถ๊ฐ ๋ฐ ์ฌ์ฉ์ ์ง์ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ ์ฌ์ฉ์ ํตํด ViewSet์ ์ฌ์ฉ์ ์ ์ํ ์ ์๋ ๊ธฐ๋ฅ์ ํตํด API์ ํน์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋๋ก ์กฐ์ ํ ์ ์์ต๋๋ค. ์ด ๊ฐ์ด๋์ ์ค๋ช ๋ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ViewSet์ด ์ ์ค๊ณ๋๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ๋๋ก ํ์ฌ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ธ API๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
๊ธ๋ก๋ฒ ๋์์ ์ํ API๋ฅผ ๊ตฌ์ถํ ๋ ๊ตญ์ ํ ๋ฐ ํ์งํ๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค. ์ฌ๋ฌ ์ธ์ด, ํตํ ๋ฐ ์๊ฐ๋๋ฅผ ์ง์ํ๋๋ก ViewSet ๋ฐ ์ง๋ ฌํ ํ๋ก๊ทธ๋จ์ ์กฐ์ ํ์ฌ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ์ํํ ๊ฒฝํ์ ์ ๊ณตํ์ญ์์ค.
ViewSet์ ๋ง์คํฐํ๋ฉด Django REST Framework ๊ธฐ์ ์ ํ ๋จ๊ณ ๋์ด์ฌ๋ฆฌ๊ณ ๊ฐ๋ ฅํ๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ API๋ฅผ ๊ตฌ์ถํ ์ ์์ต๋๋ค. ์ด๋ ๊ณ ํ์ง ์ํํธ์จ์ด์ ๊ธ๋ก๋ฒ ๊ณ ๊ฐ์๊ฒ ๊ธ์ ์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ธฐ์ฌํฉ๋๋ค.
์ด ๊ฐ์ด๋๋ Django REST Framework ํ๋ก์ ํธ์์ ViewSet์ ์ดํดํ๊ณ ๊ตฌํํ๊ธฐ ์ํ ๊ฒฌ๊ณ ํ ๊ธฐ๋ฐ ์ญํ ์ ํด์ผ ํฉ๋๋ค. ์ง์ ํ ViewSet ๋ง์คํฐ๊ฐ ๋๊ธฐ ์ํด ๊ณ์ ์ฐ์ตํ๊ณ ์คํํ๊ณ DRF ์ค๋ช ์๋ฅผ ํ์ํ์ญ์์ค!