Language/Javascript

[styled-component] react-slick 사용하기 (how to use react-slick)

코찔이_suj 2022. 4. 13. 23:02
728x90

개요

Carousel을 만드는 과제를 하면서 이것저것 많이 보고 이 정도까지 열심히 만들어봤는데...

https://youtu.be/xXTb7uQcSLQ

생각보다 퀄리티가 많이 부족해서 쓰지 않고 react-slick이라는 라이브러리를 사용하였습니다.

이번 포스트에서는 아쉬운 맘을 담아 제가 만들던 코드를 올리고, react-slick의 설치부터 제작까지 진행하며 유용했던 정보, 꼭 알아야할 정보를 적고자 합니다.

 

본론

1. Carousel 직접 제작

1.1) 도움이 많이 된 글 모음

- Carousel 개념 잡는데 좋았던 글 (1)

 

[JavaScript] 자바스크립트로 캐러셀(Carousel) 구현하기

자바스크립트로 캐러셀 슬라이더 만들기 step-by-step

velog.io

 

- Carousel 개념 잡는데 좋았던 글 (2)

 

carousel practice

...

codepen.io

- Transition 개념 익히는데 많이 도움이 되었던 글

 

CSS 트랜지션 사용하기 - CSS: Cascading Style Sheets | MDN

CSS 트랜지션은 CSS 속성을 변경할 때 애니메이션 속도를 조절하는 방법을 제공합니다. 속성 변경이 즉시 영향을 미치게 하는 대신, 그 속성의 변화가 일정 기간에 걸쳐 일어나도록 할 수 있습니

developer.mozilla.org

- Web관련 헷갈렸던 개념을 바로잡기 좋은 사이트

 

W3Schools Free Online Web Tutorials

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

- Event에 관한 개념을 잡는데 도움된 글

 

[React] Drag and Drop 기능 구현하기

라이브러리 없이 Drag and Drop🖱

velog.io

 

1.2) 내가 만든 Carousel 코드

더보기

transitionX와 반응형에 맞춰 size별로 나눠 width와 height를 바꾸려다보니 일이 커져서...

그냥 코드만 올려둡니다...! 유튜브 영상처럼 작동은 해요! 다만 auto를 할때 슬라이드를 하면 속도가 이상해진다거나 width와 height를 작은 사이즈로 했을때 transitionX의 값이 올바르지 않아서 시간 관계상 다음 기회로 미뤄두려합니다.

// index.stories.tsx (스토리북에서 보기 위해 만든 예시)
export const DefaultCarousel = (args: ComponentStory<typeof Carousel>) => {
  const imgLists = [
    {
      idx: 0,
      image: '/imgs/Carousel.png',
      alt: 'happy carousel',
      onClick: () => {
        alert('Carousel');
      },
    },
    {
      idx: 1,
      image: '/imgs/Carousel2.png',
      alt: 'sad carousel',
      onClick: () => {
        alert('Carousel2');
      },
    },
    {
      idx: 2,
      image: '/imgs/Carousel3.png',
      alt: 'haha carousel',
      onClick: () => {
        alert('Carousel3');
      },
    },
    {
      idx: 3,
      image: '/imgs/Carousel3.png',
      alt: 'haha caroul',
      onClick: () => {
        alert('Carousel4');
      },
    },
    {
      idx: 4,
      image: '/imgs/Carousel3.png',
      alt: 'ha carousel',
      onClick: () => {
        alert('Carousel5');
      },
    },
  ];
  return (
    <GlobalThemeProvider theme={theme}>
      <Carousel device={'md'} imgLists={imgLists} auto={true} {...args} />
    </GlobalThemeProvider>
  );
};
// index.tsx (실제 로직이 있는곳.)
import React, { useEffect } from 'react';
import { StyledCarouselItem, StyledCarousel, SCarouselItemProps } from './style';

export interface CarouselItemProps extends SCarouselItemProps {
  src: string;
  alt?: string;
  onClick?: (e: React.MouseEvent) => void;
}

export const CarouselItem = ({ device, src, onClick, alt }: CarouselItemProps) => {
  return <StyledCarouselItem device={device} src={src} onClick={onClick} alt={alt} />;
};

// imgitem의 타입선언 (Carousel안에서 img를 담는 CarouselItem이 필요로할거...)
export type ImgItem = {
  idx: number;
  image: string;
  alt: string;
  onClick: (e: React.MouseEvent) => void;
};

