개발/프로젝트

Swiper.js 라이브러리를 사용해서 슬라이더 구현하기 (Next.js + React)

xuwon 2025. 2. 13. 18:09

Swiper.js 라이브러리를 사용해서 반응형 슬라이더를 구현해 보았다.
Swiper는 브라우저에서만 동작하는 라이브러리라서,
'use client'를 선언하여 클라이언트 컴포넌트로 지정해야 사용이 가능했다.

// Swipers.tsx

"use client";

import React, { ReactNode } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import { Pagination, Navigation, Autoplay } from "swiper/modules";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";

interface SwipersProps {
  children: ReactNode;
}

const Swipers: React.FC<SwipersProps> = ({ children }) => {
  return (
    <div className="relative mx-auto w-full overflow-visible">
      <Swiper
        className="relative flex h-[300px] overflow-visible md:h-[430px]"
        slidesPerView={3}
        breakpoints={{
          0: { slidesPerView: 1 },
          540: { slidesPerView: 2 },
          769: { slidesPerView: 3 },
        }}
        modules={[Navigation, Pagination, Autoplay]}
        navigation={true}
        pagination={{ clickable: true, type: "bullets" }}
        autoplay={{ delay: 3000, disableOnInteraction: true }}
      >
        {React.Children.map(children, (child, index) => (
          <SwiperSlide key={index}>
            <div className="flex justify-center">{child}</div>
          </SwiperSlide>
        ))}
      </Swiper>
    </div>
  );
};

export default Swipers;

공통 컴포넌트로 분리를 해주고, props로 슬라이더 안에 들어갈 컴포넌트를 지정하는 형태로 만들었다.

 

interface SwipersProps {
  children: ReactNode;
}

SwiperProps 타입을 정의하여 childrenReactNode (모든 React 요소) 타입으로 받게 했다. (TypeScript)

 


 

const Swipers: React.FC<SwipersProps> = ({ children }) => {

React.FCReact 함수형 컴포넌트 타입을 정의하는 TypeScript의 유틸리티 타입이다.


React.FC<props>

- Props 타입을 자동으로 적용
- children이 기본적으로 포함! (별도로 선언하지 않아도 children 사용 가능)
- React 함수형 컴포넌트임을 명확히 표시

 

React.FC를 사용하지 않으려면

const Swipers = ({ children }: SwipersProps) => { ... };

요렇게 사용하면 된다.

 


 

<Swiper
  className="relative flex h-[300px] overflow-visible md:h-[430px]"
  slidesPerView={3} // 한 번에 3개 슬라이드 표시
  breakpoints={{ // 반응형 슬라이드 개수 조절
    0: { slidesPerView: 1 },
    540: { slidesPerView: 2 },
    769: { slidesPerView: 3 },
  }}
  modules={[Navigation, Pagination, Autoplay]} // 모듈 추가
  navigation={true} // 기본 네비게이션 버튼
  pagination={{ clickable: true, type: "bullets" }} // 기본 페이지네이션 
  autoplay={{ delay: 3000, disableOnInteraction: true }} 
  // 3초마다 자동 슬라이드, 사용자가 조작하면 멈춤 
>

그냥 Swiper에서 제공해주는 옵션들을 그대로 갖다 사용하면 된다.

modules={[Navigation, Pagination, Autoplay]}

modules를 꼭 포함시켜줘야 했다. 포함 안 하면 작동을 안 했음.

import { Pagination, Navigation, Autoplay } from "swiper/modules";

import도 필수 . . .


이것 말고도 정말 많은 옵션이 있다.

https://swiperjs.com/

 

Swiper - The Most Modern Mobile Touch Slider

Swiper is the most modern free mobile touch slider with hardware accelerated transitions and amazing native behavior.

swiperjs.com

↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑

여기서 확인 가능!

 

/* globals.css */

/* 기본 Swiper 네비게이션 버튼 커스텀 */
.swiper-button-prev,
.swiper-button-next {
  position: fixed !important;
  transform: translateY(-50%);
  z-index: 10 !important;
  top: 70% !important;
  color: #efc071 !important;
}

.swiper-button-prev {
  left: -50px !important;
}

.swiper-button-next {
  right: -50px !important;
}

.swiper-button-prev:after,
.swiper-button-next:after {
  font-size: 20px !important;
  font-weight: 600 !important;
}

.swiper-pagination-bullet {
  background-color: gray !important;
}

.swiper-pagination-bullet-active {
  background-color: #efc071 !important;
}

@media (max-width: 540px) {
  .swiper-button-prev {
    left: 30px !important;
  }

  .swiper-button-next {
    right: 30px !important;
  }
}

@media (max-width: 768px) {
  .swiper-pagination-bullet {
    width: 6px !important;
    height: 6px !important;
  }
}

@media (min-width: 769px) {
  .swiper-button-prev {
    left: -30px !important;
  }

  .swiper-button-next {
    right: -30px !important;
  }

  .swiper-button-prev:after,
  .swiper-button-next:after {
    font-size: 35px !important;
  }
}

.swiper-button-prev:hover,
.swiper-button-next:hover {
  color: #ffd795 !important;
}

.swiper-button-disabled {
  opacity: 0.3 !important;
}

그리고 나는 Pagination 색깔이랑 Navigation 버튼 색깔이 맘에 안 들어서 커스텀도 해주었다!

클래스명은 기본으로 제공되기 때문에, 따로 지정해줄 필요는 없다.

 


원래는 기본 Navigation 버튼이 아니라 완전히 커스텀을 하고 싶었지만,
연결이 안되는 상황이 발생했다. ㅠㅠ

그리고 또 반응형으로 슬라이드 개수를 조절했는데, 메인 페이지를 서버 컴포넌트로 해놔서 그런지,
새로고침을 해야만 반응형이 적용됐다.

근데 이거는 뭐 상관 없을 것 같기도...
하지만 MVP 기능이 다 끝나고 나면 한 번 제대로 알아보려고 한다.