Django REST API의 필요성과 간단한 사용 방법

왕형준
8 min readSep 27, 2018

--

프론트 개발자와 협력하여 프로젝트를 진행하다 보면 REST API의 필요성을 느끼는 순간이 분명 온다. 가령, 프론트 개발자가 React JS를 쓰려고 한다면 정보 송수신을 어떻게 할 것인가? 프론트로부터 정보를 받고 데이터베이스에 저장하는 것은 기존의 방법으로 할 수 있겠지만 정보를 전달하려면 REST API를 써야 한다. 이때는 Django Rest Framework(DRF)를 사용하여 코드를 작성해야 한다.

처음에는 이 과정이 귀찮을 수 있다. 사실 기존에 있던 코드를 탈바꿈하는 것을 누가 반기겠는가? 하지만, 현재 그 과정을 겪고 REST API를 사용하여 프로젝트를 진행하고 있는 일인으로서 귀찮음에 대한 대가는 충분히 크다고 말하고 싶다.

REST API를 활용하지 않는다면 프론트와 백엔드의 완전한 분리가 불가능하다. Django를 통해 백엔드를 개발하고 있는 사람은 이 말의 뜻을 이해할 것이다. 예를 한 번 보자.

필자의 프로젝트 views.py 코드 일부

위의 캡쳐한 사진은 필자 프로젝트의 views.py 코드 중 일부이다. ListView를 활용한 클래스 기반의 뷰이다. 이렇게 백엔드에서 보낸 정보를 프론트에서 받을 때 다음과 같이 써야할 것이다.

필자의 프로젝트 프론트 코드 일부

위의 사진에서 {% for following in following_list %}는 HTML 코드가 아니다. Javascript도 아니다. Django Template filter이다. 즉, 프론트도 정보를 받기 위해 Django를 어느 정도 알아야 하는 것이다. 혹은 백엔드가 프론트를 대신해 위와 같은 코드를 일부 써줘야 할 것이다.

상황이 이렇게 된다면 프론트와 백엔드는 서로 끊임없이 연락하고 함께 코드를 합치고 고치는 일이 잦아질 것이며 개발 속도는 느려질 수밖에 없다. 작업의 효율성을 높이기 위해서는 백엔드와 프론트는 완전히 구별되는 것이 이상적이며 그러기 위해서는 REST API 필요하다.

이외에 또 한 가지 장점이 있다. 바로 코드의 재활용성이 높아진다는 것이다. 예를 들어보겠다. 기존의 방식은 한 페이지당 하나의 클래스 혹은 함수의 views.py 코드가 필요했다. 이를 그림으로 설명하면 아래와 같다.

21세기 블로거가 이렇게 무식하게 개념도를 표현해서 미안하다. 아주 솔직히 말하면 개념을 표현하기 위해 다른 도구를 사용하기가 귀찮았다. 그래도 아예 그림을 첨부하지 않는 것보다 낫지 않은가? (변명)

그림을 보면 HTML에 정보를 송수신하는 데 Main 클래스만 활용됐다. 그 밑의 여타 클래스는 작동하지 않는다. 간단하게 한 페이지 당 하나의 클래스(혹은 함수)를 할당했다.

자 그러면 이 방식의 문제는 무엇인가? 바로 코드의 재활용성이 떨어진다는 것이다. 다시 한 번 필자의 프로젝트로 예를 들어보겠다.

같은 코드의 반복 예

한 페이지에 하나의 클래스나 함수를 할당하게 되면 같은 정보를 보내더라도 코드를 반복할 수밖에 없다. 얼마나 비효율적인가? 거의 비슷한 페이지임에도 코드를 재활용하지 못한다는 것은 비극적인 일이다. REST API는 이런 현상을 막아준다. 다시 한 번 그림을 그려보겠다.

한 페이지 당 여러 개의 API 사용

그림이 난잡해서 미안하다. 어지러우면 안 보셔도 된다. 핵심은 한 HTML&JS 페이지가 여러 API에서 정보를 받을 수 있다는 점이다. 기존 정보 송수신의 틀을 깨야 REST API를 이해할 수 있다. 이 방식의 장점은 1개의 API가 100개, 1000개, 10 만 개의 페이지에서 활용될 수 있다는 것이다. 코드 재활용성이 파격적으로 높아지는 것을 경험할 수 있을 것이다.

