본문 바로가기

WEB

캐러셀... 너 뭔데 나를 이렇게 힘들게 해...

비비비상... 감자 윤신지... 메인 페이지 캐러셀을 담당하다!!.... 우당탕탕 캐러셀 일기 시작합니다.

 

 

안녕하세요! 메인 화면과 예매 조회 페이지 개발을 맡은 윤신지입니다. 🐤 저는 감자 개발자인데... 메인 페이지가 확장될 여지도 많고, 저같은 감자 개발자에게 적절한 챌린징 요소가 있다고 생각하여 메인 페이지를 하고 싶다고 어필을 하게 되었어요. 🫶 덕분에 메인 페이지를 맡게 되었습니다~~

 

 

햄버거바도, 플로팅 버튼도 예상치 못하게 저를 힘들게 하였지만 개발 전 저에게 가장 걱정되는 부분은 롤링배너라고도 불리는 캐러셀이었습니다! 😢 물론 이전에 진행한 작은 프로젝트에서 캐러샐을 라이브러리 없이 구현한 경험이 있었지만, BEAT의 캐러셀과는 조금 다른 방식으로 동작하기도 하였고 모바일 뷰에서 캐러셀을 구현해 보는 것은 처음이라 조금 떨렸습니다!

 

 

제가 받은 뷰는 이런 구성의 캐러셀이었는데요! 5초에 한 장씩 애니메이션과 함께 슬라이드 되고, 하단의 인디케이터가 함께 넘어가는 구성이었습니다! 

 

import { useEffect, useRef, useState } from "react";

const Carousel = ({ promotionList }: PromotionComponentProps) => {
  const navigate = useNavigate();

  const [currIndex, setCurrIndex] = useState(1);
  const [currList, setCurrList] = useState<string[]>();

  const carouselRef = useRef<HTMLUListElement>(null);
  
  const carouselList = promotionList.map((promotion) => promotion.promotionPhoto || "");

  // 인덱스 번호 변경
  const moveToNthSlide = (index: number) => {
    setTimeout(() => {
      setCurrIndex(index);
      if (carouselRef.current !== null) {
        carouselRef.current.style.transition = "";
      }
    }, 500);
  };

  // 슬라이드 이동할 때 무한 + 어색하지 않도록 처음과 끝 반복
  useEffect(() => {
    if (carouselList.length !== 0) {
      const startData = carouselList[0];
      const endData = carouselList[carouselList.length - 1];
      const newList = [endData, ...carouselList, startData];

      setCurrList(newList);
    }
  }, [carouselList]);

  // idx 변경되면 위치 이동
  useEffect(() => {
    if (carouselRef.current !== null) {
      carouselRef.current.style.transform = `translateX(-${currIndex}00%)`;
    }
  }, [currIndex]);

 

저는 moveToNthSlide 함수를 통해 인덱스 번호를 변경하였습니다. 이때 가장 중요한 부분은 무한 캐러셀을 제작할 때 처음과 끝이 자연스럽게 이어지도록 캐러셀 리스트의 처음과 끝에 각각 끝과 처음 데이터를 하나씩 추가해 주어야 합니다! 그렇지 않으면 마지막과 처음의 연결이 어색하고 마지막이나 첫 번째 리스트가 종종 사라지는 경우가 생깁니다..

또한 currIndex를 useEffect의 deps에 넣어주어 현재의 인덱스가 변경될 때마다 그 인덱스 번호만큼 translate를 주도록 구현하였습니다.