프리온보딩 | 6번째 과제 회고 - 3주차

noopy·2022년 2월 14일
2

프리온보딩

목록 보기
5/6
post-thumbnail

Wanted-preonboarding 3-1

💡 정보
깃허브 링크
배포 링크

⏰ 기한

  • 2022/02/14 ~ 2022/02/16 오전 10시

📕 구현 명세

  1. figma를 바탕으로 모바일 웹 페이지 클론
  2. Next.js, Typescript 사용하기
  3. E2E 테스트 구현

(내가 맡은 부분 ✅)

모바일 웹 페이지 클론

  • 홈 페이지 ✅ (배너 캐러셀만 = Swiper)
    • 배너 캐러셀 부분은 임의로 데이터 활용하기
  • 브랜드 페이지
  • 상품리스트 페이지
  • 상품상세 페이지
  • 고객센터 페이지 ✅

🪞 데모

홈페이지브랜드 페이지, 상품리스트 페이지
홈페이지브랜드, 상품리스트
상품상세 페이지고객센터 페이지
상품상세고객센터

⏰ 진행 과정

🧐 컴포넌트 폴더구조의 의문점

항상 우리 팀원들과 하던 데로 피그마와 웹사이트를 분석하고 가장 작은 단위인 base 컴포넌트부터 만든다. 다만 컴포넌트 폴더구조를 단순히 base, domain으로 나누다 보니 기준이 명확하지 않아 domain으로 가야할 게 base로 섞여 들어간 느낌이 강했다. 내 기준으론 base는 진짜 더이상 나눌 수 없는 최소단위고 domain는 다수의 base 컴포넌트가 섞이는 건데 팀원들에게 이 부분이 명확하지 않았나 보다.

그리고 컴포넌트 폴더 이름이 domain인데 domain으로 컴포넌트를 나눈 것도 아니어서 이름의 목적대로 쓰지 않는다는 느낌이 들었다. 따라서 이 다음 프로젝트에선 Atomic 패턴으로 진행해볼까 한다. 과연 화학구조로 컴포넌트를 나눈다면 어떨 지? 기대가 됩니다.

💬 진행사항 공유하기

팀원들과 어느정도 프로젝트를 진행하다보니 진행 사항 공유하는 시간이 굳어지게 되었다. 즉 프로젝트는 거의 이틀 간 주어지는데 (첫날 오후 4시 ~ 막날 오전 10시) 오후에 1번 (2시 혹은 4시), 당일 저녁 9시 반에 한번 어느정도 진행하고 앞으로 뭘할 건지 공유하는 시간을 갖는다. 이때 궁금하거나 해결못한 것들은 화면 공유하고 다같이 해결한다. 또 사실 google meet 에서 거의 48시간 붙어있기 때문에 두 시간 정도? 고민해봤는데 답이 안나오면 SOS를 쳐서 작업에 지체가 없도록 하였다.

💡 정리

  • 오후 2시/ 4시, 오후 9시 반 현황 공유, 할일 정리
  • 2시간 이상 고민했는데 답이 안나올 경우 SOS로 다같이 해결

1️⃣ 고객센터 페이지 구현

고객센터

고객센터 페이지는 우선 ContactTab 컴포넌트, DropdownList 컴포넌트가 사용된다. 기존에 팀원이 만든 NavigationBar 컴포넌트를 사용하면 될꺼라 생각했지만, 다른 부분들이 꽤 있어서 재사용할 수 없다고 생각했다.

NavigationBarTab

아니 지금보니까 뭔가 재사용할 수 있을 것 같은데,,, 이럴 때 HOC를 쓰면 좋을 것 같다. 공통으로 사용할 Tab 컴포넌트를 만들고 위에 HOC로 로직을 추가하는 ? 형식으로 만들면 되지않을까 추측해본다.

어쨌든 Tab 컴포넌트에서 useTab 훅을 만들어서 썼더니 편했다. 간단하게 받아온 데이터에서 인덱스로 값을 리턴해주는 형태이다. 해당 값은 아래 DropdownList에서 사용된다.
DropdownLIst 컴포넌트 로직을 쪼금 고민했는데 최상위 컴포넌트에서 클릭한 아이템의 index를 받기 위해 useClickedId 훅을 만들어서 사용했고 clickedId를 하위 Dropdown 컴포넌트가 받아서 사용했다. Dropdown 컴포넌트는 받아온 id와 현재 map의 인덱스랑 비교해서 isToggle 값을 바꿔준다.

  const [isToggle, setToggle] = useState(false);

  useEffect(() => {
    setToggle(clickedId === id ? true : false);
  }, [clickedId]);

다만 clickedId는 하나이기 때문에 탭 전환 시 isToggle된 값이 유지가 되버린다. 탭 전환 시에 clickedId를 초기화해주면 해결!

2️⃣ Swiper 구현

하... 정말 다사다난한 시간이었다. Swiper를 많이 구현해봤다 생각하고 호기롭게 도전했는데 다 만들어놓고 무한 스와이퍼에서 처음으로 돌아갈 때 애니메이션 잠깐 끄는 게 안돼서 호로록하고 처음으로 돌아가는 게 보였다. 마음이 아팠다 😣. 스와이퍼 로직은 useSwipe에 작성했다.
이걸 2시간 넘게 고민하고 결국 SOS 쳤는데 onTransitionEnd 이벤트가 있다는 걸 알려주셔서 도움을 받아 해결했다. 기존에는 스와이퍼 이동 이벤트가 끝나면 0.3초동안 애니메이션을 켰다 꺼서 슬라이드가 슉하고 자연스럽게 속도를 받았다 사라지도록 했다. 문제는 0.3초 동안 애니메이션이 켜졌다 바로 꺼져서 isTransition 값을 추적하기가 힘들다는 것이다.

