Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 3 (백엔드 DRF)
Project/Django & Vue.js

Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 3 (백엔드 DRF)

뉴비뉴 2020. 6. 9.

안녕하세요.

 

평소 필력이 많이 부족한데다가 이런 프로젝트는 처음이라 두서는 진행과

설명이 부실한 부분이 많습니다. 부족한 점은 구글링을 이용하여 습득하시면 감사하겠습니다.

또한 필자는 빠르게 Todo 리스트를 만들어보는 것을 목표로 잡고 있고, 한번 만들어보고 나서 개념을 다잡는

공부방법이 가장 빠르게 습득할 수 있는 방법이라 생각하기에 이런 방식으로 진행하고 있는 점 이해주시면 감사하겠습니다.

 

잘못 된 부분이 있으면 댓글로 지적해주시면 감사하겠습니다 : )

 

DRF ( Django REST Framework)

오늘은 REST API Server를 만들어 보겠습니다.

그 전에 REST가 뭔지에 대해 알 필요가 있습니다.

설명이 자세히되어있는 블로그들이 많으니 여기서는 간단하게만 확인하고 넘어가겠습니다. 

 

REST는 REpresentiational State Transfer를 의미합니다.

자원을 이름으로 구분하여 해당 자원의 상태(정보)를 주고 받는 모든 것을 의미합니다.

 

구체적인 개념은 HTTP URL을 통해 자원을 명시하고, HTTP Method(POST, GET, DELETE, PUT)를 통해 해당 자원에 대한 CRUD 오퍼레이션을 적용하는 것이라고 할 수 있습니다. 

 

투두 프로젝트로 예시를 한번 들어보겠습니다.

백엔드 개발자는 REST API Server를 구축하고, 투두 리스트를 작성할 수 있는 엔드포인트를 생성하였습니다. 

# ex) POST /todo/create

{'title': ''}
{'content': ''}

프론트 개발자와 앱 개발자는 백엔드 개발자가 만든 엔드포인트에 트리거(Trigger) 합니다. 위의 예시를 보니 title과 content를 받고 있습니다. 프론트 개발자와 앱 개발자는 입력해야되는 것들을 입력하고 /todo/create 엔드포인트에 POST로 요청을 보내고, 서버에서는 프론트, 앱 개발자가 입력을 잘못했다면 404 Bad Request를 잘 생성되었다면 201 Created 를 리턴해줍니다.

 

데이터를 송수신하는 과정에서 json, xml, yaml 과 같은 데이터포맷이 필요하긴 하지만 간단하게 설명하기 위해 제외하였습니다.

 

좋습니다.

저희가 필요한 것은 투두리스트 작성(Create), 수정(Update), 읽기(Read), 삭제(Delete) CRUD가 필요합니다.

 

위에서 말한 엔드포인트는 기능을 의미합니다. CRUD 정말 간단하게만 봐도 우리는 엔드포인트를 4개를 만들어야 된다는 것을 알 수 있습니다. 그럼 같이 한번 만들어보시죠!

 

환경 세팅

1편을 보셨다면 이미 INSTALLED_APPS 에 rest_framework와 drf-yasg가 추가되어 있을 것 입니다.

settings 에서 타임존을 TIME_ZONE = 'Asia/Seoul' 로 설정해주도록 하겠습니다.

 

URLs

먼저 디렉터리 구조를 보면 현재 config(설정파일)와 todo 디렉터리가 있습니다.

config에 urls.py 에서 url을 등록해주도록 하겠습니다.

 

등록하면서 todo/urls.py todo 디렉터리 안에 urls.py 파일을 생성해주도록 하겠습니다.

# config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('todo.urls'))  # http://localhost:8000/api/
]

include로 생성한 todo.urls 파일을 참조하고 있습니다.

/api/ 로 접속하면 todo의 urls로 이동된다는 것과 같습니다.

 

Views - status_check

 

다음으로 간단한 status_check view를 생성해보도록 하겠습니다.

 