// 전체 Carousel용 props
export interface CarouselProps {
  auto?: boolean;
  imgLists: ImgItem[];
}

const Carousel = ({ device, auto, imgLists }: CarouselProps & SCarouselItemProps) => {
  // Variables
  const size = imgLists.length;
  const [currentIdx, setCurrentIdx] = React.useState(size / 2);
  const transRatio = 100 / size;
  const [transX, setTransX] = React.useState(size % 2 === 0 ? -transRatio / 2 : transRatio);
  // 페이지 전환
  const nextPage = () => {
    let move = transX - transRatio;
    if (move < -50) move += 100;
    setTransX(move);
    setCurrentIdx(currentIdx + 1);
  };
  const prevPage = () => {
    let move = transX + transRatio;
    if (move > 50) move += -100;
    setTransX(move);
    setCurrentIdx(currentIdx - 1);
  };
  const ScrollHandler = (e: React.WheelEvent) => {
    if (e.deltaY >= 400) nextPage();
    else if (e.deltaY <= -400) prevPage();
  };
  // Item 생성 함수
  const createItem = ({ idx, image, alt, onClick }: ImgItem) => {
    return (
      <StyledCarouselItem device={device} key={idx} src={image} onClick={onClick} onWheel={ScrollHandler} alt={alt} />
    );
  };
  // 자동재생 기능
  useEffect(() => {
    if (!auto) return;
    setTimeout(() => {
      nextPage();
    }, 3000);
  });
  // Carousel로 반환될 내용
  return (
    <React.Fragment>
      <StyledCarousel translateX={transX} hidden>
        {imgLists.map(imgList => createItem(imgList))}
      </StyledCarousel>
    </React.Fragment>
  );
};

export default Carousel;
import styled from '@emotion/styled';
import theme from '../../../styles/theme';

const carouselTheme = theme.style.carousel;
export interface SCarouselProps {
  translateX: number;
}

const changePage = ({ translateX }: SCarouselProps) => {
  return `
    transform: translateX(${translateX}%);
  `;
};

export const StyledCarousel = styled.div`
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: stretch;
  transition-duration: 400ms;
  ${changePage};
`;

export interface SCarouselItemProps {
  device: 'sm' | 'md' | 'lg';
}

const setSize = ({ device }: SCarouselItemProps) => {
  return `
    width: ${carouselTheme.width[device]};
    height: ${carouselTheme.height[device]};
  `;
};
export const StyledCarouselItem = styled.img`
  margin: 0 1rem;
  cursor: pointer;
  flex-basis: 50vw;
  ${setSize};
`;

아마 99%의 확률로 저 코드는 별로일거예요... 그냥 지금 이 피곤하고 머리안돌아가는 상태로도 알수있습니다... 그냥 아래 링크들에 가서 좋은 정보 많이 가져가셨으면합니다...

 

 

 

2. Carousel Library 사용

1) 유용한 Carousel Library 후보들

- Slick http://kenwheeler.github.io/slick/
- Swiper https://swiperjs.com/
- Flickity https://flickity.metafizzy.co/
- Keen-Slider - 부드러운 HTML 터치 슬라이더 : https://news.hada.io/topic?id=2299

 

2)  react-slick

 

slick - the last carousel you'll ever need

slick is a responsive carousel jQuery plugin that supports multiple breakpoints, CSS3 transitions, touch events/swiping & much more!

kenwheeler.github.io

React-slick의 많은 사용량과 autoplay제공, 편리한 사용방법, 다양한 예시를 보고 사용하기로 결정했습니다.

사용량이 많다는 건 그만큼 자료가 많기에 비교적 난이도가 낮아진다는 점. 이를 이용해 빠르게 설치를 해봤습니다.

 

3) react-slick 설치 방법 

저는 yarn berry 사용 + typescript와 react를 사용하는 프로젝트였기 때문에 아래와 같이 입력해줬습니다.

$ yarn add react-slick -D
$ yarn add slick-carousel -D
$ yarn add @types/react-slick -D

 

4) react-slick의 style 설정 정리된 글

블로그 미리보기

slick의 공식 페이지보다 더 이해하기 편하게 settings의 type과 event, method를 설명해준 글입니다! (다음에 carousel을 다시한번 구현해야할 상황이 온다면 해당 글은 꼭 재방문할 것 같네요!!)

