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

이태연·2021년 12월 26일
0

이번 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개의 댓글