무한 스와이퍼 시에 setInterval로 3초마다 한번씩 오른쪽으로 이동시켰는데 중간에 애니메이션을 잠깐 끄는 방법을 찾을 수가 없었다. 추측하기론 setInterval비동기적으로 동작하며 몇 초마다 내부 함수를 실행시키는데 setInterval 내부에서 외부 데이터를 받아 조건을 따지려 해도 이미 콜스택이 비워져 있기 때문에 setInterval에 전달할 수 없다. 그럼 바깥에서 interval을 껐다 켰다 해야하는데 intervalId에 할당 전이므로 가져올 수도 없다.

팀원들과 머리를 맡댄 끝에 나온 결론은 애니메이션을 그냥 상시 주고 특정 조건에서만 껐다가 다시 키자! 였다. 또 setInterval 이벤트를 setTimeout으로 대체했다. 어차피 특정 조건이 바뀌면 useEffect가 내부 로직을 다시 실행해서 마치 setInterval을 준 것처럼 일정하게 반복된다.

  useEffect(() =>
    let timerId: NodeJS.Timer;

    if (!isTransition) {
      // @NOTE: Transition이 꺼지면 슬라이드 위치를 처음으로 옮기는 로직

      setTimeout(() => {
        // @NOTE: 위치를 바꾸고 0.1초 후에 다시 애니메이션 넣어줌
        setIsTransition(true);
      }, 100);
    }

    if (!isDragging) {
      // @NOTE: 드래그 상태가 아닐 때 오른쪽으로 하나씩 이동시킴
      timerId = setTimeout(() => {
        shiftSlide('right');
      }, INTERVAL_TIME);
    }

    return () => clearTimeout(intervalId);
  }, [currentIndex, isTransition, isDragging]);

그렇게 탄생한 코드...!

🔑 KEY POINT

  1. Swiper에서 받아오는 이미지는 unsplash에서 무작위로 가져오기
    Next/Image를 활용하지 않으면 unsplash에서 무작위로 데이터를 가져오는데 Next/Image가 주소를 캐싱해서 주소가 같으면 같은 이미지를 보여준다 ㅋㅋㅋㅋㅋ 하... 일부러 무작위로 보여줄려고 unsplash 이미지 사용한건데 웃프다...
    아 그리고 unsplash에서 받아오는 이미지 용량이 엄청 커서 데이터를 받아오는 데 진~ 짜 오래걸렸는데 Next/Image에서 preload 기능과 priority 기능으로 초기 다운 속도를 엄청 낮출 수 있었다..! 대박 혁신!!!!

💡 preload, priority
preload: 대상이 viewport에 들어왔을 때만 다운로드 하는 속성 (기본 값 true)
priority: 대상을 우선적으로 다운받음. (LCP 일 땐 무조건 사용하기)

  1. Next의 SSR과 CSR을 잘 구분해서 쓰기
    저번 Surf 프로젝트에서 Next.js를 사용해봤었는데 SSR을 잘 활용하지 못해서 아쉬웠었다. 그 덕에 이번에 Next.js의 getServerSidePropsStaticProps 등을 실컷 사용했는데 예상치 못하게 진짜 라우팅이 너무너무 느려서 당황했다. 시간부족으로 그대로 제출했는데 이점이 좀 아쉽다. 점점 많은 기업들이 Next.js를 활용하는데 우리 프로젝트가 너무너무 느린 걸 보니 CSR과 SSR을 사용해할 곳을 잘 구분해서 써야할 것 같다 ㅋㅋㅋㅋ.
    공식문서에선 데이터 변동이 빈번히 일어나면 CSR을 쓰라고 권고한다.
브랜드, 상품리스트 페이지고객센터 페이지
브랜드고객센터

그니까 우리 브랜드 페이지NavigationBar를 누를 때마다 데이터를 요청하기 때문에 겁나게 느린 것이다. 이 때는 SSR이 아닌 CSR을 사용해야 한다. 반면에 오른쪽 고객센터는 SSR을 썻음에도 불구하고 굉장히 빠르게 로드되는 것을 볼 수 있다. 한번 데이터를 요청하고 변경되지 않기 때문에 이 때는 SSG나 SSR이 적당하다.
그나저나 상품 상세 페이지에서 이미지들은 로드가 왜이렇게 느릴까? preload가 적용되지 않은 느낌이 드는데 나중에 확인해봐야겠다. 그리고 라우팅은 또 왜이렇게 느릴까? 허허

🌈 결론

이번엔 Next.js로 모바일 웹 사이트를 클론하는 과제였다. Next를 완벽히 이해하고 적용한 것이 아니라 문제가 좀 있지만!!! 그럼에도 불구하고 SSR과 CSR을 더 잘 이해할 수 있었던 과제였다. 그리고 여태 과제중에 가장 많이 시간을 들인 과제이기도 하다. 새벽 4시까지 하고 정신이 혼미해져서 4시간 자고 일어났다 ㅋㅋㅋㅋㅋㅋ.
아쉽게도 E2E 테스트를 진행하지 못했는데 얼른 틈틈이 테스트를 공부해서 적용해보고 싶다 진짜찐짜

profile
💪🏻 아는 걸 설명할 줄 아는 개발자 되기

0개의 댓글