Programming/Styles

[React-slick] Carousel 만들기 (+ Typescript, Tailwind, styled-components)

Jiwoo 2023. 3. 31. 12:21

이틀의 똥꼬쇼 기록

🤔 문제 상황

현재 tailwind와 styled-components가 결합된 tailwind-styled-components를
사용하고 있는데 이미지 슬라이더가 필요했다.
찾아보니 carousel이 정식 명칭이었고 찾아보니 사용할 수 있는 소스가 많았다.
처음에는 간단할 줄 알았는데 구현하는데 거의 이틀이 걸렸다.
세 가지 프레임워크를 사용해봤는데 결론적으로 react-slick을 사용했다.

실패 기록

  1. flowbite
    이미 navbar를 flowbite로 구현했던지라 그 안에서 해결하고 싶었다.
    그래서 flowbite에도 좋은 carousel이 있길래 사용하려고 했는데... 실패했다.
    거의 하루를 붙잡고 있었는데 공식 문서에 나와있는대로 복붙을 해도 안됐다.
    이미지를 싸고 있는 div를 벗기니까 이미지가 보이긴 했는데, 만질수록 오작동이 많아져서
    결국 버리고 다른 프레임 워크를 찾기 시작했다.
    react-flowbite는 아직 완전하지 않고 typescript와의 호환도 그다지 좋지 않다.
    tailwind의 ui를 찾으면 가장 많이 나오는 프레임워크인데... 비추이다.
  2. tailwind-element
    import부터 문제가 계속 발생했다...
    안 그래도 flowbite 때문에 지쳐있던터라 조금 만져보다가
    flowbite와 다를 바 없을 것 같아서 아예 라이브러리를 찾기 시작했다.

✅ React-slick 뼈대 코드

너무 간단해서 처음에 놀랐다.
돌아가지말고 처음부터 가장 많이 쓰이는 라이브러리를 썼어야 했다...ㅎㅎ

import React, { Component } from "react";
import Slider from "react-slick";

function SliderWrapper {
    const settings = { // 세팅할 요소들을 설정하고
      dots: true,
      infinite: true,
      speed: 500,
      slidesToShow: 1,
      slidesToScroll: 1
    };
    return ( // 넣어주기만 하면 끝임
      <div>
        <Slider {...settings}>
          <img src="#" />
        </Slider>
      </div>
    );
  }

🎨 커스텀 과정

몇 가지 커스텀을 해줬다.
라이브러리의 단점이 있다면 커스텀하기 힘들다는 것인데,
나는 일회성으로 쓸 것이기 때문에 상관없지만
현업에서는 직접 구현하는 것이 나을 것 같다.

초기 에러 처리

처음 넣었을 때 화면이 엄청나게 커지면서
안에 내용물이 날아가는 에러가 발생했다.
slider나 이를 감싸는 div에 width 값을 적절하게 부여하니까 사라졌는데
아직도 왜 그런지는 알 수 없다.

이미지는 children으로 받아서 넣어주기

재사용이 가능해야 하니까 이미지를 children으로 받아서 넣었다.
나중에는 children으로 받을 다른 태그가 생겨서
이미지 src 내역을 JSON.stringify(배열)로 전달한 다음,
컴포넌트에서 JSON.parse(받은 문자열 배열)로 처리해서 사용했다.

tailwind-styled-components로 스타일 변경하려면?

같은 tsx파일 안에서 tailwind-styled-components를 이용해서 커스텀 하려면
tailwind.config.js파일을 통해 css 적용 1순위로 올려야 한다.
module.exports 객체 안에 important: true를 넣자.
(클래스를 통해 변경해야 하는 것은 그냥 global.css 안에 적었다.)

next, pre 버튼 바꾸기

배경이 밝은 색인데 버튼도 흰색이라 잘 안 보여서 바꾸려고
css를 만져봤는데 아이콘이 아니라 svg 이미지파일이라서 아예 바꿔야했다.
그래서 아이콘을 넣었는데 아예 안보이고 이미지를 넣으니까 보였다.
버튼을 바꿀 때는 이미지 파일로 넣으시길.,,

  • flation 이 사이트가 아이콘 색상 변경해서 저장할 수 있어서 추천한다.
    (svg은 유료이고 png는 무료다)
// global.css
/* 기존 슬라이더 화살표 없애기 */
.slick-prev::before,
.slick-next::before {
opacity: 0;
display: none;
}
.slick-slide div {
cursor: pointer;
}

이미지 x축 가운데 정렬

이미지의 크기가 다를 경우, 가장 큰 크기를 기준으로 디스플레이가 맞춰진다.
그래서 크기가 작은 사진인 경우 위쪽으로 올라가서 보인다는 것이다.
이를 해결하기 위해서는 slick-track 엘리먼트를 가운데 정렬해야 한다.

// global.css
.slick-track {
  display: flex !important;
  align-items: center;
}

💥 최종 코드

import React, { ReactNode } from "react";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import tw from "tailwind-styled-components";

const SliderWrapper = tw.div`
  w-[100%] mb-5
`;
// 여기서 w-[18rem]같이 너비를 지정해주지 않으면 에러가 난다
const StyledSlider = tw(Slider)`
  mx-[auto] w-[18rem]
`;
// next, pre 버튼 커스텀 (크기 바꾸고 이동시킴)
const NextArrow = tw.img`
  h-[1.5rem] w-[1.5rem] right-[-2rem] 
`;
const PreArrow = tw.img`
  h-[1.5rem] w-[1.5rem] left-[-2rem]
`;

interface CarouselProps {
  children: ReactNode;
}

const Carousel = ({ children }: CarouselProps) => {
  const settings = {
    dots: true,
    infinite: true,
    speed: 500,
    slidesToShow: 1,
    slidesToScroll: 1,
    centerPadding: "50px",
    nextArrow: <NextArrow src="/chevron-right.png" />,
    prevArrow: <PreArrow src="/chevron-left.png" />,
  };

  return (
    <SliderWrapper>
      <StyledSlider {...settings} className="relative shadow-lg">
        {children}
      </StyledSlider>
    </SliderWrapper>
  );
};

export default Carousel;


참고

ryurim.tistory.com