hotamul의 개발 이야기

[hotamul] Django request 횟수 줄이기 (+Vue.js) 본문

project/share-blog

[hotamul] Django request 횟수 줄이기 (+Vue.js)

hotamul 2022. 9. 7. 22:13

기존 home 화면에서의 vue-django 연동 과정

현재 프로젝트에서 home url(/)에 접근했을 때의 Vue-Django 연동 처리 과정이다.

  • 처음 request(/)에는 DB에 접근하지 않고 html, css, js 파일만을 전달한다.
  • 렌더링 시 Vue.js 코드의 created()에서 axios 객체를 이용해 두 번째 request(/api/post/list)가 실행된다.
    이 때는 DB에 접근한다.

위 과정은 반드시 두 번의 request가 있어야 한다. 하지만 처음 html, css, Vue.js 를 전달할 때 DB에도 접근하여 JsonResponse를 전달 할 수 있다면 request 수를 줄일 수 있어 렌더링 시간을 줄일 수 있을 것이다.

request 수에 주목하자. 기존에는 20 requests가 실행된다.

from django.views.generic import TemplateView


class HomeView(TemplateView):
    template_name = 'home.html'

기존에는 위와 같이 DB에 접근하지 않아도 되기 때문에 TemplateView를 사용했고 template_name만 지정해주었다.

created() {
  console.log("created()...");
  const params = new URL(location).searchParams;
  this.category = params.get('category');
  this.tag = params.get('tags');
  this.fetchPostList();
},

그리고 created()에서 fetchPostList 메소드를 호출하면서 axios 객체를 통해 postList를 가져오고 있다.

개선방법 및 결과

from django.views.generic import ListView

from api.utils import obj_to_post
from blog.models import Post

import json


class HomeView(ListView):
    model = Post
    template_name = 'home.html'
    paginate_by = 3

    def get_queryset(self):
        param_cate = self.request.GET.get('category')
        param_tag = self.request.GET.get('tag')
        if param_cate:
            qs = Post.objects.filter(category__name__iexact=param_cate)
        elif param_tag:
            qs = Post.objects.filter(tags__name__iexact=param_tag)
        else:
            qs = Post.objects.all()
        return qs

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data()
        post_list = [obj_to_post(obj) for obj in context['object_list']]
        page_cnt = context['paginator'].num_pages
        cur_page = context['page_obj'].number
        data_dict = {
            'postList': post_list,
            'pageCnt': page_cnt,
            'curPage': cur_page,
        }
        context['myJson'] = json.dumps(data_dict)
        return context

기존 HomeViewListView를 상속받게 하고 두 개의 메소드(get_queryset, get_context_data)만 오버라이딩 해주면 된다. 현재 django의 paginate 기능을 사용하고 있기 때문에 paginate_by, context['paginator'], context['page_obj']와 같은 코드들이 있다.

필요한 데이터들을 'myJson' 이름으로 담아 Javascript에 전달한다.

...
const myJson = JSON.parse('{{ myJson|escapejs }}');

const PostListApp = {
        delimiters: ['[[', ']]'],
...
        created() {
            console.log("created()...");
            const params = new URL(location).searchParams;
            this.category = params.get('category');
            this.tag = params.get('tags');
            this.postList = myJson.postList;
            this.pageCnt = myJson.pageCnt;
            this.curPage = myJson.curPage;
        },
...

현재 Jinja template을 같이 사용하고 있기 때문에 delimters[[, ]]로 설정해주고 있다.
따라서 받아온 myJson을 Javascript 객체로 만드려면 위와 같이 escapejs를 사용하고 따옴표로 감싸서 JSON.parse 인자에 넣어줘야 한다.

이렇게 변경한 뒤 request 수를 확인해보자.

request 수가 20에서 19로 감소한 것을 볼 수 있다.

Comments