들어가기

설 명절 동안에 인테리어 상품 소개 컴포넌트를 만드는 선택 과제가 들어왔습니다. 이 과제를 낸 기업은 평소에 유튜브를 통해서 자주 보고 있고, 너무 좋아하는 기업이라서 선택 과제이지만 안 할 수가 없었습니다. 결국 명절에는 부모님과 시간을 보내다가 명절 마지막날부터 작업을 시작하여 마무리했습니다.

준비

명절 기간이 거의 다 지났고 빠르게 프로젝트를 진행해야 하기 때문에 일단 구체적인 설계부터 시작했습니다.

레이아웃과 기능
레이아웃과 컴포넌트 이름
ToolTip의 종류

기본적인 기능들을 그림을 그려서 정리했습니다. 그리고 레이아웃과 컴포넌트를 어떻게 배치할 지 이어서 그림을 다시 그렸습니다. 배너라고 쓴 부분은 ToolTip이라는 이름으로 컴포넌트를 만들었는데, 해당 기업에서 쓰는 이름과 동일하게 하기 위해서 이름을 그렇게 지었습니다.

메인 컴포넌트는 ContentImage와 ProductList 두 개로 나누었는데 두 컴포넌트 모두 선택된 상품을 다뤄야 하기 때문에 currentProduct라는 상태를 추가하여 선택 값을 다루도록 했습니다.

Github의 Issue관리

혼자 진행하는 프로젝트이지만 남은 시간이 별로 없는 만큼 빠르게 진행하기 위해서 구체적으로 구현해야 하는 기능들을 issue에 추가하여 작업을 진행했습니다. 작업 진행 후 완료되는 대로 바로 이슈를 종료 시키는 방식으로 진행했습니다.

스타일링

css를 기본으로 하고 추가로 API에서 들어오는 ToolTip의 X, Y값을 활용하기 위해서 Styled Component를 사용했습니다. Styled Component를 사용하면 API에서 들어오고 변하는 값들을 스타일에 넣어서 사용할 수 있기 때문에 스타일 값을 실시간으로 변경할 일이 많을 경우 사용하면 유용합니다. 이 프로젝트에서는 Styled Component가 필요한 툴팁, 슬라이더에서만 사용하고 나머지는 기본 css로 작성했습니다.

툴팁

처음 툴팁을 구현했을 때 무조건 버튼 위에 뜨도록 구현했는데 예제로 구현된 화면에는 툴팁의 위치마다 말풍선의 위치가 다르게 되어 있는 것을 알게 되었습니다. API에서 X, Y값을 받을 때 500이 100%와 마찬가지 였기 때문에 ToolTip의 종류가 바뀌는 것을 X, Y값의 50%인 250을 기준으로 250이 넘어가면 형태가 바뀌도록 구현했습니다. X값이 250이 넘어가면 말풍선이 왼쪽으로 오고 아닐 경우 오른쪽, Y값이 250이 넘어가면 말풍선이 위로, 아니면 아래로 뜨도록 구현했습니다.

ToolTip의 종류 2

아쉬운 점 : 슬라이더라고 이름을 지었으면 좋았을 텐데...

밑에 나오는 부분이 캐러셀이라고 생각해서 이름을 캐러셀이라고 짓고 시작했는데 나중에 완성하고 확인해 보니 상품 리스트가 무한하게 돌아가는 것이 아니었습니다. 그냥 슬라이더라고 이름을 짓는 것이 나았을 것 같다고 생각이 듭니다. (계획 단계에서는 이게 캐러셀이 아니라는 것은 전혀 생각하지 못했습니다.)

고민했던 부분 : 슬라이더의 슬라이드 영역

ProductList 컴포넌트에 슬라이드 기능을 넣었는데 마우스가 컴포넌트 바깥쪽으로 넘어가면 onMouseLeave가 되면서 마우스 드래그 값이 이상해지는 버그가 발생했습니다. 결국 컴포넌트에 이벤트를 줬던 것을 document에 이벤트 리스너를 주어서 슬라이드 바깥쪽으로 드래그 되더라도 드래그 하는 move 값을 받아올 수 있게하여 문제를 해결했습니다.

const carouselMoveEvent = (event) => {
    setMoveValue(event.screenX - moveStartValue);
    document.removeEventListener('mousemove', carouselMoveEvent);
  };
  
  const carouselDownEvent = (event) => {
    setMoveStartValue(event.screenX);
  }

  const carouselTouchStart = () => {
    setIsMove(true);
    document.addEventListener('mousedown', carouselDownEvent);
  };

  const carouselTouchLeave = () => {
    setIsMove(false);
    document.removeEventListener('mousedown', carouselDownEvent);
    document.removeEventListener('mousemove', carouselMoveEvent);
    moveValue > 0 && setMoveValue(0);
    moveValue < -100 && setMoveValue(-100);
  };

  const carouselTouchMove = () => {
    isMove 
    &&
    document.addEventListener('mousemove', carouselMoveEvent)
  }

  useEffect(() => {
    productList && 
    selectItem === productList[0].productId && setMoveValue(0);
    productList && 
    selectItem === productList[productList.length - 1].productId && setMoveValue(-100);
  }, [selectItem])

  return <div className="wrapper">
    <Carousel 
      productLength={productList && productList.length}
      onMouseDown={carouselTouchStart}
      onMouseUp={carouselTouchLeave}
      onMouseLeave={carouselTouchLeave}
      onMouseMove={carouselTouchMove}
      moveValue={moveValue}
    >

해당 부분의 코드입니다. carouselTouchMove 함수를 보면 마우스가 down되었을 때 document에 이벤트리스너를 주어서 이동 값을 받아오게 했습니다. 그리고 carouselMoveEvent에서 이벤트 리스너를 닫아 주었습니다. 또한 useEffect부분에서 보이듯이 마우스 이벤트가 종료되었을 때 슬라이드의 위치가 상품리스트 바깥에 있는 경우 다시 상품 리스트가 있는 쪽으로 보이게 하기 위해서 moveValue 상태 값을 조정해 주었습니다.

마치며

지금까지 혼자 프로젝트를 진행하면서 issue를 사용한 적이 없었습니다. 항상 그림을 그리고 그 순서대로 구현을 했는데, 그림으로 그린 설계를 다시 issue에 리스트화 시키고 이것을 하나씩 클리어하면서 프로젝트를 진행하니까 게임을 하고 있는 것 같은 즐거움이 있었습니다. 앞으로 프로젝트를 진행할 때도 이런식으로 관리하며 진행하면 지금보다 더 빨리 프로젝트를 진행할 수 있겠다는 생각을 했습니다. 또한 선발 과제로 캐러셀 구현하기, 이번 과제에서 슬라이드 만들기를 해 보면서 다음에 비슷한 것을 구현해야 할 때 빠르게 할 수 있겠다고 느꼈습니다.

링크

github : https://github.com/b41-41/interior_information

Last modified: 2022년 02월 04일

Comments

Write a Reply or Comment

Your email address will not be published.