본문 바로가기
FrontEnd Develop/Project : AI TUTOR

튜토리얼 모달 컴포넌트 기능 개발 #2. 상세 설계서

by Frisbeen 2025. 3. 11.

튜토리얼 모달를 개발했는데, 생각보다 공부할게 많아 좀 더 상세히 분석을 했습니다. 

 

1. 컴포넌트 역할 개요

 

  • OnBoardingModal.tsx
    • 온보딩 화면을 사용자에게 모달 형태로 제공하는 컴포넌트입니다.
    • 슬라이드 데이터를 관리하며 슬라이드 변경 상태를 slideIndex로 추적합니다.
  • OnBoardingCarousel.tsx
    • 실제 캐러셀 UI를 담당하며, 슬라이드 간 이동을 처리하고 현재 선택된 슬라이드를 모달로 전달합니다.

2. Props 구조와 데이터 흐름

OnBoardingModal → OnBoardingCarousel 전달 Props는 크게 2가지

  • slides: 슬라이드의 내용(배경 이미지, 제목, 설명)을 담고 있는 객체 배열입니다.-> 이 내용이 UX로 직접 렌더링 되겠습니다.
  • onSlideChange: 슬라이드 변경 시 캐러셀에서 모달로 현재 인덱스를 전달해주는 콜백 함수입니다.
  • 캐러셀 슬라이드가 움직일때, 모달에 있는 slide 배열의 이미지가 바뀌어야 하기에, 움직였다는 핸들러는 이미지를 지니고 있는 OnBoardingModal.tsx가 지닙니다.
const slides = [
  { background: '/IMG/slide1.png', title: '새 과목 폴더를 만들어보세요', desc: '이미 만든 폴더는 내용을 수정하거나 삭제할 수 있어요!' },
  { background: '/IMG/slide2.png', title: '새 노트 만들기로 학습 콘텐츠를 생성하고, 노트를 리스트로 관리하세요!', desc: '더 이상 필요없는 노트는 삭제할 수 있어요.' },
  // ...생략
];

const handleSlideClicked = (index: number) => {
  setSlideIndex(index);
};

<OnBoardingCarousel slides={slides} onSlideChange={handleSlideClicked} />

OnBoardingCarousel 내부 Props 처리 방식 (Slides배열, onSlideChange  이벤트 함수)

  • Carousel은 slides를 map하여 UI에 각 슬라이드를 렌더링합니다.
  • 사용자가 슬라이드를 이동할 때마다 afterChange 속성을 통해 변경된 슬라이드의 인덱스를 onSlideChange로 모달에 전달합니다.

OnBoardingCarousel Setting

캐러셀은 리액트 슬라이드 라이브러리를 가져왔기 때문에 세팅값이 매우 중요합니다.

더군다나, 모달컴포넌트와 캐러셀 자체를 분리했기에 캐러셀이 움직이고나서야 (afterChange) props로 받은 이벤트 함수처리가 됩니다.

 

그로 인해, 캐러셀이 afterChange 되고나서야, 이미지가 바뀝니다.

 

즉 캐러셀과 이미지 컴포넌트를 분리했기에 그만큼 시간적 딜레이가 생긴 다는것이니

BeforeChange 속성을 추가해야합니다.

BeforeChange 속성과 AfterChange 속성을 같이 쓰면 그런 딜레이가 사라지겠습니다.

const carouselSetting = {
    dots: true,
    customPaging: (i: number) => (
      <div className="w-1 h-1 rounded-full bg-gray-300" />
    ),
    appendDots: (dots: React.ReactNode) => (
      <ul className="flex justify-center gap-3 list-none absolute w-full top-1">
        {React.Children.map(dots, (dot) => {
          const element = dot as React.ReactElement<any>;
          const isActive =
            element.props.className &&
            element.props.className.includes('slick-active');
          return (
            <li
              key={element.key || Math.random()}
              onClick={element.props.onClick}
              className="cursor-pointer"
            >
              <div
                className={`w-3 h-3 rounded-full relative bottom-6 ${
                  isActive ? 'bg-primary' : 'bg-gray-300'
                }`}
              ></div>
            </li>
          );
        })}
      </ul>
    ),
    infinite: false,
    speed: 500,
    slidesToShow: 1,
    slidesToScroll: 1,
    arrows: true,
    prevArrow: <CustomPrevArrow />,
    nextArrow: <CustomNextArrow />,
    afterChange: (current: number) => {
      if (onSlideChange) onSlideChange(current);
    },
    beforeChange: (oldIndex: number, newIndex: number) => {
      if (onSlideChange) onSlideChange(newIndex);
    },
  };

3. 주요 기능 및 이벤트 처리 복습

  • 슬라이드 선택 상태 관리
    • OnBoardingModal slideIndex 상태를 useState로 관리하며, 이를 통해 현재 슬라이드의 배경 이미지를 동적으로 표시합니다.
  • 슬라이드 전환 이벤트
    • 사용자가 캐러셀에서 슬라이드를 전환하면 OnBoardingCarousel BeforeChange && afterChange 이벤트가 실행됩니다.
    • 이때 모달 컴포넌트의 handleSlideClicked 함수가 호출되어 상태가 업데이트되고, 모달 배경 이미지가 변경됩니다.
  • 모달 닫기 이벤트
    • 모달 외부 또는 우측 상단의 닫기 버튼 클릭 시, 상위 컴포넌트에서 받은 onClose prop이 호출되어 모달이 닫힙니다.
    • onClose는 이벤트 버블링 방지를 고려하였습니다.
<button
  className="absolute top-4 right-1 bg-transparent text-white px-3 py-1 rounded-md"
  onClick={onClose}
></button>

4. 사용자 상호작용 흐름 정리

  • 사용자는 온보딩 모달에서 좌우 캐러셀 화살표나 하단 도트를 통해 슬라이드를 전환합니다.
  • 슬라이드가 변경될 때마다 모달의 배경 이미지가 변경됩니다.
  • 사용자가 모달 외부나 닫기 버튼을 클릭하면 모달이 사라지며 온보딩이 종료됩니다.

최종적으로 요래