💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    전체 흐름 Part5 | ✅저자: 이유정(박사)

    소스보기

    API 루트 View 추가, 하이라이트 View 추가 snippets/views.py

    from rest_framework.decorators import api_view
    from rest_framework.response import Response
    from rest_framework.reverse import reverse
    from rest_framework import renderers
    
    # ... 기존 필드 생략 ...
    
    # API의 홈(/)에 접속하면 users, snippets 링크 제공
    @api_view(['GET'])
    def api_root(request, format=None):
        return Response({
            'users': reverse('user-list', request=request, format=format),
            'snippets': reverse('snippet-list', request=request, format=format)
        })
    
    # HTML 하이라이트 뷰 만들기
    class SnippetHighlight(generics.GenericAPIView):
        queryset = Snippet.objects.all()
        renderer_classes = [renderers.StaticHTMLRenderer]
    
        def get(self, request, *args, **kwargs):
            snippet = self.get_object()
            return Response(snippet.highlighted)
    

    api_root 함수 / (API 홈 주소)에 접속하면, 사용자 목록(/users/)과 코드 목록(/snippets/) 링크를 보여줍니다.

    왜 필요하냐면?
    DRF에서 브라우저로 API를 탐색할 때,
    처음 화면에 링크를 보여줘야 어디로 가야 할지 알 수 있기 때문입니다.
    → API의 홈 메뉴판 같은 역할이에요.


    SnippetHighlight 클래스 코드 조각을 HTML로 예쁘게 하이라이팅된 형태로 보여주는 API입니다. 왜 필요하냐면?
    일반 JSON으로 코드를 보는 것보다,
    하이라이팅된 HTML로 보여주면 가독성이 훨씬 좋아서 사용자 경험이 좋아집니다.


    ✅ ModelSerializer vs HyperlinkedModelSerializer 차이

    ModelSerializerHyperlinkedModelSerializer는 **Django REST Framework(DRF)**에서 제공하는 두 가지 직렬화 클래스입니다. 둘 다 model의 필드를 자동으로 직렬화해 주지만, 중요한 차이점은 링크 기반 표현 방식에 있습니다.


    ✅ 주요 차이점 요약

    항목 ModelSerializer HyperlinkedModelSerializer
    기본 URL 표현 기본적으로 PK 기반 (/snippets/1/) 기본적으로 하이퍼링크 기반 (/snippets/1/)
    url 필드 필요 여부 필요 없음 url 필드가 필수
    관계 표현 방식 기본적으로 PK 또는 문자열 기본적으로 하이퍼링크(Relation URL)
    API 스타일 간단, 데이터 위주 RESTful, 탐색 가능 API 지향
    사용 목적 JSON 데이터 구조가 주가 되는 경우 하이퍼미디어(HATEOAS) 스타일의 API를 만들고 싶을 때

    ✅ 코드 예시 비교

    1. ModelSerializer (기본 스타일)

    {
      "id": 1,
      "title": "Example",
      "owner": "braverokmc",
      "highlighted": "...",
      "highlight": "http://api.example.com/snippets/1/highlight/",
      "sampleTest": "샘플 테스트 글자"
    }
    
    • 관계 필드: 문자열 또는 PK

    • url 필드 없음

    2. HyperlinkedModelSerializer (링크 중심 API)

    {
      "url": "http://api.example.com/snippets/1/",
      "title": "Example",
      "owner": "http://api.example.com/users/braverokmc/",
      "highlight": "http://api.example.com/snippets/1/highlight/",
      "sampleTest": "샘플 테스트 글자"
    }
    
    • url 필드 자동 포함

    • 관계 필드도 URL 링크로 표현

    view_name을 지정하지 않으면 DRF는 model_name-detail이라는 URL 패턴을 찾습니다. 따라서 URLConf와 basename 설정이 중요합니다.


    ✅ 어떤 걸 써야 할까?

    상황 추천 클래스
    간단한 API + 내부 시스템에서만 사용 ModelSerializer
    외부 공개 API + 링크 기반 탐색 지원 HyperlinkedModelSerializer
    RESTful, HATEOAS 스타일 따르고 싶음 HyperlinkedModelSerializer

    ✅ 추가 팁

    • HyperlinkedModelSerializer를 사용할 때는 ViewSet에 lookup_field, basename, url 필드가 잘 연결되어 있어야 합니다.

    • ModelSerializer는 더 직관적이고 단순해서 시작할 때 학습하기 쉬움.


    HyperlinkedModelSerializer로 변경, 하이라이트 필드 및 URL 필드 추가 snippets/serializers.py

    from rest_framework import serializers
    from snippets.models import Snippet
    from django.contrib.auth.models import User
    
    class SnippetSerializer(serializers.HyperlinkedModelSerializer):
        owner = serializers.ReadOnlyField(source='owner.username')
        highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
    
        class Meta:
            model = Snippet
            fields = ['url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style']
    
    
    class UserSerializer(serializers.HyperlinkedModelSerializer):
        snippets = serializers.HyperlinkedRelatedField(
            many=True,
            view_name='snippet-detail',
            read_only=True
        )
    
        class Meta:
            model = User
            fields = ['url', 'id', 'username', 'snippets']
    
    class SnippetSerializer(serializers.HyperlinkedModelSerializer):
    
    이 시리얼라이저는 `ModelSerializer`의 확장 버전인
    HyperlinkedModelSerializer 
    일반 필드뿐 아니라, 링크(URL) 도 포함해서 보여줍니다.
    

        owner = serializers.ReadOnlyField(source='owner.username')
    
    owner 필드는 읽기 전용입니다.
    Snippet 객체에 연결된 User 객체의 username만 표시됨
    사용자가 직접 owner를 입력하지 않아도 됨
    
        highlight = serializers.HyperlinkedIdentityField(
            view_name='snippet-highlight',
            format='html'
        )
    
    이 필드는 하이라이트된 코드 보기 링크
    /snippets/<id>/highlight/ 와 같은 URL로 연결됨
    view_name='snippet-highlight' 뷰를 호출함
    

        class Meta:
            model = Snippet
            fields = ['url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style']
    
    어떤 모델을 직렬화할지 지정 (`Snippet`)  
    어떤 필드들을 포함할지 나열  
    url 필드가 자동 생성되어 각 Snippet의 상세 링크 제공됨  
    highlight는 HTML 보기 전용 링크  
    owner는 작성자 username  
    나머지는 코드의 실제 내용들 (제목, 내용 등)
    

    class UserSerializer(serializers.HyperlinkedModelSerializer):
    
    사용자(`User`) 객체를 직렬화할 때 링크를 포함해서 보여주는 시리얼라이저
    
        snippets = serializers.HyperlinkedRelatedField(
            many=True,
            view_name='snippet-detail',
            read_only=True
        )
    
    사용자가 작성한 Snippet 목록  
    여러 개(many=True)  
    각 Snippet은 링크 형태(/snippets/<id>/)로 제공  
    read_only=True → 사용자 정보 입력 시 여기에 직접 값을 넣지 않음
    
        class Meta:
            model = User
            fields = ['url', 'id', 'username', 'snippets']
    
    User : 모델을 직렬화
    url : 이 사용자의 상세 URL
    id : 고유 번호
    username : 사용자 이름
    snippets : 이 사용자가 만든 Snippet들의 링크 목록
    

    모든 URL에 이름(name=...) 추가, API 루트 및 하이라이트 경로 추가 snippets/urls.py

    from django.urls import path
    from rest_framework.urlpatterns import format_suffix_patterns
    from snippets import views
    
    urlpatterns = format_suffix_patterns([
        path('snippets/', views.SnippetList.as_view(), name='snippet-list'),
        path('snippets/<int:pk>/', views.SnippetDetail.as_view(), name='snippet-detail'),
        path('users/', views.UserList.as_view(), name='user-list'),
        path('users/<int:pk>/', views.UserDetail.as_view(), name='user-detail'),
    	
    	path('', views.api_root),
        path('snippets/<int:pk>/highlight/', views.SnippetHighlight.as_view(), name='snippet-highlight'),
    ])
    

    tutorial/settings.py 페이지네이션 설정 추가

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 10,
        'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
      ]
    }
    
    part6을 위한 페이지 네이션 미리 설정
    
    TOP
    preload preload