노트

DRF 뷰 계층

Django REST Framework Views and ViewSets

백엔드#django · 연결된 개념 9개

쉽게 말하면

DRF 뷰 계층은 요리를 재료 손질부터 직접 할지, 밀키트를 쓸지, 완성된 도시락을 살지 고르는 것과 같아요. 위로 갈수록 정해진 관례가 많아 코드는 줄지만, 마음대로 바꿀 여지도 줄죠.

비유가 깨지는 곳 도시락처럼 편하지만 안에서 무엇이 자동으로 일어나는지 모르면 추적이 어려워요. 예를 들어 queryset만 두면 URL과 상관없이 전체가 나오니 중첩 URL에선 get_queryset으로 좁혀요.

DRF는 같은 API를 점점 더 적은 코드로 쓰게 해 주는 뷰 계층을 제공한다. 함수 뷰 → APIView → 제네릭 뷰(generic view)와 믹스인(mixin) → 구체 제네릭 뷰 → ViewSet과 Router 순으로 올라갈수록 관례가 많아지고 코드가 줄어든다.

단계별

@api_view(["GET", "POST"])                      # 1. 함수 뷰
def movie_list(request): ...
 
class MovieList(APIView):                        # 2. 메서드별 핸들러
    def get(self, request): ...
    def post(self, request): ...
 
class MovieList(generics.ListCreateAPIView):     # 3. 구체 제네릭 뷰
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
 
class MovieViewSet(viewsets.ModelViewSet):       # 4. ViewSet: 목록·생성·조회·수정·삭제 전부
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
 
router = DefaultRouter()
router.register("movies", MovieViewSet)          # URL을 자동 생성
urlpatterns = router.urls
  • DRF의 Request는 request.data로 JSON·폼 본문을 똑같이 읽게 해 주고, Response는 콘텐츠 협상(content negotiation)으로 형식을 정한다(DRF 파서·렌더러와 콘텐츠 협상)
  • GenericAPIView는 get_queryset()·get_object()·페이징·필터 같은 공통 기능을, CreateModelMixin 같은 믹스인은 create()·list() 같은 동작을 준다. 이를 묶은 것이 ListCreateAPIView, RetrieveUpdateDestroyAPIView 같은 구체 뷰다
  • View와 ViewSet: View는 HTTP 메서드(get·post)별로, ViewSet은 동작(list·create·retrieve·update·destroy)별로 메서드를 나눈다. ViewSet은 Router와 함께 URL을 자동으로 만든다
  • ReadOnlyModelViewSet은 조회만 연다

자주 덮어쓰는 지점

class ReviewList(generics.ListCreateAPIView):
    serializer_class = ReviewSerializer
 
    def get_queryset(self):                       # URL의 pk로 범위를 좁힘
        return Review.objects.filter(watchlist_id=self.kwargs["pk"])
 
    def perform_create(self, serializer):         # 저장할 때 요청 사용자 넣기
        serializer.save(author=self.request.user)
  • queryset만 두면 URL과 상관없이 전체가 나온다. 중첩 URL에서는 get_queryset으로 좁힌다
  • ViewSet에 기본 CRUD 외 동작은 @action(detail=True)으로 추가한다
  • URL이 관례에서 벗어나면 Router에 억지로 맞추기보다 뷰를 직접 연결하는 편이 낫다

관례 위에 올라탈수록 코드는 짧아지지만, 무엇이 자동으로 일어나는지 모르면 동작을 추적하기 어렵다(누수 추상화의 법칙). 권한·필터·페이지는 DRF 인증과 권한, DRF 필터·검색·정렬, 페이지네이션 (offset·cursor)을 본다. 반복을 줄이는 도구의 한계는 DRY 원칙와 3의 법칙도 함께 볼 만하다.

출처: DRF Generic views: GenericAPIView · Mixins · Concrete View Classes · DRF ViewSets · Extra actions

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • DRF API 테스트

    DRF는 장고 테스트 위에 API 요청을 편하게 보내는 APITestCase와 APIClient를 제공한다. 장고 테스트 러너(test runner)는 테스트용 DB를 따로 만들고, 각 테스트를 트랜잭션으로 감싸 끝나면 되돌리므로 실제 데이터를 건드리지 않는다.

  • DRF 시리얼라이저

    DRF(Django REST Framework)의 시리얼라이저는 모델 인스턴스·QuerySet을 JSON으로 바꿀 수 있는 파이썬 기본 자료형으로 바꾸고(직렬화, serialization), 반대로 들어온 데이터를 검증해 모델로 만드는(역직렬화, deserialization) 틀이다. 장고의 Form과 비슷하게 필드와 검증 규칙을 선언한다.

  • Spring MVC 요청 흐름

    Spring MVC는 모든 HTTP 요청을 DispatcherServlet 하나가 받아, 알맞은 컨트롤러 메서드로 보내고 결과를 응답으로 바꾸는 프런트 컨트롤러(Front Controller) 구조다. 스프링 이전에는 URL마다 서블릿을 직접 만들고 매핑했다.

  • 요청 제한 (Throttling)

    요청 제한(rate limiting, throttling)은 일정 시간 동안 한 클라이언트가 보낼 수 있는 요청 수를 묶어 두는 장치다. 한도를 넘으면 429 Too Many Requests로 거절하고, 보통 Retry-After 헤더로 언제 다시 시도하면 되는지 알려 준다.

  • GraphQL

    GraphQL은 클라이언트가 필요한 데이터의 모양을 쿼리로 적어 보내면 서버가 정확히 그 모양으로 응답하는 API 쿼리 언어(query language)다. Facebook이 2012년 내부에서 만들어 2015년 공개했고, 지금은 GraphQL Foundation이 관리한다.

보기 옵션