[SuperfluidClone] 2nd project - superfluid 클론 9일차: prefetch_related를 이용한 전체 상품뷰 구현

Alex of the year 2020 & 2021·2020년 8월 11일
0
post-thumbnail

쉽지 않은 Filtering

Superfluid 홈페이지의 Shop 메인뷰는 (shop을 누를 경우 렌더링 되는 페이지)
사진처럼 category와 apply on 두 가지 기준으로 상품을 나눈다.

category는 색조 화장품(Color), 기초 화장품(Care) 별 분류이며
apply on은 말그대로 해당 제품을 어디에 사용하는지에 따라 lips, eyes, face로 분류한다.

category 내 color와 care를 중복 선택할 경우 모든 제품이 노출되며
apply on 내 lips eyes face를 모두 선택할 경우에도 모든 제품이 노출된다.

한 가지 더 구현을 복잡하게 만드는 요인은

1) Category의 color(Category 1개 선택)와 Apply on의 lips, eyes(Apply on 2개 선택)

2) Category의 color, care(Category 2개 선택)와 Apply on의 lips(Apply on 1개 선택)

이런 식으로의
카테고리 별, 어플라이 온 별 마구 잡이 중복 선택 또한 가능하다는 것이다.

지난 1차 프로젝트에서 오로지 회원가입/로그인 그리고 리뷰 크롤링만 다뤄보았기 때문에 get method를 이용한 전체 혹은 필터링된 일부 상품 뷰 렌더링 코드 구현을 꼭 해보고 싶었다. 이것이 객관적으로 크게 난이도 있는 코딩은 아닐 것이다. 그러나 내 입장에서는 구글링과 함께하는 삽질, 그리고 소중한 위코드 동료들이 없었다면 어려웠을 코드였다. 잊지 않기 위해 이 바쁜 와중에도 꼭! 남겨야겠다.

Get method로 무엇을?


Shop main을 구성하고 있는 정보들을 모두 보내준다했을 때, 나는 프론트에게

1) 모델 사진 이미지 (호버 전에는 등장하지 않다가 마우스 호버 시 등장)
2) 제품 사진 이미지
3) 해당 제품의 이름 (위 사진에서는 'B.L.U.R PRIMER BLUR'에 해당)
4) 해당 제품의 제품군 (위 사진에서는 'MOISTURIZER'에 해당)
5) 가격 (위 사진에서는 '26유로'에 해당)

에 해당하는 데이터를 모두 넘겨야 했다.
이 때는 데이터를 넘기기만 할뿐(Read), 해당 정보를 새로이 작성(Create)하거나 수정(Update) 혹은 새삭제(Delete)하기 위한 메소드가 아니기 때문에 GET을 사용하는 것이 RESTful API 사용을 생각한다면 적절했다.

데이터를 넘겨 구현하는 과정은

1) 필터링 없이 모든 상품을 몽땅 보여주는 전체 상품 뷰
2) 필터링을 거친 상품을 보여주는 일부 상품 뷰

로 나누어 생각했고 조금 더 구현이 쉬운 전체 상품 뷰를 먼저 짜봤다.

Superfluid는 상품이 21개(색깔 다른 상품도 다른 상품으로 쳐서)밖에 없어서 전체 상품 뷰를 구현한 후, 잘 구현이 된 것인지 postman으로 check할 때 참 편리했다.

그리고 이 전체 뷰 구현을 위해 17번째 줄에서 보이다시피
prefetch_related라는 것을 드디어 사용했다.

Prefetch_related가 이런거구나

Superfluid 홈페이지 내의 상품과 Category, 어플라이온(이하 applying), 그리고 image는 이러한 모델링 관계 속에 있다.

내가 렌더해야 하는 정보 중 제품 이름, 제품군, 가격은 product table에만 접근해도 충분히 끌어올 수 있는 정보이지만,

모델의 이미지나 제품의 이미지는 product table 내에 모델링 하지 않았기 때문에(위의 모델링을 보면 image 테이블을 따로 빼놓은 것을 볼 수 있다.)
product table이 역참조 하고 있는(잠깐! 역참조란: Aquerytool 상에서 기준 테이블(현재는 product)이 참조를 '당하고' 있다면, 즉 화살표를 '받고' 있는 입장이라면 '역참조' 관계에 있다고 이야기함) images 테이블을 prefetch_related로 엮어주어 DB에 접근하는 것이 효율적인 것이다. 그렇지 않을 경우, 머리 싸매가며 모델링한 관계형 DB의 이점을 누리기 어려울 뿐더러 각각의 테이블에 모두 접근해야하므로 효율성도 떨어지게 될 것이다.

즉 17번째 줄의Product.objects.prefetch_related("image_set").all()의 코드의 의미는
Image 테이블을 역참조하고 있는 Product 테이블에 있는 모든 객체를 나열해줘 라는 의미가 되며, 이런 역참조 관계를 나타낼 때에는 그냥 .prefetch_related("image")로 작성하지 않고, 역참조 테이블 뒤에 _set을 붙여 .prefetch_related("image_set") 이라고 쓰도록 한다.

23, 24번째줄에서처럼 실제로 이미지 테이블 내 속성인 image_url을 가져올 경우,
17번째 줄 코드에서 이미 모두 불러놓은 product 객체를 의미하는 product. 뒤에 이제는 Product 테이블을 넘어 image 테이블에 접근한다는 의미를 담은(?) .image_set을 써주면 이제는 역참조 관계에 있는 image 테이블의 정보에 접근할 수 있는 준비를 마치게 된다.

그리하여 이 코드를 포스트맨으로 작동시켜보면?


이렇게 모든 상품의 정보가 잘 들어온 것을 확인할 수 있다.

실은
QueryString GET.getlist를 사용한 FilterView도 구현해서 그 내용과
git rebase를 배우며 얼마나 심장이 떨렸는지에 대해
꼭 블로깅하고 싶었는데
지금 팀 프로젝트가 바쁘니 이 내용은 오늘 혹은 내일 혹은 팀 프로젝트가 끝나면 적어야겠다.

profile
Backend 개발 학습 아카이빙 블로그입니다. (현재는 작성하지 않습니다.)

0개의 댓글