요약하면 REST API를 사용했을 때의 장점은 첫째, 백엔드와 프론트엔드의 완전한 분리가 가능하다는 것이고 둘째, 정보 송수신이 자유로워져 생산성이 급격하게 상승한다는 것이다. 따라서 프로젝트가 어느 정도 진행되고 Django 코드 작성에 익숙해진 단계에서는 REST API로 넘어갈 것을 권한다.

지금 당장 REST API로 바꾸라고요?

그 뜻은 아니다. 기존의 방식에 불편함이 안 느껴진다면 그대로 진행해도 무방하다. 불편함을 느끼기 시작하고 REST API의 필요성이 간절히 느껴진다면 그때 시스템을 바꿔도 늦지 않다. 단순히 남들이 좋다고 말하기 때문에 이제까지의 시스템을 바꾸는 것은 프로그래밍 세계에서는 옳지 않다고 생각한다. 직접 필요성을 느낀 후 배우기 시작해야 학습곡선도 가파르게 올라갈 것이다.

이제 실전으로 넘어가보자.

우선 공식문서부터 확인하자.

설치, settings.py 변경, 간단한 API 서버 구축까지 잘 나와 있다. 우선 공식 문서 내용을 그대로 따라해볼 것을 권한다. 필자는 이와 관련하여 다루지 않겠다.

필자는 어떻게 페이지에 맞춤화된 정보까지 전달할 수 있을지 논하고자 한다. 대부분의 경우는 한 모델의 모든 정보를 나열한 ListAPIView에서 해결할 수 있겠지만 페이지에서 특별히 요구하는 정보를 전달할 때는 이로 충분치 않다. 그럴 경우 어떻게 코드를 작성할 지 소개하겠다.

from rest_framework.renderers import JSONRenderer
from rest_framework.views import APIView
from rest_framework.response import Response
class SettingAPIView(APIView):

renderer_classes = (JSONRenderer, )

def get(self, request, username):
user=get_object_or_404(MyUser, username=username)
content = {'user': user.username, 'greeting': "안녕"}
return Response(content)

코드를 이와 같이 작성했을 때 API 페이지를 들어가면 다음과 같은 내용을 확인할 수 있을 것이다.

API 예시

이제 프론트 개발자는 이 API에서 정보를 긁어오면 되는 것이다. axios를 쓰면 되는데 백엔드 개발자는 여기까지 신경 안 써도 된다. 프론트 개발자가 요구하는 정보를 API에 잘 넘겨주기만 하자.

혹시 독자들이 헷갈릴까 첨언하자면 REST API를 사용해도 Template을 위한 Views 코드는 작성해야 한다. 다음의 예를 보자.

class Setting(TemplateView):
template_name = "cebula/alpha_setting.html"

Template을 위한 코드는 이렇게 간단하게 적을 수 있을 것이다. 정보 전달은 API로 하면 된다. 혹여 API URL에 쓸 pk를 전달하고 싶다면 get_context_data를 오버라이딩해서 Template에 전송한 후 JavaScript에서 받으면 된다. 코드로 설명하자면 다음과 같다.

#views.py
class
Setting(TemplateView):
template_name = "cebula/alpha_setting.html"


def get_context_data(self):
context=super(TemplateView,self).get_context_data()
context['pk']=self.kwargs["pk"]

return context

이렇게 context에 추가적으로 정보를 전달한 뒤

#setting.html
...
<script>
var pk="{{pk}}";
url="127.0.0.1:8000/api/pk/setting".replace("pk", pk);
axios.get(url).then(...)

JavaScript로 받고 그 값을 url에 전달해서 정보를 긁어오면 되는 것이다. url을 replace 구문으로 완성하는 것은 좋은 벙법은 아닐 것이다. 다른 방법이 있겠지만 필자는 잘 모른다. 이 부분은 프론트 개발자가 해결하면 된다.

이제 REST API에 익숙해질 일만 남았다!

필자는 아주 간략하게 필요성과 사용 방법을 언급했을 뿐이다. 무궁무진한 세계가 우리 앞에 있고 우리는 이에 익숙해져야 한다. 처음엔 낯설지 모르겠지만 필요성을 느낀 이상 포기하지 말고 계속 도전해보자.

익숙해지면 신세계가 기다릴 것이다.

--

--