REST API는 아래 원칙을 따를 때 RESTful API라고 합니다.
| 원칙 | 설명 |
|---|---|
| 1. 클라이언트-서버 구조 | 클라이언트는 요청을 보내고, 서버는 데이터를 제공 |
| 2. 무상태성(Stateless) | 요청 간 상태 정보를 저장하지 않음 (각 요청은 독립적) |
| 3. 캐시 가능(Cacheable) | 응답을 캐시하여 성능 최적화 가능 |
| 4. 계층화된 시스템(Layered System) | API 서버는 여러 계층으로 구성 가능 (보안, 로드 밸런싱) |
| 5. 일관된 인터페이스(Uniform Interface) | 표준 HTTP 메서드 사용 (GET, POST, PUT, DELETE) |
| 6. 코드 온 디맨드 (선택적) | 필요하면 서버에서 실행할 수 있는 코드를 클라이언트에 제공 |
✅ 이 원칙을 따르면 RESTful API라고 부릅니다! 🚀
APIView와 ViewSet의 차이점Django REST Framework(DRF)에서는 API를 만들 때 APIView와 ViewSet을 사용할 수 있습니다.
둘 다 API 엔드포인트를 만들기 위한 방법이지만 구조와 사용법이 다릅니다.
APIView (클래스 기반 뷰 - CBV)📌 APIView는 HTTP 메서드(GET, POST, PUT, DELETE)를 직접 정의해야 하는 클래스 기반 뷰입니다.
View 클래스를 확장한 것으로, get(), post(), put(), delete() 등의 HTTP 메서드를 직접 정의해야 합니다. urls.py에서 수동으로 연결해야 합니다. APIView 예제from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Blog
from .serializers import BlogSerializer
class BlogListAPIView(APIView):
def get(self, request):
blogs = Blog.objects.all()
serializer = BlogSerializer(blogs, many=True)
return Response(serializer.data)
def post(self, request):
serializer = BlogSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
urls.py에서 수동으로 URL 등록from django.urls import path
from .views import BlogListAPIView
urlpatterns = [
path('blogs/', BlogListAPIView.as_view(), name='blog-list'),
]
ViewSet (자동 라우팅 지원)📌 ViewSet은 CRUD(Create, Read, Update, Delete)를 위한 API 엔드포인트를 자동으로 만들어주는 클래스입니다.
ModelViewSet을 사용하면 리스트 조회, 개별 조회, 생성, 수정, 삭제 기능이 자동으로 생성됩니다. router.register()를 사용하면 자동으로 URL 라우팅이 설정됩니다. list(), create(), retrieve(), update(), destroy() 등의 기본 CRUD 메서드를 제공하며, 필요하면 오버라이딩할 수 있습니다. ViewSet 예제from rest_framework import viewsets
from .models import Blog
from .serializers import BlogSerializer
class BlogViewSet(viewsets.ModelViewSet):
queryset = Blog.objects.all()
serializer_class = BlogSerializer
urls.py에서 DefaultRouter를 사용하여 자동 등록from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BlogViewSet
router = DefaultRouter()
router.register(r'blogs', BlogViewSet, basename='blog')
urlpatterns = [
path('', include(router.urls)), # ✅ 자동 라우팅
]
APIView vs ViewSet 차이점 비교표APIView | ViewSet | |
|---|---|---|
| 라우팅 방식 | urls.py에서 path()로 개별 연결 필요 | router.register()로 자동 등록 가능 |
| 자동 CRUD 기능 | ❌ 직접 구현해야 함 | ✅ ModelViewSet 사용 시 자동 제공 |
| 사용 예제 | GET, POST 등 HTTP 메서드를 직접 정의 | list(), retrieve(), create(), update(), destroy() 제공 |
| 추천 사용 사례 | 특정 로직이 필요한 API | 단순한 CRUD API를 빠르게 만들 때 |
APIView와 ViewSet을 함께 사용하여 API 구현하기📌 기능:
GET /blogs/ → 블로그 목록 조회 POST /blogs/ → 새로운 블로그 생성 GET /blogs/popular/ → 인기 블로그 조회 (ViewSet으로는 자동 제공되지 않는 커스텀 API) ViewSet을 사용하여 /api/blogs/에서 CRUD 자동 제공 urls.py 코드 (APIView + ViewSet)from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BlogViewSet, BlogListAPIView, PopularBlogAPIView
router = DefaultRouter()
router.register(r'blogs', BlogViewSet, basename='blog')
urlpatterns = [
path('api/', include(router.urls)), # ✅ ViewSet 자동 라우팅
path('blogs/', BlogListAPIView.as_view(), name='blog-list'), # ✅ APIView 사용
path('blogs/popular/', PopularBlogAPIView.as_view(), name='popular-blogs'), # ✅ 커스텀 API
]
ViewSet을 사용하여 /api/blogs/에서 자동 생성 APIView를 사용하여 /blogs/popular/에서 직접 구현 ViewSet과 APIView을 적절히 섞어서 사용하면 효율적임. 🔥 즉, CRUD는 ViewSet, 복잡한 로직은 APIView를 사용하면 된다! 🚀
APIView와 ViewSet을 함께 사용하여 API 구현하기Django REST Framework에서 APIView와 ViewSet을 함께 사용하면 다양한 방식으로 API를 구성할 수 있습니다.
아래 예제에서는 Blog 모델을 사용하여 APIView와 ViewSet을 동시에 적용하는 방법을 보여줍니다.
APIView를 사용한 개별 API 엔드포인트📌 기능:
GET /blogs/ → 블로그 목록 조회 POST /blogs/ → 새로운 블로그 생성 GET /blogs/popular/ → 인기 블로그 조회 (ViewSet으로는 자동 제공되지 않는 커스텀 API) views.py에서 APIView 적용from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Blog
from .serializers import BlogSerializer
class BlogListAPIView(APIView):
def get(self, request):
blogs = Blog.objects.all()
serializer = BlogSerializer(blogs, many=True)
return Response(serializer.data)
def post(self, request):
serializer = BlogSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class PopularBlogAPIView(APIView):
def get(self, request):
popular_blogs = Blog.objects.filter(views__gte=100) # 조회수 100 이상
serializer = BlogSerializer(popular_blogs, many=True)
return Response(serializer.data)
urls.py에서 APIView 등록from django.urls import path
from .views import BlogListAPIView, PopularBlogAPIView
urlpatterns = [
path('blogs/', BlogListAPIView.as_view(), name='blog-list'),
path('blogs/popular/', PopularBlogAPIView.as_view(), name='popular-blogs'),
]
ViewSet을 사용한 자동 CRUD API📌 기능:
GET /api/blogs/ → 블로그 목록 조회 POST /api/blogs/ → 새로운 블로그 생성 GET /api/blogs/{id}/ → 특정 블로그 조회 PUT /api/blogs/{id}/ → 특정 블로그 수정 DELETE /api/blogs/{id}/ → 특정 블로그 삭제 views.py에서 ViewSet 적용from rest_framework import viewsets
from .models import Blog
from .serializers import BlogSerializer
class BlogViewSet(viewsets.ModelViewSet):
queryset = Blog.objects.all()
serializer_class = BlogSerializer
urls.py에서 ViewSet 등록from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BlogViewSet
router = DefaultRouter()
router.register(r'blogs', BlogViewSet, basename='blog')
urlpatterns = [
path('api/', include(router.urls)), # ✅ ViewSet 자동 라우팅
]
APIView와 ViewSet을 같이 사용하는 urls.py위에서 만든 APIView와 ViewSet을 하나의 urls.py에서 함께 사용할 수 있습니다.
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BlogViewSet, BlogListAPIView, PopularBlogAPIView
router = DefaultRouter()
router.register(r'blogs', BlogViewSet, basename='blog')
urlpatterns = [
path('api/', include(router.urls)), # ✅ ViewSet 자동 라우팅
path('blogs/', BlogListAPIView.as_view(), name='blog-list'), # ✅ APIView 사용
path('blogs/popular/', PopularBlogAPIView.as_view(), name='popular-blogs'), # ✅ 커스텀 API
]
✔ CRUD API는 ViewSet을 사용하여 /api/blogs/에서 자동 처리
✔ 특수 API (인기 블로그 조회 등)는 APIView를 사용하여 /blogs/popular/에서 직접 처리
APIView | ViewSet | |
|---|---|---|
| 라우팅 방식 | urls.py에서 path()로 개별 연결 필요 | router.register()로 자동 등록 가능 |
| 자동 CRUD 기능 | ❌ 직접 구현해야 함 | ✅ ModelViewSet 사용 시 자동 제공 |
| 사용 예제 | 특정 기능 API (/blogs/popular/) | CRUD API (/api/blogs/) |
| 추천 사용 사례 | 비즈니스 로직이 복잡한 API | 단순한 CRUD API를 빠르게 만들 때 |
APIView와 ViewSet을 어떻게 함께 사용할 수 있는가?ViewSet을 사용하여 /api/blogs/에서 자동 생성 APIView를 사용하여 /blogs/popular/에서 직접 구현 APIView와 ViewSet을 적절히 섞어 사용하면 효율적인 REST API를 만들 수 있음🔥 즉, CRUD는 ViewSet, 복잡한 로직은 APIView를 사용하면 된다! 🚀