views 폴더 아래 status_check.py 파일을 생성해줍니다. 그리고 같이 todo/urls.py 도 설정해주겠습니다.

# todo/views/status_check.py


from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view


@api_view(['GET'])  # get으로 요청 시에 응답합니다. 그 외 다른 Method로 요청하면 405 코드를 반환합니다.
def status_check(request):
    """
    서버의 상태를 확인하는 함수입니다.
    """
    return Response({
        "status": "OK"
    }, status=status.HTTP_200_OK)


# todo/urls.py


from django.urls import path

from todo.views import *  # views/__init__.py 에서 status_check.py를 모듈로 선언했기에 한번에 가져올 수 있습니다.


urlpatterns = [
    path('status_check/', status_check, name='status_check'),  # /api/status_check/
]

위 코드는 /api/status_check/ 로 요청을 받으면 status_check라는 뷰를 실행하라는 것이고, status_check 에서는 서버에 이상이 없다면 Response로 "status": "OK" 와 200 코드를 요청한 사람에게 돌려줍니다.

localhost:8000/api/status_check/ 와 동일합니다. Content_Type을 확인해보세요. json으로 보내진 것을 확인할 수 있습니다.

정말 신기하지않나요? 우리는 rest_framework 를 설치하고 등록하고 요청을 보냈더니 rest_framework의 기본페이지가 생기면서 보기 편하게 화면이 정리되어있습니다.

 

정리해보면 view를 생성하고, urls.py에 path와 함께 view를 설정해주면, 이용하는 사람은 해당 엔드포인트(URI)로 요청하면 원하는 자원을 얻을 수 있게 된 것 입니다.

 

그렇다면 우리는 Todo라는 모델을 가지고 CRUD를 진행할 것 입니다.

 

View를 만드는 방법

여기서 우리는 Views를 만들 수 있는 방법을 알아볼 필요가 있습니다.

 

View를 만드는 방법은 크게 4가지로 나뉘어집니다.

APIView, Mixin, Generics APIView, ViewSet
자세한 내용이 궁금하신 부분은 공식문서를 확인해보시고, 사용법을 확인하고 싶으시면 링크를 참고하시면 되겠습니다.

 

Serializer/Deserializer란?

serializer를 알아보기전에 

 

status_check 의 마지막 Response 부분을 기억하시나요?

기억이 안나신다면 한번 보고 오시기 바랍니다.

 

python dict 데이터 타입으로 {"status": "OK"} 로 data를 넘겼었습니다.

하지만 Python의 Dict 데이터 타입으로 된 데이터를 다른 곳에 넘기기 위해서는 json 이라는 것으로 변환하여 넘겨야 합니다.

꼭 json일 필요는 없지만 표준으로 사용된다고 보시면 됩니다. 

 

그럼 이런생각이 듭니다. "어 나는 {"status": "OK"} 로 보냈는데 applications/json로 보내졌지?" 이것은 rest_framework의 Response가 data를 입력하면 json으로 변경하여 응답을 준다고 생각하시면 됩니다.

 

자 그럼 serializer는 무슨 역할을 할까요? (개념적인 것은 구글링을 추천드립니다.)

 

Queryset 및 Model Instance 와 같은 복잡한 데이터를 원시 Python(Dict) 데이터 유형으로 변환한 다음

JSON, XML 또는 기타 컨텐츠 유형으로 쉽게 렌더링 할 수 있습니다.

Serializer는 역직렬화 기능을 제공하여 파싱된 데이터의 유효성 검사를 한 후 복잡한 유형으로 다시 변환할 수 있습니다.

 

- Todo 테이블에 있는 title과 content 컬럼을 json으로 변환하여 보낼 수 있습니다.

 - Python Dict 형 데이터도 json로 변환하여 보낼 수도 있습니다.

 

deserializer

- 간단하게 말하면 json 데이터를 읽어들여 검증하고, Python Dict형으로 변환합니다. 

 

TodoList - CRUD ViewSet으로 만들기 + Serializer 생성하기

