1차 프로젝트 2. 실전

코지클래식·2021년 10월 13일
0

Mecook

목록 보기
2/4

1차 프로젝트를 진행하면서 깨진점 / 느낀점에 대해 회고를 해본다.

1. 맡은 임무

나는 쇼핑몰에서 상품 관련된 데이터모델/API를 맡았다.
이는 상품 목록(카테고리) / 상품메인 / 상품의 상세페이지 / 각종 해시태그 + 좋아요의 '조회' 기능이 필요한 내용이었다.

2. 진행

1. 초기세팅

여기에서 나는, 프론트엔드에서 보고 싶어하는 데이터를 직접 보여주기 위해 기획된 대로 상품 모델링을 한 이후, 쇼핑몰에서 대표이미지를 하나 골라 예쁜 상품 페이지를 하나 만들고

먼저 raw 데이터를 보여주는 페이지를 만들었다.
아래의 코드처럼

2. 페이지별 기능 생성

그 다음, 나는 프론트엔드의 요청에 따라
카테고리별 / 상세페이지별 / 좋아요순 등으로 상품목록을 보여주도록 코드를 작성한다.

(* 이런식으로 각 테이블마다 Model.objects 를 사용하는 클래스를 3개 정도 만들었음. 이후 다른 기능이 추가될 때마다 Model.objects 는 추가되기만 함.)

3. 리팩토링

이후, Model.objects가 호출되는 빈도를 줄이고자 select_related(), prefetch_related()를 사용해서 코드를 변경했다. 여기서 보면, 위에서는 5~6 회정도 DB와 접속했다면, 아래에서는 2회로 줄인것을 알 수 있다.

class DetailByProduct(View) :
    def get(self,request,product_id) :
        
        @login_decorator
        def get_user_id(self,request) :
            return request.user.id
        
        # product 테이블의 ID를 foreignKEY로 사용하는 테이블들을 한번에 가져오기 위해 prefetch_realated사용
        products = Products.objects.select_related('category'
        ).prefetch_related('product_main_images'
        ).prefetch_related('products_hashtag'
        ).prefetch_related('product_detail_attrs'
        ).prefetch_related('like_by_product'
        ).filter(id=product_id)[0]

        likes = products.like_by_product.count()
        
        hash_numbers    = [x['hashtag_id'] for x in list(products.products_hashtag.values('hashtag_id'))]
        hash_names      = [x['name'] for x in list(Hashtags.objects.filter(id__in=hash_numbers).values('name'))]
        detail = [{
            "text"      : i.text,
            "image_url" : i.image_url,
            "priority"  : i.priority,
            } for i in [attr for attr in products.product_detail_attrs.all() if attr.product_id==product_id]]
        

        result = {
            "image"     : products.product_main_images.get(product_id=product_id).main_image_url,
            "category"  : products.category.name,
            "name"      : products.name,
            "likes"     : likes,
            "hashtag"   : hash_names
        }
        
        if 'Authorization' in request.headers :
            user_id                     = get_user_id(self,request)
            like_boolean                = bool([like for like in products.like_by_product.all() if like.user_id==user_id])
            result["this_user_like"]    = int(like_boolean)

        return JsonResponse({
            "result" : [result],
            "detail" : detail
        })

3. 후기

select_related()와 prefetch_related()가 어떤 것인지,
그리고 사용방법에 대해 '대략적으로' 찾아서 사용했다.

그러나 이 코드들이 실제로 효율적인지 테스트를 하기가 어렵고, (데이터가 20개정도씩밖에 없어서 효율성 검사를 해보기 어려움), 상품조회 기능들마다 중복되는 기능들이 꽤 있는데, input 받는 값에 따라
SQL문의 메인이 되는 테이블이 달라져서 코드를 합치기도 애매하다.

생각해보면 각 기능들을 간단하게 구현하는 것은 각각 30분정도가 안 걸린것 같은데,
코드가 나뉘어 있어서 각각 효율적으로 변경하기 위해 select_related와 prefetch_related를 적용하는데에는 한참이 걸렸다.

profile
코지베어

0개의 댓글