[1st Project] Brokurly?! ver 2.0 - 메인 View 완성

제갈창민·2021년 12월 16일
0

작업물

목록 보기
7/9
post-thumbnail

1. 코드 리뷰 - 종합

(주의) elif 의 악몽

class ProductView(View):
    def get(self, request):

        try:
            menu_name = request.GET.get('menu', None)
            sort      = request.GET.get('sort', '0')
            sort_dict = {
                'created_at' : 'created_at',
                'price'      : 'price',
                '-price'     : '-price'
            }
            
            if menu_name   == '채소전체':
                menu_name  = '채소'
                menus      = Menu.objects.get(name=menu_name)
                categories = Category.objects.filter(menu=menus).all()
                products   = Product.objects.filter(category__in=categories).all().order_by(sort_dict[sort])
                results    = []

            elif menu_name == '샐러드전체':
                menu_name  = '샐러드'
                menus      = Menu.objects.get(name=menu_name)
                categories = Category.objects.filter(menu=menus).all()
                products   = Product.objects.filter(category__in=categories).all().order_by(sort_dict[sort])
                results    = []

            elif menu_name == '과일전체':
                menu_name  = '과일'
                menus      = Menu.objects.get(name=menu_name)
                categories = Category.objects.filter(menu=menus).all()
                products   = Product.objects.filter(category__in=categories).all().order_by(sort_dict[sort])
                results    = []

            elif menu_name == '간편식전체':
                menu_name  = '간편식'
                menus      = Menu.objects.get(name=menu_name)
                categories = Category.objects.filter(menu=menus).all()
                products   = Product.objects.filter(category__in=categories).all().order_by(sort_dict[sort])
                results    = []

            if menu_name:
                menus      = Menu.objects.get(name=menu_name)
                categories = Category.objects.filter(menu=menus).all()
                products   = Product.objects.filter(category__in=categories).all().order_by(sort_dict[sort])
                results    = []

            for product_data in products:
                results.append(
                    {
                        'name'         : product_data.name,
                        'introduction' : product_data.introduction,
                        'price'        : product_data.price,
                        'image'        : [image.url for image in product_data.image_set.all()]
                    }
                )
            print(results)

            return JsonResponse({'result':results}, status=201)

        except AttributeError:
            return JsonResponse({'message' : 'AttributeError'}, status=400)
        
        except TypeError:
            return JsonResponse({'message' : 'TypeError'}, status=400)
            
        except Category.DoesNotExist:
            return JsonResponse({'message' : 'DoesNotExits'}, status=500)
            
class CategoryView(View):
    def get(self, request):
        try:
            category_name = request.GET.get('category', None) 
            sort          = request.GET.get('sort', '0')
            sort_dict     = {
                'created_at' : 'created_at',
                'price'      : 'price',
                '-price'     : '-price'
            }

            if category_name:
                categories = Category.objects.get(name=category_name)
                products   = Product.objects.filter(category=categories).all().order_by(sort_dict[sort])
                results    = []

            for product_data in products:
                results.append(
                    {
                        'name'         : product_data.name,
                        'introduction' : product_data.introduction,
                        'price'        : product_data.price,
                        'image'        : [image.url for image in product_data.image_set.all()]
                    }
                )
            print(results)

            return JsonResponse({'result':results}, status=201)

        except AttributeError:
            return JsonResponse({'message' : 'AttributeError'}, status=400)
        
        except TypeError:
            return JsonResponse({'message' : 'TypeError'}, status=400)
            
        except Category.DoesNotExist:
            return JsonResponse({'message' : 'DoesNotExits'}, status=500)

-> 사실 '--전체' 페이지는 카테고리 하나의 페이지와 똑같은 속성을 가진다. 다시말해, '채소전체'는 '채소'와 데이터가 동일하는 뜻이다. 근데 왜 굳이 중복코드를 도배해 가면서 '--전체'기능을 따로 만든 것일까. 첫째, 프론트와 내가 이해하고 있는 url의 사용법이 달랐기 때문이다. 둘째, 내가 '분리된 기능'에 사로잡혀서 데이터가 같다는 사실을 망각한 것이다. 코드리뷰에서 멘토님이 하신 한마디에 진짜 뒤통수 씨게 맞은 듯했다.

  • "이거 그냥, 프론트한테 url에다 '채소'라고 보내달라고 하면 되요."


아래는 코드 리뷰 후의 편안한 코드입니다.