serializers 폴더를 생성한 뒤 안에 __init__.py와 todo.py 파일을 생성해주겠습니다.

from rest_framework import serializers

from todo.models import Todo


class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ['title', 'description', 'author', 'due_date', 'completed']  # Todo 테이블의 필드를 지정

ModelSerializer 클래스를 사용하면 Model에 정의한 필드에 해당하는 값을 serializer에서 사용할 수 있습니다.

위 코드의 fields 가 없다면 Default로 모든 컬럼을 사용할 수 있습니다.

 

views 폴더 안에 todo.py를 만들어 ModelViewSet을 생성해주겠습니다.

from rest_framework import viewsets

from todo.models import Todo
from todo.serializers.todo import TodoSerializer


class TodoModelViewSet(viewsets.ModelViewSet):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer


"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""

ModelViewSet은 Create, Retrieve, Update, Partial_update, Destroy, List를 지원합니다.

이말은 즉 위에 보이는 TodoModelViewSet만 생성해도 여러 기능들을 사용할 수 있음을 의미합니다.

 

안에보이는 queryset은 어떠한 모델 인스턴스로 지정할지를 설정한다고 생각하시면(?) 되고, serializer_class 도 비슷합니다.

 

그리고 router를 등록해주도록 하겠습니다. (추가 2020.07.10)

# todo/urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter

from todo.views import *

router = DefaultRouter()  # viewset 은 router 를 사용하여 URL 을 관리할 수 있습니다.
router.register(r'todo', TodoModelViewSet)

urlpatterns = [
    # Endpoints
    path('status_check/', status_check, name='status_check'),
    path('', include(router.urls)),  # 위에 선언한 router 를 사용
]

 

자 그럼 어떻게 동작하는지 한번 확인해보겠습니다.

우리는 위에서 router.register(r'todo', TodoModelViewSet) 를 지정했었습니다.

 

localhost:8000/api/todo/ 로 접속하니 뭔가 그럴싸한 화면이 보입니다.

 

localhost:8000/api/todo/

사진의 제일 위에 GET /api/todo/ 는 GET으로 /api/todo/ 에 요청했다는 것 입니다.

그 아래보이는 내용은 Todo에 작성했던 내용들이 보이네요, 2개가 보이는 이유는 2개를 작성했기 때문이고,

2개가 보인다는 것은 List를 보고 있다는 것을 의미합니다. Retrieve였으면 하나만 보였겠죠?

그리고 그 아래에는 뭔가 작성할 수 있는 입력란들이 보이고 맨 아래 POST라는 버튼이 보입니다.

이건 해당 폼을 입력하고 POST /ap/todo/ 로 요청을 보내면 내용이 DB에 저장되는 것을 말합니다.

 

지금까지 파악한 URL을 정리해보면

 

GET /api/todo/ -> List

POST /api/todo/ -> Create

 

localhost:8000/api/todo/1

GET /api/todo/1/ -> Retrieve

DELETE /api/todo/1/ -> Destroy

PUT /api/todo/1/ -> Update/Partial_update

 

정말 편리하지 않나요? 코드 몇줄로 이 많은 기능들을 사용할 수 있습니다.

추후에 작업할 Vue(프론트) 에서는 해당 URL로 요청하면서 데이터만 올바르게 넣어주면 정상적으로 데이터가 들어갈 것 입니다.

 

하지만 여기서 커스텀하게 특정 값이 들어오면 어떠한 처리를 하고, 이러한 작업은 각 메서드를 호출해서 사용해야되지만 크게 어렵지 않습니다.

 

좋습니다. 우리는 정말 간단하게 REST API Server의 기반을 갖췄습니다.

이제 프론트에서 이쁘게 꾸며주고, 클라이언트가 입력한 값을 백서버로 보내어 실제 데이터를 생성, 삭제, 업데이트 해보도록 하겠습니다.

 

Reference

 

 

 

 

댓글

💲 추천 글