리액트 라이브러리 Swiper

JoonPark·2023년 12월 15일
0
post-thumbnail

서론

난 스와이퍼를 아주 싫어한다. 아니, 싫어했었다.
처음 코딩을 배울때 스와이퍼의 역할을 하는 슬라이드 이미지를 바닐라 JS로 개발하는 방법을 배워서 그런 것 같다.
'왜 이렇게 맘대로 커스터마이징 하기가 까다로워? 에이 그냥 슬라이드 필요하면 직접 개발하고 말지 뭐..'
처음에 이렇게 생각 했다보니 당연히 첫 인상이 나쁠 수 밖에 없다.
하지만 결국 '향후 쓰지 않더라도 지금 한번 써보자' 마인드로 개인 포폴 사이트를 만들면서 도전하게 되었다.

다룰 줄 알면서 사용하지 않는 것과, 다룰줄 몰라서 못 쓰는 것은 다르다.

본론

기능 요구 사항

  • Swiper 페이지는 height 100%로 부모 요소를 꽉 채워야 한다.
  • Pagenation은 NavBar의 버튼을 클릭하는 방식으로 작동한다.
  • NavBar의 버튼은 'Selected'와 'Default' 스타일로 나뉘며 선택된 페이지만 'Selected' 스타일이 적용되어야 한다.
  • 마우스 스크롤에 슬라이드가 반응해야하며, 이에 따라 NavBar 버튼 또한 현재 슬라이드가 선택되었다는 표시가 되어야 한다.

아니 스타일링을 CSS로 하라구요? 싫은데 😭

처음 코딩을 배울때는 아는게 없어서 싫어했다면, 지금 공식문서를 방문하고 정떨어진 부분은 CSS문서로 복잡한 선택자를 사용해서 스타일링을 해야한다는 점이다.
내가 요즘 TailwindCSS의 편리함에 푹 빠져 '가능한 CSS 문서를 만들지 않는다' 라는 쪽으로 코딩 스타일이 굳어졌기 때문에, Swiper를 위한 CSS를 따로 할당하고 싶지 않았다.

  • 왜 그런지는 모르겠지만, 이젠 아래와 같은 어지러운 클래스명과 속성들을 보면 머리가 아프다.
.swiper-pagination-bullet {
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  font-size: 12px;
  color: #000;
  opacity: 1;
  background: rgba(0, 0, 0, 0.2);
}

.swiper-pagination-bullet-active {
  color: #fff;
  background: #007aff;
}

일단 CSS 스타일링은 최소화

운 좋게도 기능 요구 사항에 따라 많은 부분을 CSS 문서로 직접 스타일링 할 필요는 없었다.
다만 Swiper와 SwiperSlide 내에 적절한 스타일을 부여해줘야 했다.

<Swiper style={{ height: "100%" }}>
  <SwiperSlide key={index}>
    <section className="w-full min-h-full p-10">
      it's {section} section.
    </section>
  </SwiperSlide>
</Swiper>

swiper-pagination-bullet 클래스를 직접 스타일링 하기 싫다면?

의외로 Swiper에는 많은 기능들을 Props와 함수로 제공한다.
그러니까, 다른 컴포넌트의 어떤 버튼이 눌러졌을 때 slideTo 함수로 특정 슬라이드로 가게 명령할 수도 있고, 그걸 onSwiper Prop으로 받아 슬라이드를 움직이게 할 수 있다.
onSlideChange Prop으로 슬라이드가 변경될 때마다 activeIndex를 pageIndex로 바꿔주면, 다른 컴포넌트의 버튼에게도 영향을 줄 수 있다.
이정도면 글로벌 상태관리 라이브러리와 함께 사용했을 때 충분히 기능 요구사항을 구현할 수 있음을 확인했다.

구현된 실제 코드

  • 아래 코드는 Swiper, Zustand 라이브러리를 사용했다.
  • import문은 생략 했다.
export default function SwiperPage() {
  SwiperCore.use([Pagination, Mousewheel, A11y]);
  const swiperRef = useRef<SwiperRef>(null);
  const sections = ["first", "second", "third", "fourth", "fifth"];
  const setSwiper = usePageStore((state) => state.setSwiper);
  const setPageIndex = usePageStore((state) => state.setPageIndex);

  return (
    <main className="w-full h-full max-w-[1200px] border overflow-hidden">
      <Swiper
        onSwiper={setSwiper}
        onSlideChange={(swiper) => setPageIndex(swiper.activeIndex)}
        ref={swiperRef}
        style={{ height: "100%" }}
        direction="vertical"
        slidesPerView={1}
        mousewheel={true}
        loop={true}
        className="mySwiper">
        {sections.map((section, index) => (
          <SwiperSlide key={index}>
            <section className="w-full min-h-full p-10">
              it's {section} section.
            </section>
          </SwiperSlide>
        ))}
      </Swiper>
    </main>
  );
}

추가로 필요한 사항

  • 현재 loop={true}로 되어있으므로 마지막 슬라이드에서 첫 슬라이드로 넘어가야하는데, 이에 따른 버튼 스타일은 적용되지 않고 있는 상황이다. 다음에 해결해보자.

결론

'무지의 공포'라는 말이 있다. 잘 모르는 것에 대해서 무의식적으로 공포감을 느끼고 활용하길 꺼려한다는 뜻이다.
마냥 내 입맛대로 커스터마이징이 안된다고 싫어했었는데, 일단 사용해보니 생각보다 편했고, 앞으로도 사용해 볼 용의가 있다.
많은 라이브러리들을 접하면서 느끼는거지만 늘 결론은 이렇게 귀결된다.

내가 이 기능을 직접 만들었어도 고도화 하다보면 이것처럼 되었겠구나.

profile
FE Developer

0개의 댓글