Maximize Your Potential

BackEnd

[DRF 설명서 개념 따라잡기] DRF View와 ViewSet

maxworld 2024. 9. 17. 10:00
728x90
반응형

 DRF View와 ViewSet

API 엔드포인트

API 엔드포인트는 API가 클라이언트와 상호작용할 수 있도록 노출하는 특정한 URL 또는 URI입니다. 예를 들어, 사용자 프로필을 관리하는 가상의 API에서 다음과 같은 API 엔드포인트가 있을 수 있습니다

- GET /api/users: 모든 사용자 프로필의 목록을 검색합니다.
- GET /api/users/{id}:특정 사용자 프로필을 ID로 검색합니다.
- POST /api/users: 새로운 사용자 프로필을 생성합니다.
- PUT /api/users/{id}:특정 사용자 프로필을 ID로 업데이트합니다.
- DELETE /api/users/{id}:특정 사용자 프로필을 ID로 삭제합니다.

기본 DRF View를 상속받아 필요한 메서드를 오버라이드하거나, 필요한 로직을 추가하여 사용자 정의 View를 작성할 수 있습니다. 이렇게 하면 기존 DRF 기능을 활용하면서 복잡한 요구 사항을 충족시킬 수 있습니다.

View셋은 여러 개의 View를 단일 클래스로 묶을 수 있게 해줍니다. 사용자 정의 ViewSet을 작성하면, 각각의 API 엔드포인트에 대한 로직을 한 곳에서 관리할 수 있습니다.

복잡한 시나리오 사용시

복잡한 사용 사례에 대해 처리하려면 사용자 정의 View나 ViewSet을 작성하는 것이 좋을 수 있습니다. 이는 특별한 로직, 복잡한 데이터 처리, 또는 특별한 인증과 권한 검사와 같은 요구사항을 충족시키기 위해 필요할 수 있습니다.

  • 사용자 정의 View 작성
  • 기본 DRF View를 상속받아 필요한 메서드를 오버라이드 하거나, 필요한 로직을 추가하여 사용자 정의 View를 작성할 수 있습니다. 이렇게 하면 기존 DRF 기능을 활용하면서 복잡한 요구 사항을 충족시킬 수 있습니다.
**#views.py**
from rest_framework.views import APIView
from rest_framework.response import Response

class Animal(APIView):
    def get(self, request, format=None):
        # 여기에 GET 요청 처리 로직을 작성합니다.
        return Response({"message": "Dog data"})

    def post(self, request, format=None):
        # 여기에 POST 요청 처리 로직을 작성합니다.
        return Response({"message": "Dog created"})
  • 사용자 정의 View셋 작성

ViewSet은 여러 개의 View를 단일 클래스로 묶을 수 있게 해줍니다. 사용자 정의 ViewSet을 작성하면, 각각의 API 엔드포인트에 대한 로직을 한 곳에서 관리할 수 있습니다.

**#views.py**
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response

class Animal(ViewSet):
    def list(self, request):
        data = {"message": "Here is a list of animals"}  
        return Response(data)

DRF View를 사용하여 CRUD 작업 처리하기

CRUD 작업은 대다수의 API에서 중요한 부분을 차지하며, DRF는 이러한 작업을 수행하기 위한 효율적인 방법을 제공합니다.

from rest_framework import viewsets
from .serializers import AnimalSerializer
from .models import Animal
class AnimalViewSet(viewsets.ModelViewSet):
    queryset = Animal.objects.all()
    serializer_class = AnimalSerializer
  • ViewSet에 사용자 정의 동작 추가하기

사용자 정의 동작은 viewset에 메소드를 추가하고 @action 데코레이터로 장식하여 추가할 수 있습니다.

from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action
from .serializers import AnimalSerializer

class Animal(viewsets.ModelViewSet):
    serializer_class = AnimalSerializer

    @action(detail=True, methods=['post'])
    def mark_as_read(self, request, pk=None):
        dog = self.get_object()
        return Response({'status': 'marked as read'})
  • @action 데코레이터

