[2차 프로젝트] 리스트 페이지 불러오기 기능

이태연·2021년 12월 26일

이번 2차 프로젝트에서 가장 많은 시간을 들였고 사실 가장 아쉬운 부분이기도 했던 부분이 바로 리스트 페이지를 불러오는 기능입니다.

원래 하고 싶었던 기능은 스탯 4가지를 교집합으로 필터링하여 체력과 지능을 선택하면 체력과 지능 두 가지 스탯을 모두 가지고 있는 강의만 나오게 하고 싶었는데 교집합이 아닌 합집합만 나와서 결국 교집합 기능구현은 리팩토링 때 꼭 해내고 말겠다고 마음먹게 만든....그런 기능입니다.

제가 작성한 코드는 다음과 같습니다.

class ProductListView(View):
    @AuthorizeProduct
    
    def get(self,request):
            category       = request.GET.get('category', None)
            sub_category   = request.GET.get('sub_category', None)
            stat           = request.GET.getlist('stat', None)  
            
            q=Q()

            if category:
                q &=Q(sub_category__category__name=category)
                
            if sub_category:
                q &=Q(sub_category__name=sub_category)
                
            if stat:
                q &=Q(coursestat__stat__name__in=stat)
               
                
            products = Course.objects.prefetch_related('like_set').filter(q).distinct()
            
            results=[{  "course_id"      : product.id,
                        "thumbnail"      : product.thumbnail_image_url,
                        "user_name"      : product.user.name,
                        "sub_category"   : product.sub_category.name,
                        "course_name"    : product.name,
                        "price"          : product.price,
                        "payment_period" : product.payment_period,
                        "discount_rate"  : product.discount_rate,
                        "discount_price" : product.price * product.discount_rate / 100,
                        "course_like"    : product.like_set.count(),
                        "is_like_True"   : product.like_set.filter(user_id=request.user).exists()
                        } for product in products]
                
            return JsonResponse({"results" : results}, status=200)

Q객체를 활용하면 catgory/sub_category/stat에 맞는 강의를 가져오는 기능입니다. 이 코드는 코드리뷰하면서도 좋지 못한 코드라는 멘토님의 리뷰를 받았습니다.

이유는 if문을 많이 사용하여 코드가 선형적이지 못하다는 이유 때문입니다. 멘토님의 리뷰 후 수정된 코드는 다음과 같습니다.

class ProductListView(View):
    FILTERS = {
        "category"     : Q(sub_category__category__name=category),
        "sub_category" : Q(sub_category__name=sub_category)
        "stat"         : Q(coursestat__stat__name__in=stat)
    }

    [Q(sub_category__category__name=category), Q(sub_category__name=sub_category), Q(coursestat__stat__name__in=stat)]
    Q(Q(sub_category__category__name=category), Q(sub_category__name=sub_category))

    @AuthorizeProduct
    def get(self,request):
        query = functools.reduce(lambda q1, q2: q1.add(q2, Q.AND), [FILTERS.get(request.GET[key], Q()) for key in request.GET.keys()])
        products = Course.objects.filter(query).distinct()

아직 해당코드를 완벽하게 이해하지는 못했지만 if문을 하나도 사용하지 않은 선형적인 코드라는 것은 확실합니다.

이번 코드리뷰를 받기 전까지는 그저 기능을 구현하는것에만 신경써서 이 코드가 정말 좋은 코드인지 고민해보는 시간이 부족했던 것 같습니다.

앞으로 개발자로 성장하는 과정 가운데 단순히 기능구현에만 만족하는 것이 아니라 어떻게 선형적인 코드를 잘 작성할 수 있을지 고민해봐야 될 것 같습니다.

profile
주니어 백엔드 웹 개발자입니다.

0개의 댓글