class ProductView(View):
    def get(self, request):

        try:
            menu_name     = request.GET.get('menu', None)
            category_name = request.GET.get('category', None) 
            sort          = request.GET.get('sort', '-created_at')
            
            sort_dict = {
                '-created_at' : '-created_at',
                'price'       : 'price',
                '-price'      : '-price'
            }

            if menu_name:
                menu     = Menu.objects.get(name=menu_name)
                products = Product.objects.filter(category__menu=menu).order_by(sort_dict[sort])

            if category_name:
                category = Category.objects.get(name=category_name)
                products = category.product_set.all().order_by(sort_dict[sort])

            results = [
                {
                    'id'           : product_data.id,
                    'name'         : product_data.name,
                    'introduction' : product_data.introduction,
                    'price'        : product_data.price,
                    'image'        : [image.url for image in product_data.image_set.all()]
                }for product_data in products]
             
            return JsonResponse({'result':results}, status=200)

        except KeyError:
            return JsonResponse({'message' : 'KeyError'}, status=400)
        
        except Category.DoesNotExist:
            return JsonResponse({'message' : 'CategoryDoesNotExist'}, status=400)

-> 코딩테스트에서나 봤을 법한 elif와 중복코드들이 모두 삭제되고 2개의 클래스가 1개로 통합되었다. '전체보기' 기능은 멘토님의 조언대로 프론트에 요청했고, 프론트에서는 Query parameter/product?menu='채소'&'category='브로콜리'&sort='price' 와 같이 요청 정보들을 담아서 보내는 것으로 결론 지었다.

-> 새롭게 '__'(언더바언더바) 기능을 배웠는데, 형태는 비슷하지만 전혀 다른 기능을 하는 메소드였다. 구글링 도중 찾았던 __in 기능과도 많이 달라서 매우 신기했다. category__menu=menu 는 시작지점인 Product가 참조하고 있는 category를 슥- 하고 지나가서 category가 참조하고 있는 menu까지 곧바로 도달하게 하는데, 이는 쿼리문을 줄이는 데에 그 목적이 있는 것이다. 원래는 menu를 참조하는 category를 한번 찾는 쿼리문을 쓰고 거기서 다시 Product가 참조하고 있는 category를 찾아야 하는데, 그 과정을 줄여주는 것이다.

-> 잘 모르겠으면 shell을 적극 사용하자.

  1. __ 대신 __in을 사용했을 때 :

  2. __ 사용 했을 때 :

  3. 2번 실험에서 __in을 사용 했을 때 :

-> Wow!

2. Final Reivew

-> 먼저 프론트와의 마지막 결론에 도달하기까지 해당 팀원들에게 여러번 정보 수정을 요청해야해서 너무나 미안했었다. 그래도 끝까지 이해해주고 수용해준 팀원들에게 그저 고개숙여 감사할 따름이다.

-> 이번 프로젝트에서는 보다 다양하고 고난이도의 코드를 많이 알았다기 보단, 협업에 대해 많이 배운 시간들이었다. 프론트 용어들에 대해 문외한에 가까웠기에, 컴포넌트가 뭔지, 모달이 뭔지, fetch(퓃치)가 뭔지부터 물어보는게 먼저였다. 또한, 반대로 내가 아는 백엔드 용어들을 설명해 주는 것도 많은 어려움이 있었다. 나에게는 익숙한 쿼리문이나 DB 용어들이 그들에게는 ??? 하는 내용들이어서 설명하기 전에 두번 세번 고민하고 비유를 최대한 사용해서 설명하려고 노력했었다.

-> 앞으로 있을 더 많은 협동와 협업에 있어서 이런 일이 없을리는 없겠지만, 분명 그 빈도를 줄일 수는 있을 것이다. 줄여야만 하고, 줄여 나갈 것이다. 그 과정에서 더 많이 깨지고, 실패하고, 좌절하고, 후회하겠지만 그정도는 겪을만큼 겪었고 넘어진 후에 일어나는 것이 익숙하다. 다만, 이전까지는 혼자 짊어져야해서 그냥 체념하고 일방적인 수용하는 자의 입장에 있었던 지난날 과는 다르게 이젠 혼자가 아니다. 나는 팀의 일부이지만 팀은 나의 전부이다. 그런 마음으로 앞으로의 개발자 인생을 걸어나갈 것이다. 분명, 그러할것이다.

profile
자기계발 중인 신입 개발자

0개의 댓글