[Clone-Coding]디즈니샵 프로젝트 후기

1. 프로젝트 목적물 설정

디즈니샵
https://www.shopdisney.com/
제품 카테고리를 줄이고 기능적인 측면을 구현하는데에 집중하기로 하였으며, 자세한 내용은 하기와 같습니다.

1) 구현 범위 설정

  • 150여개 카테고리와 다양한 IP를 보유하고 있는 쇼핑몰
    => 7개 카테고리와 3개 브랜드로 축소 구현
  • 랜딩페이지의 기획전을 비롯하여, 추천상품 등 제품 노출영역
    => 기획전 배너 2개, 추천상품 영역 1개
  • 그 밖의 제품구매 프로세스는 전체 구현
    => 제품탐색(필터링,검색) - 찜하기 - 장바구니 넣기 - 결제

2. 프로젝트 관리

1)일정관리

  • 의사결정록 notion 도입

    	특정 안건 열람이 어려운 standing회의록의 단점 보완하고자 의사결정록 도입.
    	이슈를 한눈에 열람하고 구성원간 공유 원활히 할 수 있도록 함.
  • trello + BigPicture

    	트렐로 카드는 개별 업무단위를, BigPicture는 전체 진도율 관리.

2)업무 배분

		크게 3가지 단위와 추가구현기능으로 업무를 나누었고, 
        붉은 테두리의 영역을 맡아 구현하기로 함.

3)기타 담당 내역

  • 프로젝트 개시 직후, 상품이미지/브랜드/이벤트배너 등 쇼핑몰 전반에 표시될 상품데이터 제작하여 스프레드시트 형태로 Backend에 전달.
    => 제품데이터를 사전에 픽스함으로써 기능의 범위가 명확해졌으며, Backend와의 소통 원활해짐. 아울러 프로젝트 막바지에 신경쓰기 어려운 이미지작업을 사전에 마쳐놓음으로써 팀원들이 개발에만 전념할 수 있는 환경 조성

3. 프로젝트 개발

GIT : https://github.com/JaySurplusYoon/31-1st-kidsney-frontend

3-1. Query Parameter활용한 제품탐색기능

1)구현화면

2)구성도

  • 제품탐색기능은 필터, 가격순정렬, 검색, 페이지네이션 4가지로 구분.

3)구현특징

  • 디즈니샵의 경우 필터링시 쇼핑몰 URL이 변하지 않음.
    따라서, useLocation에서 url을 받아 렌더링하는 방법 사용할 수 없음.
  • 대신 각 조건을 배열의 형태로 state에 저장하여 렌더링의 대상이 되는 queryString으로 만들어 렌더링하는 방식으로 구현함.

4)구현상세

(1) Product List에서는 Filter, Sorter, Search, Pagination에 필요한 state와 이를 수정할 수 있는 function을 만들어 각각의 컴포넌트로 전달.

  const handleFilter = (name, attr) => {
    const filterArr = [...filters];
    filterArr.includes(`${name},${attr}`)
      ? filterArr.splice(filterArr.indexOf(`${name},${attr}`), 1)
      : filterArr.push(`${name},${attr}`);
    setFilters(filterArr);
    setQueryStrings(filterArr);
  };

※필터의 경우 1회 클릭시 적용, 중복 클릭시 적용이 해제되므로, Splice로 중복된 인덱스의 필터배열을 제거하도록 함.

(2)각각의 컴포넌트에서는 onClick, onChange 등을 통해 내려받은 function으로 부모의 state를 수정하고 끌어올림.

 <li
 key={categoryAttr}
 className="categoryAttr"
 onClick={() => handleFilter(categoryName, categoryAttr)}
 >

(3)끌어올린 state값으로 queryParameter를 만들고 이에 의존성에 있는 useEffect내부의 fetch함수로 화면을 렌더링.

   switch (splittedFilter[0]) {
          case 'sub':
            addParamFilters.push(`&sub=${param}-${splittedFilter[1]}`);
            break;
          case 'size':
            addParamFilters.push(`&size=${splittedFilter[1]}`);
            break;
          case 'character':
            addParamFilters.push(`&character=${splittedFilter[1]}`);
            break;
          default:
        }

3-2. 서버통신을 통한 결제 및 주소업데이트 기능

1)구현화면

2)구현특징

  • 가입시점에 고객주소정보 입력하지않으므로, 배송정보를 수집 및 고객정보로 저장하는 기능 필요.
  • PG를 붙일 수 없으므로 고객마일리지에서 차감하는 형식으로 진행.

3)구현상세

(1)배송정보 유효성 검사 후, 고객이 입력한 주소를 기본배송지로 업데이트하겠다는 의사를 확인하고 이에 따라 결제대금 차감 및 주소 업데이트 진행.

  const submitOrder = () => {
    if (orderNecessaryInfo) {
      if (orderInfo.updateAddress) {
        postBalance();
        patchAddress();
      } else {
        postBalance();
      }
    } else alert('정보를 모두 입력해주세요');
  };

(2)결제는 POST방식으로 서버와 통신하여 진행하며 처리결과는 alert로 안내.

const postBalance = () => {
  fetch(`${BASE_URL}/orders`, {
    method: 'POST',
    headers: {
      Authorization: localStorage.getItem('token'),
    },
    body: JSON.stringify({
      total_price: subtotal,
    }),
  })
    .then(response => {
      if (response.ok) {
        alert('주문이 완료되었습니다.');
      } else if (response.message === 'moneyless') {
        alert('잔액이 부족합니다.');
      } else if (response.message === 'stockless') {
        alert('재고가 부족합니다.');
      } else {
        throw new Error('Unexpected Error');
      }
    })
    .catch(error => {
      // eslint-disable-next-line no-console
      console.log(error.message);
    });
};

(3)주소 업데이트는 PATCH방식으로 서버와 통신하여 진행하며 처리결과는 alert로 안내.

const patchAddress = () => {
    fetch(`${BASE_URL}/users/`, {
      method: 'PATCH',
      headers: {
        Authorization: localStorage.getItem('token'),
      },
      body: JSON.stringify({
        zip_code: orderInfo.zipCode,
        location: orderInfo.addressMain,
        datail_address: orderInfo.addressDetail,
      }),
    })
      .then(response => {
        if (response.ok) {
          alert('주소변경이 완료되었습니다.');
        } else {
          throw new Error('Unexpected Error');
        }
      })
      .catch(error => {
        // eslint-disable-next-line no-console
        console.log(error.message);
      });
  };

4. Lesson Learned

1) PR Attitude

  • 가능한한 세분화하여 PR 올릴 것.
  • Sider 및 컨벤션 면밀히 체크한 후 PR올릴 것.

2) Co work

  • 이슈발생시 즉각 논의하고 기록으로 남길 것.
  • 기록을 한눈에 찾아볼 수 있는 시스템을 활용하여 불필요한 회의는 줄일 수 있도록 할 것.
  • 팀원들의 코드를 리뷰하고 질의함으로써, 담당파트를 더욱 빠르게 구현하고 학습할 수 있음.
  • 담당파트와 더불어 전체그림의 진척도를 계속 상기할 것.

3) Hook

  • 리액트의 다양한 hook을 사용하며 dependency 및 불변성 학습
  • 깊은 복사/ 얕은 복사 개념 학습

좋은 웹페이지 즐겨찾기