@action 데코레이터를 활용하면 ViewSet에 사용자 지정 동작을 포함 시킵니다.

from rest_framework.decorators import action
from rest_framework.viewsets import ViewSet

class Animal(ViewSet):
    @action(detail=True, methods=['get', 'post'])
    def my_custom_action(self, request):
        pass

예제 코드

다음은 기본적인 ViewSet 구조입니다. ViewSet은 Django Rest Framework(DRF)에서 제공하는 강력한 추상화로, 여러 종류의 View 로직을 하나의 클래스에 결합할 수 있게 해줍니다.

**#views.py**
from rest_framework import viewsets
from .serializers import AnimalSerializer
from .models import Animal

class AnimalViewSet(viewsets.ModelViewSet):
    queryset = Animal.objects.all()
    serializer_class = AnimalSerializer

#urls.py
from rest_framework.routers import DefaultRouter
from .views import AnimalViewSet

router = DefaultRouter()
router.register(r'animals', AnimalViewSet)

urlpatterns = [
   
]

urlpatterns += router.urls

REST API 설계 철학으로 API를 구현하면 묶음 단위로 만들어지게 됩니다. 보통 특정 자원에 대한 행위가 하나만 존재하는 경우는 잘 없기 때문입니다. 예를 들어 동물원에 동물을 등록하는 ‘Animal이라는 모델에 대해 이루어질 수 있는 행위(Method)는 총 5가지가 존재한다’ 라는 개념을 DRF를 활용하여 REST API로 설계하려 하면 아래와 같이 ViewSet을 작성하면 됩니다.

  • GET: 데이터 조회
  • POST: 데이터 생성
  • PUT: 데이터 일괄 수정 (필드 항목 전체 수정만 가능)
  • PATCH: 데이터 부분 수정 (필드 항목 일부 수정 가능)
  • DELETE: 데이터 삭제
**#views.py**
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from .serializers import AnimalSerializer
from .models import Animal
from rest_framework.generics import get_object_or_404

class AnimalViewSet(viewsets.ModelViewSet):
    queryset = Animal.objects.all()
    serializer_class = AnimalSerializer

  # 기본적인 list(), create(), retrieve(), update(), partial_update(), destroy()는
  # ModelViewSet에 이미 구현되어 있습니다.
  # 추가적인 커스텀 액션을 정의하고 싶다면 @action 데코레이터를 사용할 수 있습니다.

    @action(detail=False, methods=['get'])
    def some_custom_action(self, request):
        # 여기에 커스텀 액션 로직을 구현
        pass

#urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import AnimalViewSet

router = DefaultRouter()
router.register(r'animals', AnimalViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

위와 같이 작성한 ViewSet을 urls.py에서 DRF 라우터에 연결해주면 다음과 같이 그에 맞는 API가 만들어집니다.

 

 

이처럼 REST 아키텍처는 HTTP를 잘 사용할 수 있는 방법을 개발자에게 제시하는 아키텍처입니다. 반드시 지켜야하는 것은 아니지만 근래에는 거의 표준으로 자리잡고 있는 추세입니다. REST 아키텍처를 지킬수록 일관된 API 구조를 만들 수 있기 때문입니다. 이렇듯 개발자는 언제나 일관성 있는 API 설계를 위해 노력해야 하지만 이는 매우 까다로운 일이며 실무에서는 REST 아키텍처 규격을 지키지 못하는 경우도 많이 생깁니다. 이를 염두해두시면 되겠습니다.

REST에는 단독으로 존재하는 API 개념이 없습니다. 하나의 API에 여러 행위(메서드)가 존재하는 개념입니다. Monologue Django 대비 DRF가 어려운 이유는 REST에 단독으로 존재하는 API 개념이 없는데도 ViewSet을 사용해서 내가 원하는 API 하나를 간단히 구현하고 싶은 개발자로서의 마음가짐 때문입니다.