✚ Dr.Martens 상품 리스트 레이아웃 때문에 고군분투한 이야기😱 (feat. 재귀함수)

Solmii·2020년 6월 30일
3

Project

목록 보기
8/14
post-thumbnail
post-custom-banner

열심히 구현중인 닥터마틴 사이트!

오늘은 Product List 페이지에서 닥터마틴의 3-2-3-1 레이아웃을 구현하기 위해 고군분투 한 이야기를 써보려고 한다....

솔직히 진짜 때려칠뻔 했다.....

어떻게든 길고 긴 함수를 써서 구현해내긴 했으나, 엄청 난해하고 복잡한 함수만 남아버렸다...............😭

그 길고 난해하고 복잡한 함수 보러 가시죠..!!!


   problem   

닥터마틴 사이트의 제품 리스트 페이지!!
화면을 억지로 줄여서 많이 깨졌다. 닥터마틴이 반응형 사이트가 아닌지라...........

보다시피 제품이 3개 - 2개 - 3개 - 1개 순서로 정렬되있다!
이때, 3개 부분은 이미지가 하나 / 2개와 1개 부분은 이미지가 두 개이다.
(이하 지옥의 3-2-3-1 레이아웃이라고 칭함)

이 다음 제품도 다시 지옥의 3-2-3-1 레이아웃으로 반복된다!

근데 여기서 문제는, 신발안에 서브 카테고리 (부츠, 슈즈, 샌들)을 누를때마다 해당 카테고리에 맞는 제품만 출력되야 하는데, 원래 닥터마틴 사이트는 카테고리를 누를때마다 데이터를 새로 받아오는듯 하지만(대부분의 사이트가 그렇다고 하니 아마도...?)

우리는 그렇게 매번 받아오기가 힘든 상황이었다....!
(닥터마틴이 데이터도 복잡하고, 백엔드에서 처리할 일이 많아서 매 카테고리의 데이터를 짜기 힘든 상황이었다...😭)

3-2-3-1 레이아웃을 포기하고 그냥 같은 컨테이너에 담아서 보여줄수도 있지만, 그렇게는 하기 싫었다....


   Thinking   

흠, 어떻게 해야 3-2-3-1로 나타낼 수 있을까?
여러가지 방법이 있겠지만, 혼자 생각해보고 멘토님들께도 계속 여쭤본 결과,

들어오는 데이터 자체를 유저가 선택한 카테고리로 1차 filter를 걸고, 그 결과값을 이미지가 하나인 배열[], 이미지가 두개인 배열[]에 각각 담는다.
최종적으로 두 배열에서 3개, 2개, 3개, 1개를 번갈아 꺼내서 새로운 배열에 담아서 map을 돌린다.
이미지 박스의 자세한 스타일은 scss에서 nth-child 를 이용해서 지정하기로...!


   My Solution   

 imgArraySorter = (data) => {
    let categoryFilter = data.filter(
      (product) =>
        product.id === this.state.currentCategoryId ||
        this.state.currentCategoryId === 0
    ); // user가 선택한 category id와 일치하는 product만 반환
   
    let lengthOne = [];
    let lengthTwo = [];
    let result = [];

    for (let i in categoryFilter) { // filter된 결과값을
      if (categoryFilter[i].productImg.length === 1) {
        lengthOne.push(categoryFilter[i]);
      } else {
        lengthTwo.push(categoryFilter[i]);
      }
    } // length에 따라(이미지가 한개/두개) 각각 다른 배열에 push

    let arraySort = (arr1, arr2) => { // 재귀함수 시작, 파라미터로 배열 2개를 받는다.
      result = [...result, ...arr1.slice(0, 3)];
      arr1.splice(0, 3);
      result = [...result, ...arr2.slice(0, 2)];
      arr2.splice(0, 2);
      result = [...result, ...arr1.slice(0, 3)];
      arr1.splice(0, 3);
      result = [...result, ...arr2.slice(0, 1)]; // 3, 2, 3, 1개씩 순서대로 result에 추가하고,
      arr2.splice(0, 1); // 추가된 후에는 원본 배열에서 삭제한다.

      if (arr1.length < 3 || arr2.length < 1) {
        result = [...result, ...arr1];
        result = [...result, ...arr2];
        return result; // 사실 이 재귀함수 종료 조건이 문제다....자세한 이야기는 밑에서...!
      }

      return arraySort(arr1, arr2); // 종료 조건에 안걸린다면, 다시 재귀함수를 실행한다.
    };
    return arraySort(lengthOne, lengthTwo); // arraySort 재귀함수에 인자로 위에서 분리해둔 lengthOne, lengthTwo 를 전달해준다.
  };

이런 말도 안되게 어려운 코드가 완성되었고..........ㅎ
(2시간동안 같이 코드카타 해주신 인호 파트멘토님 감삼다😭😭😭😭😭😭)

여기서 재귀함수 종료 조건에 문제가 있다.
lengthOne가 3개 미만 혹은, lengthTwo가 0개에서 바로 resultreturn 하면, 마지막 상품 몇개는 못팔게 된당.....ㅎ.ㅎ
그래서 남은 아이들을 그냥 result 에 다 붙였더니.... 마지막 상품들이 엄청 깨지게 된당😭
nth-child 를 이용해서 위치에 의존하는 스타일을 적용했기 때문에........ㅠㅠ
그래서 일단 마지막 상품 몇개는 팔지 않는걸로(ㅋㅋㅋㅋㅋㅋㅋ) 정했는데, 시간이 되면 더 깔끔하게 리팩토링 하고 싶다!!!


{productListData &&
   this.imgArraySorter(productListData).map((product, idx) => (
   <ProductListItem data={product} key={idx} />
))}

그리고 이 결과값으로 map 을 돌린다!!!

이렇게 전체 화면도 잘 나오고!!


세부 카테고리 클릭 시 위의 로직대로 이미지가 재정렬되서, scss 적용후에 예뿌게 잘 나온다!!!

profile
하루는 치열하게 인생은 여유롭게
post-custom-banner

0개의 댓글