https://jmjmjm.tistory.com/30

 

[PlugIn] slick slider

slick slick slick_github slick 예제 #Settings settings Type Default Description accessibility boolean true 탭 및 화살표 키를 사용한다. autoplay: true일 경우, 슬라이드 변경 후 브라우저 포커스를 현재..

jmjmjm.tistory.com

팀원 분들이 이해하시기 좋도록 PR올리며 적어둔 제가 사용한 settings 값들입니다. 참고하시면 좋을 것 같아요 :)

const settings = {
// 무한으로 돌것인가 (false면 마지막 페이지에 갔을때 첫페이지로 전환 X)
  infinite: true, 
// 전환되는 속도 (transition과 유사)
  speed: 1000, 
// 한 Slide안에서 보여줄 사진의 개수
  slidesToShow: 1, 
// 한번의 Scroll로 넘어갈 슬라이드의 개수
  slidesToScroll: 1, 
// 현재 슬라이드를 중앙에 둘지 여부
  centerMode: true, 
 // 현재 슬라이드 좌우로 줄 패딩값 ( +면 양옆의 슬라이드가 보임, - 면 양옆의 사진이 안보이도록 함)
  centerPadding: '-3px',
// 자동재생여부
  autoplay: true, 
 // 자동재생 속도
  autoplaySpeed: 2500,
// 아래 점으로 몇번째 슬라이드인지 보여주는 점의 가시 여부
  dots: true, 
// 반응형으로 처리할 셋팅값의 요소
  responsive: [ 
    {
      breakpoint: 600, // 600px이하가 되면 
      settings: {
        dots: false, // 점을 안보이게 하겠다.
      },
    },
  ],
};

 

 

5) slick-carousel의 css 

해당 부분을 import해주지 않으면 react-slick을 만들었을때 이게 뭐지????? 싶을겁니다(경험담). 꼭 import해주세요!!

import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

 

slick-carousel에는 여러 클래스가 있습니다. 제 경우에는 블로그를 돌아다니다 그냥 node_modules를 탐색해 클래스 설정 내용을 프로젝트에 맞춰 수정해봤어요. node_modules/slick-carousel/slick/slick.css와 node_modules/slick-carousel/slick/slick-theme.css을 참고하시면 carousel을 만들며 사용된 요소들의 css값을 확인하실 수 있습니다!

제가 설정한 slick의 클래스명은 slick-track, slick-list, slick-slide, slick-dots였습니다. 이런 구조로 보이는거라 생각하고 값을 설정하였습니다.

 

 

6) carousel 속 Img의 크기 설정 (object-fit)

Carousel의 요구사항은 wanted와 비슷하게 작동하되 서비스의 특성에 맞춰 진행하는 것이었습니다. 첫번째 사진처럼 인물이 중앙에 있고 웹 페이지의 크기에 맞춰 중앙 부분이 잘려나오도록 만들어야 했습니다.

desktop 기준 화면
mobile 기준 화면

wanted처럼 carousel의 반응형을 구현하고자 600px이하로 내려가면 object-fit에 none을 줘 사진이 중앙기준으로 크기에 맞춰 설정되도록 변경하였고, 해당 글이 많은 도움이 되었습니다.

https://nykim.work/86

 

[CSS] 이미지 사이즈 맞추기 (object-fit, absolute, background)

프롤로그 컨테이너의 크기는 고정되어 있는데, 해당 컨테이너 안에 들어갈 이미지의 크기는 다양한 경우가 있습니다. 사용자가 이미지를 등록하는 경우 또는 마케팅 팀이 아무 이미지나 넣는

nykim.work

 

6) Slick과 Styled Component를 같이 쓰고자 참고한 사이트

정리가 잘되어있어서 많이 참고했어요 

https://poew.tistory.com/707

 

React Slick 사용법

🌳 React Slick 리액트 프로젝트에서 carousel을 쉽게 구현하도록 도와주는 모듈 👉🏻 React Slick 홈페이지 👉🏻 슬라이드 종류 1. 다음과 같은 명령어를 터미널에 입력해서 설치해준다. $ npm install

poew.tistory.com

 

 

 

마무리

결과물!

https://youtu.be/h0Vqc0CTwGk