Django REST Framework (DRF)์์ ํจ๊ณผ์ ์ธ QuerySet ํํฐ๋ง ๋ฐ ๊ฒ์ ๊ธฐ์ ์ ํ์ํ์ฌ ๊ฐ๋ ฅํ๊ณ ํ์ฅ ๊ฐ๋ฅํ API๋ฅผ ๊ตฌ์ถํ์ธ์. ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ๋ฐ์ดํฐ ๊ฒ์ ์ต์ ํ๋ฅผ ์ํด ํํฐ๋ง, ์ ๋ ฌ ๋ฐ ๊ฒ์์ ๋ฏธ๋ฌํ ์ฐจ์ด๋ฅผ ์์๋ณด์ธ์.
DRF ํํฐ๋ง vs. ๊ฒ์: QuerySet ํํฐ๋ง ์ ๋ต ๋ง์คํฐํ๊ธฐ
์น ๊ฐ๋ฐ ์์ญ์์ ํจ์จ์ ์ด๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ API๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ๊ฐ์ฅ ์ค์ํฉ๋๋ค. Django REST Framework (DRF)๋ RESTful API๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ํดํท์ ์ ๊ณตํ๋ฉฐ, ์ฌ๊ธฐ์๋ ๋ฐ์ดํฐ ํํฐ๋ง ๋ฐ ๊ฒ์์ ์ํ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ด ํฌํจ๋ฉ๋๋ค. ์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ DRF์ QuerySet ํํฐ๋ง ๊ธฐ๋ฅ์ ๋ณต์ก์ฑ์ ๊น์ด ํ๊ณ ๋ค์ด, ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ๋ฐ์ดํฐ ๊ฒ์์ ์ต์ ํํ๊ณ API ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ค์ํ ์ ๋ต์ ํ์ํฉ๋๋ค. ์ธ์ ํํฐ๋ง์ ์ฌ์ฉํ๊ณ , ์ธ์ ๊ฒ์์ ์ฌ์ฉํ๋ฉฐ, ์ด๋ฌํ ๊ธฐ์ ์ ์ต๋์ ํจ๊ณผ๋ฅผ ์ํด ์ด๋ป๊ฒ ๊ฒฐํฉํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
ํํฐ๋ง ๋ฐ ๊ฒ์์ ์ค์์ฑ ์ดํดํ๊ธฐ
ํํฐ๋ง๊ณผ ๊ฒ์์ ๊ฑฐ์ ๋ชจ๋ API์์ ๊ธฐ๋ณธ์ ์ธ ์์ ์ ๋๋ค. ์ด๋ ํด๋ผ์ด์ธํธ(์: ์น ์ ํ๋ฆฌ์ผ์ด์ , ๋ชจ๋ฐ์ผ ์ฑ)๊ฐ ์์ ์ ๊ธฐ์ค์ ๋ฐ๋ผ ํน์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ด ์๋ค๋ฉด API๋ ๋ฒ๊ฑฐ๋กญ๊ณ ๋นํจ์จ์ ์ด์ด์ ํด๋ผ์ด์ธํธ๊ฐ ์ ์ฒด ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ค์ด๋ก๋ํ ๋ค์ ์์ฒด์ ์ผ๋ก ํํฐ๋งํ๋๋ก ๊ฐ์ํ ๊ฒ์ ๋๋ค. ์ด๋ ๋ค์์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค:
- ๋๋ฆฐ ์๋ต ์๊ฐ: ํนํ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ์ ๊ฒฝ์ฐ, ๋ง์ ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ฒ๋ฆฌํ๋ ๋ถ๋ด์ด ์๋ต ์๊ฐ์ ์ฆ๊ฐ์ํต๋๋ค.
- ๋์ญํญ ์๋น ์ฆ๊ฐ: ํด๋ผ์ด์ธํธ๊ฐ ๋ถํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ค์ด๋ก๋ํ๋ ๋ฐ ๋ ๋ง์ ๋์ญํญ์ ์๋นํฉ๋๋ค. ์ด๋ ์ธํฐ๋ท ์ ์์ด ์ ํ์ ์ด๊ฑฐ๋ ๋ฐ์ดํฐ ๋น์ฉ์ด ๋์ ์ง์ญ์ ์ฌ์ฉ์์๊ฒ ์ค์ํ ๋ฌธ์ ์ ๋๋ค.
- ์ ์กฐํ ์ฌ์ฉ์ ๊ฒฝํ: ๋๋ฆฐ API๋ ์ฌ์ฉ์์๊ฒ ์ข์ ๊ฐ์ ์๊ฒจ์ฃผ๊ณ ์ ๋ฐ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ฌ์ฉ์ฑ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
ํจ๊ณผ์ ์ธ ํํฐ๋ง ๋ฐ ๊ฒ์ ๋ฉ์ปค๋์ฆ์ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ์ํํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ธ๋, ๋ธ๋ผ์ง ๋๋ ์ธ๋๋ค์์์ ๊ฐ์ด ์ธํฐ๋ท ์ธํ๋ผ๊ฐ ํฌ๊ฒ ๋ค๋ฅผ ์ ์๋ ๊ตญ๊ฐ์ ์ฌ์ฉ์์๊ฒ ๋ฏธ์น๋ ์ํฅ์ ๊ณ ๋ คํ์ญ์์ค. ๋ฐ์ดํฐ ๊ฒ์์ ์ต์ ํํ๋ฉด ์ด๋ฌํ ์ฌ์ฉ์์๊ฒ ์ง์ ์ ์ธ ์ด์ ์ด ์์ต๋๋ค.
DRF์ ๋ด์ฅ ํํฐ๋ง ๊ธฐ๋ฅ
DRF๋ QuerySet ํํฐ๋ง์ ์ํ ์ฌ๋ฌ ๋ด์ฅ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค:
1. `OrderingFilter`
`OrderingFilter` ํด๋์ค๋ฅผ ํตํด ํด๋ผ์ด์ธํธ๋ ํ๋ ์ด์์ ํ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฒฐ๊ณผ์ ์์๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. ์ด๋ ๋ ์ง, ๊ฐ๊ฒฉ, ์ด๋ฆ ๋๋ ๊ธฐํ ๊ด๋ จ ์์ฑ๋ณ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฌํ๋ ๋ฐ ํนํ ์ ์ฉํฉ๋๋ค. ํด๋ผ์ด์ธํธ๋ ์ผ๋ฐ์ ์ผ๋ก `?ordering=field_name` ๋๋ `?ordering=-field_name` (๋ด๋ฆผ์ฐจ์)๊ณผ ๊ฐ์ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์์๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค.
์์:
`Product` ๋ชจ๋ธ์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length="200")
price = models.DecimalField(max_digits=10, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
๊ทธ๋ฆฌ๊ณ ํด๋น ์๋ฆฌ์ผ๋ผ์ด์ ์ ๋ทฐ์ :
from rest_framework import serializers, viewsets
from .models import Product
from rest_framework.filters import OrderingFilter
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['name', 'price', 'created_at'] # Fields allowed for ordering
์ด ์์์์ ํด๋ผ์ด์ธํธ๋ `ordering` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ์ ์ ๋ ฌํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, `?ordering=price`๋ ๊ฐ๊ฒฉ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ณ , `?ordering=-price`๋ ๊ฐ๊ฒฉ์ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํฉ๋๋ค. ์ด๋ฌํ ์ ์ฐ์ฑ์ ์ฌ์ฉ์๊ฐ ์์ ์ ํ์์ ๋ฐ๋ผ ๋ฐ์ดํฐ ํ์๋ฅผ ๋ง์ถค ์ค์ ํ๋ ๋ฐ ํ์์ ์ ๋๋ค. ์ ์์๊ฑฐ๋ ํ๋ซํผ์ ์์ํด ๋ณด์ธ์. ์ฌ์ฉ์๋ ๊ฐ๊ฒฉ(๋ฎ์ ๊ฐ๊ฒฉ๋ถํฐ ๋์ ๊ฐ๊ฒฉ๊น์ง, ๋๋ ๋์ ๊ฐ๊ฒฉ๋ถํฐ ๋ฎ์ ๊ฐ๊ฒฉ๊น์ง) ๋๋ ์ธ๊ธฐ๋๋ณ๋ก ์ฝ๊ฒ ์ ๋ ฌํ ์ ์์ด์ผ ํฉ๋๋ค.
2. `SearchFilter`
`SearchFilter`๋ ๋ชจ๋ธ์ ์ง์ ๋ ํ๋์์ ํ ์คํธ ๊ธฐ๋ฐ ๊ฒ์์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ํด๋ผ์ด์ธํธ๋ ํค์๋๋ ๊ตฌ๋ฌธ์ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก `?search=keyword`์ ๊ฐ์ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. DRF์ `SearchFilter`๋ ๊ธฐ๋ณธ์ ์ผ๋ก `icontains` ์กฐํ๋ฅผ ํ์ฉํ์ฌ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋ ๊ฒ์์ ์ํํฉ๋๋ค. ์ต์ ์ ์ฑ๋ฅ์ ์ํด, ํนํ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ์ ๊ฒฝ์ฐ, ๋์ค์ ์ค๋ช ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ณ ์ ์ฒด ํ ์คํธ ๊ฒ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ ๊ฐ์น๊ฐ ์์ต๋๋ค.
์์:
`Product` ๋ชจ๋ธ์ ๊ณ์ํด์:
from rest_framework import serializers, viewsets
from .models import Product
from rest_framework.filters import SearchFilter
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [SearchFilter]
search_fields = ['name', 'description'] # Fields allowed for searching
์ด์ ํด๋ผ์ด์ธํธ๋ `search` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ์ ๊ฒ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, `?search=laptop`์ ์ด๋ฆ์ด๋ ์ค๋ช ์ 'laptop'์ด ํฌํจ๋ ์ ํ์ ๋ฐํํฉ๋๋ค. ์ ์ธ๊ณ ์ฌ์ฉ์์ ์๊ตฌ ์ฌํญ์ ๊ณ ๋ คํ์ญ์์ค. ์ฌ๋ฌ ์ธ์ด๋ก ์ ํ์ ๊ฒ์ํ๋ ค๋ฉด ํ ์คํธ ์ฒ๋ฆฌ ๋ฐ ์์ธํ์ ๋ํ ์ ์คํ ๊ณํ์ด ํ์ํฉ๋๋ค.
3. `DjangoFilterBackend` (ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
`django-filter` ํจํค์ง๋ ๋ ๊ณ ๊ธ ํํฐ๋ง ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ค์ํ ํ๋ ์ ํ, ๊ด๊ณ ๋ฐ ๋ณต์กํ ๋ ผ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์ ์ง์ ํํฐ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ๋ณต์กํ ํํฐ๋ง ์๊ตฌ ์ฌํญ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๊ฐ์ฅ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค.
์ค์น: `pip install django-filter`
์์:
from rest_framework import serializers, viewsets
from .models import Product
from django_filters import rest_framework as filters
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class ProductFilter(filters.FilterSet):
min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
name = filters.CharFilter(field_name='name', lookup_expr='icontains')
class Meta:
model = Product
fields = ['name', 'created_at']
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.DjangoFilterBackend]
filterset_class = ProductFilter
์ด ์์๋ `icontains` ์กฐํ๋ฅผ ์ฌ์ฉํ์ฌ ์ต์ ๋ฐ ์ต๋ ๊ฐ๊ฒฉ, ๊ทธ๋ฆฌ๊ณ ์ด๋ฆ์ผ๋ก ์ ํ์ ํํฐ๋งํ ์ ์๋๋ก ํฉ๋๋ค. ์ด๋ `django-filter`์ ๊ฐ๋ ฅํจ๊ณผ ์ ์ฐ์ฑ์ ๋ณด์ฌ์ค๋๋ค. ์ด๋ ์ ์์๊ฑฐ๋ ๋๋ ์ฝํ ์ธ ๊ด๋ฆฌ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ์๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์ธ๋ถํํ ์ ์๋๋ก ํ์ฌ ๋งค์ฐ ์ ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๊ฐ๊ฒฉ ๋ฒ์, ์ ํ ์นดํ ๊ณ ๋ฆฌ ๋๋ ์์ฑ ๋ ์ง๋ณ ํํฐ๋ง์ ๋ชจ๋ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ค์ฉ๋์ฑ ๋๋ถ์ ์ด ๊ธฐ๋ฅ์ ๋ค์ํ ๊ธ๋ก๋ฒ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋ ๋ฐ ์ธ๊ธฐ ์๋ ์ต์ ์ด ๋ฉ๋๋ค.
์ฌ๋ฐ๋ฅธ ํํฐ๋ง ์ ๋ต ์ ํ: ํํฐ๋ง vs. ๊ฒ์
ํํฐ๋ง๊ณผ ๊ฒ์ ์ค ์ด๋ค ๊ฒ์ ์ ํํ ์ง๋ API์ ํน์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ํต์ฌ์ ์ธ ์ฐจ์ด์ ์ ์๋์ ์์ต๋๋ค:
- ํํฐ๋ง: ๋ฏธ๋ฆฌ ์ ์๋ ๊ธฐ์ค(์: ๊ฐ๊ฒฉ ๋ฒ์, ๋ ์ง ๋ฒ์, ์นดํ ๊ณ ๋ฆฌ)์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๋ฅผ ์ขํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ํํฐ๋ ์ผ๋ฐ์ ์ผ๋ก ์ ํํ ์ผ์น ๋๋ ๋ฒ์ ๊ธฐ๋ฐ ์ผ์น์ ๊ธฐ๋ฐํฉ๋๋ค. ์ฌ์ฉ์๋ ์ข ์ข *๋ฌด์์* ์ฐพ๊ณ ์๋์ง ์๊ณ ์์ต๋๋ค.
- ๊ฒ์: ์ฃผ์ด์ง ํ ์คํธ ๋ฌธ์์ด(์: ํค์๋)๊ณผ *์ผ์นํ๋* ๊ฒฐ๊ณผ๋ฅผ ์ฐพ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๊ฒ์์ ๋ ์ ์ฐํ๋ฉฐ ์ข ์ข ํผ์ง ๋งค์นญ์ ํฌํจํฉ๋๋ค. ์ฌ์ฉ์๋ ์ ํํ ๋ฌด์์ ์ฐพ๊ณ ์๋์ง ๋ชจ๋ฅผ ์ ์์ง๋ง, ์์์ ์ ์์ต๋๋ค.
๋ค์์ ์ฃผ์ ์ฐจ์ด์ ์ ์์ฝํ ํ์ ๋๋ค:
ํน์ง | ํํฐ๋ง | ๊ฒ์ |
---|---|---|
๋ชฉ์ | ํน์ ๊ธฐ์ค์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๋ฅผ ์ขํ๋๋ค. | ์ฃผ์ด์ง ํ ์คํธ ๋ฌธ์์ด๊ณผ ์ผ์นํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ์ต๋๋ค. |
์ผ์น ๋ฐฉ์ | ์ ํํ๊ฑฐ๋ ๋ฒ์ ๊ธฐ๋ฐ. | ํผ์ง ๋งค์นญ (์: ํฌํจ, ์์, ๋). |
์ฌ์ฉ ์ฌ๋ก | ๊ฐ๊ฒฉ ๋ฒ์, ๋ ์ง ๋ฒ์, ์นดํ ๊ณ ๋ฆฌ ์ ํ. | ํค์๋ ๊ฒ์, ์ ํ ์ด๋ฆ ๊ฒ์, ์ฝํ ์ธ ๊ฒ์. |
์ผ๋ฐ์ ์ธ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์ | ?price__gte=10&price__lte=100 |
?search=keyword |
๊ฐ๊ฐ์ ์ฌ์ฉํ ์์ :
- ํํฐ๋ง ์ฌ์ฉ ์์ : ์ฌ์ฉ์๊ฐ ์๋ ค์ง ํ๋(์: ๊ฐ๊ฒฉ, ๋ ์ง, ์นดํ ๊ณ ๋ฆฌ) ๋ด์ ๊ฐ๋ณ ๊ฐ ๋๋ ๋ฒ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ์ธ๋ถํํ๋ ค๊ณ ํ ๋. ์ฌ์ฉ ๊ฐ๋ฅํ ํ๋๋ฅผ ์๊ณ ์์ ๋.
- ๊ฒ์ ์ฌ์ฉ ์์ : ์ฌ์ฉ์๊ฐ ์์ ํ ์คํธ ์ฟผ๋ฆฌ๋ฅผ ์ ๊ณตํ๊ณ , ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ํ๋์์ ์ผ์นํ๋ ํญ๋ชฉ์ ์ฐพ์์ผ ํ ๋.
์ฑ๋ฅ์ ์ํ ํํฐ๋ง ๋ฐ ๊ฒ์ ์ต์ ํ
ํนํ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ค๋ฃฐ ๋ ์ฑ๋ฅ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ๋ค์ ์ต์ ํ ๊ธฐ์ ์ ๊ณ ๋ คํ์ญ์์ค:
1. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ๋ฑ์ฑ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ๋ฑ์ฑ์ ํํฐ๋ง ๋ฐ ๊ฒ์ ์ต์ ํ๋ฅผ ์ํ ๊ธฐ๋ณธ์ ๋๋ค. ํํฐ๋ง ๋ฐ ๊ฒ์์ ์ฌ์ฉํ๋ ํ๋์ ์ ์ ํ ์ธ๋ฑ์ค๊ฐ ์๋์ง ํ์ธํ์ญ์์ค. ์ธ๋ฑ์ฑ์ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ ์ฒด ํ ์ด๋ธ์ ์ค์บํ์ง ์๊ณ ๋ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ์ ์ํ๊ฒ ์ฐพ์ ์ ์์ต๋๋ค. ์ธ๋ฑ์ค ์ ํ(์: B-ํธ๋ฆฌ, ์ ์ฒด ํ ์คํธ)์ ์ ํ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ ๋ฐ ์ฟผ๋ฆฌ์ ํน์ฑ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ์ธ๋ฑ์ฑ์ ํนํ ์ ์ธ๊ณ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ๋ค๋ฃฐ ๋ ์ ํ๋ฆฌ์ผ์ด์ ํ์ฅ์ฑ์ ๋งค์ฐ ์ค์ํฉ๋๋ค.
์์ (PostgreSQL):
CREATE INDEX product_name_idx ON myapp_product (name);
CREATE INDEX product_price_idx ON myapp_product (price);
์์ (MySQL):
CREATE INDEX product_name_idx ON product (name);
CREATE INDEX product_price_idx ON product (price);
์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ ๊ฑฐํ ๋ ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ ํญ์ ํ ์คํธํ์ญ์์ค. ์ฅ๋จ์ ์ ๊ณ ๋ คํ์ญ์์ค: ์ธ๋ฑ์ค๋ ์ฝ๊ธฐ ์๋๋ฅผ ๋์ด์ง๋ง ์ฐ๊ธฐ(์ฝ์ , ์ ๋ฐ์ดํธ, ์ญ์ ) ์๋๋ฅผ ๋ฆ์ถ ์ ์์ต๋๋ค.
2. ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ณ ์ ์ฒด ํ ์คํธ ๊ฒ์
๋ณต์กํ ๊ฒ์ ์๊ตฌ ์ฌํญ์ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ ์ ์ ์ฒด ํ ์คํธ ๊ฒ์ ๊ธฐ๋ฅ์ ํ์ฉํ์ญ์์ค. ์ ์ฒด ํ ์คํธ ๊ฒ์ ์์ง์ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ฒ์ํ๋๋ก ํน๋ณํ ์ค๊ณ๋์์ผ๋ฉฐ, ์ข ์ข ์ด๊ฐ ์ถ์ถ, ๋ถ์ฉ์ด ์ ๊ฑฐ ๋ฐ ์์ ์ง์ ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ฒด ํ ์คํธ ๊ฒ์ ๊ธฐ๋ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- PostgreSQL: `pg_trgm` ๋ฐ `fts` (์ ์ฒด ํ ์คํธ ๊ฒ์) ํ์ฅ ๊ธฐ๋ฅ์ ์ฌ์ฉํฉ๋๋ค.
- MySQL: ๋ด์ฅ๋ `FULLTEXT` ์ธ๋ฑ์ค๊ฐ ์์ต๋๋ค.
- Elasticsearch: Django์ ํตํฉํ ์ ์๋ ์ ์ฉ ๊ฒ์ ์์ง์ ๋๋ค.
์์ (์ ์ฌ์ฑ ๊ฒ์์ ์ํด `pg_trgm`์ ์ฌ์ฉํ๋ PostgreSQL):
CREATE EXTENSION pg_trgm;
-- In your Product model:
from django.contrib.postgres.search import TrigramSimilarity
Product.objects.annotate(
similarity=TrigramSimilarity('name', search_term),
).filter(similarity__gt=0.3).order_by('-similarity')
์ ์ฒด ํ ์คํธ ๊ฒ์์ ๋ค๊ตญ์ด ๊ฒ์์ ์ง์ํ ๋ ํนํ ์ ์ฉํฉ๋๋ค. ์ด๋ ๋ค์ํ ์ธ์ด ๋ฐ ๋ฌธ์ ์งํฉ์ ๋ ์ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํต๋๋ค.
3. ์บ์ฑ
์์ฃผ ์ก์ธ์คํ๋ ๋ฐ์ดํฐ๋ ๋น์ฉ์ด ๋ง์ด ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ์บ์ฑ์ ๊ตฌํํ์ญ์์ค. DRF๋ Redis ๋๋ Memcached์ ๊ฐ์ ์บ์ฑ ์์คํ ๊ณผ ์ ํตํฉ๋ฉ๋๋ค. ์บ์ฑ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ถํ๋ฅผ ํฌ๊ฒ ์ค์ด๊ณ ์๋ต ์๊ฐ์ ๊ฐ์ ํ ์ ์์ผ๋ฉฐ, ํนํ ์ฝ๊ธฐ ์์ ์ด ๋ง์ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค. ์บ์ฑ์ ๊ตฌํํ ๋ ์ ๋ฐ์ดํธ ๋น๋๋ฅผ ๊ณ ๋ คํ์ญ์์ค. ์ฌ์ฉ์์๊ฒ ์ค๋๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ณ ์ถ์ง ์์ ๊ฒ์ ๋๋ค.
์์ (Django์ ๋ด์ฅ ์บ์ฑ ์ฌ์ฉ):
from django.core.cache import cache
def get_products(search_term=None):
cache_key = f'products:{search_term}'
products = cache.get(cache_key)
if products is None:
if search_term:
products = Product.objects.filter(name__icontains=search_term)
else:
products = Product.objects.all()
cache.set(cache_key, products, timeout=3600) # Cache for 1 hour
return products
4. ํ์ด์ง๋ค์ด์
๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ํ์ํ ๋๋ ํญ์ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉํ์ญ์์ค. ํ์ด์ง๋ค์ด์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ ์๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ํ์ด์ง๋ก ๋๋์ด ํด๋ผ์ด์ธํธ๊ฐ ํ ๋ฒ์ ์์ฒญ๋ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. DRF๋ ๋ด์ฅ ํ์ด์ง๋ค์ด์ ํด๋์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด์ ์ผ๋ก๋ ๋ ๋น ๋ฅธ ์ด๊ธฐ ๋ก๋ ์๊ฐ, ๋์ญํญ ์๋น ๊ฐ์, ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ์ด ์์ต๋๋ค. ํ์ด์ง ๊ธฐ๋ฐ, ์คํ์ ๊ธฐ๋ฐ, ์ปค์ ๊ธฐ๋ฐ๊ณผ ๊ฐ์ ๋ค์ํ ํ์ด์ง๋ค์ด์ ์คํ์ผ์ ๊ณ ๋ คํ์ญ์์ค. ํ์์ ๊ฐ์ฅ ์ ํฉํ ํ์ด์ง๋ค์ด์ ์คํ์ผ์ ์ ํํ์ญ์์ค. ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ์์ ๋นํจ์จ์ ์ผ ์ ์์ต๋๋ค. ๋งค์ฐ ํฐ ๊ฒฐ๊ณผ ์ธํธ์ ์ต์ ์ฑ๋ฅ์ ์ํด ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ฌ์ฉ์ ๊ณ ๋ คํ์ญ์์ค.
์์:
from rest_framework.pagination import PageNumberPagination
class StandardResultsSetPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
๊ทธ๋ฐ ๋ค์ ๋ทฐ์ ์์ ์ด ํ์ด์ง๋ค์ด์ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ญ์์ค:
from .pagination import StandardResultsSetPagination
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = StandardResultsSetPagination
5. QuerySet ๋ฉ์๋ ์ต์ ํ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐฉ์์ ์ฃผ์ํ์ญ์์ค. ๋นํจ์จ์ ์ธ QuerySet ๋ฉ์๋ ๋ฐ ์์ ์ ํผํ์ญ์์ค. ์๋ฅผ ๋ค์ด:
- N+1 ์ฟผ๋ฆฌ ๋ฐฉ์ง: ๊ณผ๋ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํธ์ถ(์: ๋ฃจํ์์ ๊ด๋ จ ๊ฐ์ฒด ๊ฒ์)์ ํ์ง ์๋๋ก ์ฝ๋๋ฅผ ์ ์คํ๊ฒ ๊ฒํ ํ์ญ์์ค. `select_related()` ๋ฐ `prefetch_related()`๋ฅผ ์ฌ์ฉํ์ฌ ๊ด๋ จ ๊ฐ์ฒด ๊ฒ์์ ์ต์ ํํ์ญ์์ค.
- `values()` ๋ฐ `values_list()` ์ฌ์ฉ: ํ๋์ ํ์ ์งํฉ๋ง ํ์ํ ๊ฒฝ์ฐ ์ ์ฒด ๋ชจ๋ธ ์ธ์คํด์ค๋ฅผ ๊ฒ์ํ๋ ๋์ `values()` ๋๋ `values_list()`๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- `annotate()` ๋ฐ `aggregate()` ์ ์ ํ๊ฒ ์ฌ์ฉ: Python์์ ๊ณ์ฐ์ ์ํํ๋ ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ค ๊ณ์ฐ์ ์ํด ์ด๋ฌํ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- `defer()` ๋ฐ `only()` ๊ณ ๋ ค: ํน์ ํ๋ ๊ฒ์์ ์ต์ ํํ๊ณ ๋ถํ์ํ ๋ฐ์ดํฐ ๊ฒ์์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ญ์์ค.
6. ํด๋ผ์ด์ธํธ ์ธก ํํฐ๋ง (๊ณ ๋ ค ์ฌํญ)
๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ผ๋ถ ํํฐ๋ง ๋ก์ง์ ํด๋ผ์ด์ธํธ ์ธก์ผ๋ก ์ด๋ํ ์ ์๋์ง ๊ณ ๋ คํ์ญ์์ค(์: ๋ฏธ๋ฆฌ ๊ฐ์ ธ์จ ์์ ์ต์ ๋ชฉ๋ก์ ๋ํ ํํฐ๋ง). ์ด ์ ๋ต์ ๋ฐ์ดํฐ ํฌ๊ธฐ ๋ฐ ์ํํด์ผ ํ๋ ํํฐ๋ง ์ ํ์ ๋ฐ๋ผ ๋ค๋ฅด๋ฉฐ, ๋๋๋ก ์๋ฒ ๋ถํ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋๋ ๋ฐ์ดํฐ ์๊ณผ ํด๋ผ์ด์ธํธ ์ธก ์ฑ๋ฅ ๋ณ๋ชฉ ํ์ ๊ฐ๋ฅ์ฑ์ ์ ์ํ์ญ์์ค. ํด๋ผ์ด์ธํธ ์ธก ํํฐ๋ง์ ๊ตฌํํ ๋ ์ ์ ํ ๋ณด์ ์กฐ์น๋ฅผ ํ์ธํ์ญ์์ค.
๊ณ ๊ธ ์ ๋ต: ํํฐ๋ง ๋ฐ ๊ฒ์ ๊ฒฐํฉ
๋ง์ ์ค์ ์๋๋ฆฌ์ค์์ ํํฐ๋ง๊ณผ ๊ฒ์์ ๊ฒฐํฉํด์ผ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ์ ํ์ ํํฐ๋งํ ๋ค์ ํด๋น ์นดํ ๊ณ ๋ฆฌ ๋ด์์ ํน์ ํค์๋๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค.
์์ (`django-filter`๋ฅผ ์ฌ์ฉํ์ฌ ํํฐ๋ง ๋ฐ ๊ฒ์ ๊ฒฐํฉ):
from rest_framework import serializers, viewsets
from .models import Product
from django_filters import rest_framework as filters
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class ProductFilter(filters.FilterSet):
category = filters.CharFilter(field_name='category__name', lookup_expr='exact')
search = filters.CharFilter(field_name='name', lookup_expr='icontains')
class Meta:
model = Product
fields = ['category', 'search']
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [filters.DjangoFilterBackend]
filterset_class = ProductFilter
์ด ์์์์ ํด๋ผ์ด์ธํธ๋ `category`๋ก ํํฐ๋งํ ๋ค์ ํด๋น ์นดํ ๊ณ ๋ฆฌ ๋ด์์ `search`(ํค์๋)๋ก ๊ฒ์ํ ์ ์์ต๋๋ค. ์ด ์์๋ ๋ค์ํ ํํฐ ์ ํ์ด ์ด๋ป๊ฒ ๊ฒฐํฉ๋ ์ ์๋์ง ์ฟ๋ณผ ์ ์๊ฒ ํฉ๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉ์์๊ฒ ๋ ๋ณต์กํ ์ฟผ๋ฆฌ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ๋๊ตฌ๊ฐ ๋ ๊ตฌ์ฒด์ ์ธ ์ฟผ๋ฆฌ ์์ฒญ์ ํ์ฉํจ์ผ๋ก์จ ์ ์ธ๊ณ์ ์ผ๋ก ์ฌ์ฉ์ ๊ฒฝํ์ ์ด๋ป๊ฒ ๊ฐ์ ํ ์ ์๋์ง ๊ณ ๋ คํ์ญ์์ค.
๊ตญ์ ํ ๋ฐ ํ์งํ (I18n & L10n) ๊ณ ๋ ค ์ฌํญ
์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ API๋ฅผ ๊ฐ๋ฐํ ๋ ์ ์ ํ ๊ตญ์ ํ(I18n) ๋ฐ ํ์งํ(L10n)๋ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๋ API๋ฅผ ๋ค์ํ ์ธ์ด, ๋ฌธํ ๋ฐ ์ง์ญ์ ๋ง๊ฒ ์กฐ์ ํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
- ํ ์คํธ ์ธ์ฝ๋ฉ: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ API๊ฐ UTF-8 ์ธ์ฝ๋ฉ์ ์ฌ์ฉํ์ฌ ๋ค์ํ ์ธ์ด์ ๊ด๋ฒ์ํ ๋ฌธ์๋ฅผ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ญ์์ค.
- ๋ ์ง ๋ฐ ์๊ฐ ํ์: ISO 8601 ๋ ์ง ๋ฐ ์๊ฐ ํ์์ ์ฌ์ฉํ์ฌ ๋ชจํธ์ฑ์ ํผํ๊ณ ๋ค๋ฅธ ๋ก์ผ์ผ ๊ฐ์ ํธํ์ฑ์ ๋ณด์ฅํ์ญ์์ค.
- ์ซ์ ํ์ ์ง์ : ์ซ์ ํ์ ์ง์ (์: ์์ ๊ตฌ๋ถ ๊ธฐํธ, ์ฒ ๋จ์ ๊ตฌ๋ถ ๊ธฐํธ)์ ์ ์ ํ๊ฒ ์ฒ๋ฆฌํ์ญ์์ค.
- ๋ฌธ์์ด ์ผ์น: ๋ค๋ฅธ ์ธ์ด์์ ๋ฌธ์์ด ๋น๊ต๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ธ์งํ์ญ์์ค. ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋ ์ผ์น๋ฅผ ๊ณ ๋ คํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ์ ํ ๋ฐ์ดํฐ ์ ๋ ฌ ์ค์ ์ ์ฌ์ฉํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ์๋์ด๋ก ๊ฒ์ํ๋ ๊ฒฝ์ฐ ํด๋น ์ฟผ๋ฆฌ๋ ์ ์ ํ ๋ฌธ์ ์งํฉ์ผ๋ก ํจ๊ณผ์ ์ผ๋ก ์๋ํด์ผ ํฉ๋๋ค.
- ๋ฒ์ญ: ์ฌ์ฉ์์๊ฒ ํ์๋๋ ๋ฌธ์์ด, ์ค๋ฅ ๋ฉ์์ง ๋ฐ ๊ธฐํ ํ ์คํธ ์ฝํ ์ธ ์ ๋ํ ๋ฒ์ญ์ ๊ตฌํํ์ญ์์ค.
- ํตํ ์ฒ๋ฆฌ: API๊ฐ ๊ธ์ต ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฒฝ์ฐ ์ฌ๋ฌ ํตํ๋ฅผ ์ง์ํ์ญ์์ค.
- ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ (RTL) ์ง์: ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๋์ด ๋๋ ํ๋ธ๋ฆฌ์ด์ ๊ฐ์ ์ธ์ด๋ฅผ ์ง์ํด์ผ ํ๋ ๊ฒฝ์ฐ RTL ๋ ์ด์์ ๊ตฌํ์ ๊ณ ๋ คํ์ญ์์ค.
DRF๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํฌ๊ด์ ์ธ I18n ๋ฐ L10n ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์์ง๋ง, Django์ I18n/L10n ์์คํ ๊ณผ ํตํฉ๋ฉ๋๋ค. Django์ ๋ฒ์ญ ๊ธฐ๋ฅ(์: `gettext`, `ugettext`, `{% load i18n %}`)์ ์ฌ์ฉํ์ฌ ํ ์คํธ ์ฝํ ์ธ ๋ฅผ ๋ฒ์ญํ์ญ์์ค. I18n/L10n์ ์ ์ ํ๊ฒ ๊ณํํ๊ณ ๊ตฌํํ๋ ๊ฒ์ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๋๋ฌํ๊ณ ํ์งํ๋๊ณ ์ง๊ด์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ฐ ํ์์ ์ ๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ์คํ ๊ฐ๋ฅํ ํต์ฐฐ๋ ฅ
๋ค์์ DRF QuerySet ํํฐ๋ง ๋ฐ ๊ฒ์์ ๋ํ ๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ์คํ ๊ฐ๋ฅํ ํต์ฐฐ๋ ฅ ์์ฝ์ ๋๋ค:
- ์ฌ๋ฐ๋ฅธ ๋๊ตฌ ์ ํ: ํํฐ๋ง ๋๋ ๊ฒ์์ด ํ์์ ์ ํฉํ ๋ฐฉ๋ฒ์ธ์ง ์ ์คํ๊ฒ ํ๊ฐํ์ญ์์ค. ํ์ํ ๊ฒฝ์ฐ ์ด๋ค์ ๊ฒฐํฉํ์ญ์์ค.
- ์ธ๋ฑ์ฑ์ผ๋ก ์ต์ ํ: ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํํฐ๋ง ๋ฐ ๊ฒ์์ ์ฌ์ฉ๋๋ ํ๋๋ฅผ ํญ์ ์ธ๋ฑ์ฑํ์ญ์์ค. ์ ๊ธฐ์ ์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ๊ฒํ ํ๊ณ ์ต์ ํํ์ญ์์ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ณ ๊ธฐ๋ฅ ํ์ฉ: ๋ณต์กํ ๊ฒ์ ์๊ตฌ ์ฌํญ์ ์ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ณ ์ ์ฒด ํ ์คํธ ๊ฒ์ ๊ธฐ๋ฅ์ ํ์ฉํ์ญ์์ค.
- ์บ์ฑ ๊ตฌํ: ์์ฃผ ์ก์ธ์คํ๋ ๋ฐ์ดํฐ๋ฅผ ์บ์ํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ถํ๋ฅผ ์ค์ด์ญ์์ค.
- ํ์ด์ง๋ค์ด์ ์ฌ์ฉ: ์ฑ๋ฅ ๋ฐ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๊ธฐ ์ํด ํญ์ ๋๊ท๋ชจ ๊ฒฐ๊ณผ ์ธํธ๋ฅผ ํ์ด์ง๋ค์ด์ ํ์ญ์์ค.
- QuerySet ์ต์ ํ: ํจ์จ์ ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๊ณ N+1 ์ฟผ๋ฆฌ๋ฅผ ํผํ์ญ์์ค.
- ์ฑ๋ฅ ์ฐ์ ์์: API ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํ๊ณ ์ ์ฌ์ ์ธ ๋ณ๋ชฉ ํ์์ ์๋ณํ์ญ์์ค. ํ๋กํ์ผ๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ๋ถ์ํ๊ณ ์ต์ ํํ์ญ์์ค.
- I18n/L10n ๊ณ ๋ ค: ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ง์ํ๊ธฐ ์ํด ์ฒ์๋ถํฐ ๊ตญ์ ํ ๋ฐ ํ์งํ๋ฅผ ๊ณํํ์ญ์์ค.
- ๋ช ํํ API ๋ฌธ์ ์ ๊ณต: API ๋ฌธ์์ ์ฌ์ฉ ๊ฐ๋ฅํ ํํฐ๋ง ๋ฐ ๊ฒ์ ์ต์ ๊ณผ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฌธ์ํํ์ญ์์ค. ์ด๋ ์ฌ์ฉ์๊ฐ API๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. Swagger ๋๋ OpenAPI์ ๊ฐ์ ๋๊ตฌ๊ฐ ์ฌ๊ธฐ์ ํฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
- ์ฒ ์ ํ ํ ์คํธ: ๋ค์ํ ๋ฐ์ดํฐ ๋ฐ ์ฃ์ง ์ผ์ด์ค๋ก ํํฐ๋ง ๋ฐ ๊ฒ์ ๋ก์ง์ ํ ์คํธํ์ฌ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํ์ญ์์ค. ํ๊ท๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ์ญ์์ค.
์ด๋ฌํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํํฐ๋งํ๊ณ ๊ฒ์ํ๋ ๊ณ ์ฑ๋ฅ์ ์ฌ์ฉ์ ์นํ์ ์ธ API๋ฅผ ์์ฑํ์ฌ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๊ธ์ ์ ์ธ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ ์ธ๊ณ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ์๊ตฌ ์ฌํญ์ ๊ณ ๋ คํ์ญ์์ค. ์ค๊ณ ๋จ๊ณ์์ ๋ด๋ฆฌ๋ ๊ฒฐ์ ์ ์ผ๋ณธ์์ ๋ ์ผ, ์๋ฅดํจํฐ๋์ ์ด๋ฅด๋ ์ฌ์ฉ์์๊ฒ ์ํฅ์ ๋ฏธ์น๋ฉฐ, API๊ฐ ์ ์ธ๊ณ์ ์ผ๋ก ์ฑ๊ณตํ๋ ๋ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
์คํ ๊ฐ๋ฅํ ๋จ๊ณ:
- ํํฐ๋ง ๋ฐ ๊ฒ์ ์๊ตฌ ์ฌํญ ์๋ณ: API์ ์๊ตฌ ์ฌํญ์ ๋ถ์ํ๊ณ ํํฐ๋ง ๋ฐ ๊ฒ์ ์๊ตฌ ์ฌํญ์ ์๋ณํ์ญ์์ค.
- ์ ์ ํ ํํฐ๋ง ๋ฐฑ์๋ ์ ํ: ์ ์ ํ DRF ํํฐ๋ง ๋ฐฑ์๋(์: `OrderingFilter`, `SearchFilter`, `DjangoFilterBackend`)๋ฅผ ์ ํํ์ญ์์ค.
- ํํฐ๋ง ๋ฐ ๊ฒ์ ๊ตฌํ: ๋ทฐ์ ์ ํํฐ๋ง ๋ฐ ๊ฒ์ ๊ธฐ๋ฅ์ ๊ตฌํํ์ญ์์ค.
- QuerySet ๋ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ๋ฑ์ค ์ต์ ํ: ์ฟผ๋ฆฌ๊ฐ ํจ์จ์ ์ด๊ณ ์ ์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ๋ฑ์ค๊ฐ ์๋์ง ํ์ธํ์ญ์์ค.
- ์ฒ ์ ํ ํ ์คํธ: ๋ค์ํ ๋ฐ์ดํฐ ๋ฐ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ก ํํฐ๋ง ๋ฐ ๊ฒ์ ๊ตฌํ์ ํ ์คํธํ์ญ์์ค.
- API ๋ฌธ์ํ: API ๋ฌธ์์ ์ฌ์ฉ ๊ฐ๋ฅํ ํํฐ๋ง ๋ฐ ๊ฒ์ ์ต์ ์ ๋ฌธ์ํํ์ญ์์ค.
๊ฒฐ๋ก
DRF์ QuerySet ํํฐ๋ง ์ ๋ต์ ๋ง์คํฐํ๋ ๊ฒ์ ๊ฐ๋ ฅํ๊ณ ํ์ฅ ๊ฐ๋ฅํ API๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ํ์์ ์ ๋๋ค. ํํฐ๋ง๊ณผ ๊ฒ์์ ์ฐจ์ด์ ์ ์ดํดํ๊ณ , DRF์ ๋ด์ฅ ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉฐ, ์ฑ๋ฅ์ ์ต์ ํํ๊ณ , ๊ตญ์ ํ๋ฅผ ๊ณ ๋ คํจ์ผ๋ก์จ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ํจ๊ณผ์ ์ผ๋ก ์๋น์ค๋ฅผ ์ ๊ณตํ๋ API๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๋์์์ด ์งํํ๋ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ง์์ ์ธ ํ์ต๊ณผ ์ ์์ ํ์์ ์ ๋๋ค. ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ API๊ฐ ํจ์จ์ ์ด๊ณ ์ฌ์ฉ์ ์นํ์ ์ผ๋ก ์ ์ง๋๋๋ก ๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ์ต์ ๋ฐ์ ์ ๋ํ ์ ๋ณด๋ฅผ ์ป์ผ์ญ์์ค.