API, 라이브러리 없이 이미지 슬라이드 구현

노도·2022년 4월 5일
4

Project. muzimakzi

목록 보기
2/5
post-thumbnail

먼저,

이 글을 올릴 수 있었던 계기에 대해 가볍게 서술해보면 프로젝트에서 내가 맡은 부분중에 랜딩 페이지가 존재하였고 그 안에 버튼, 자동슬라이드가 같이 구현 되도록 기획을 했다.


결코 어려운 부분은 없었다. 그래서 가볍게 생각하고 있었는데 ..
시작하기도 전에 blocker issue 등장


이번 프로젝트는

라이브러리 및 custom hook 사용 금지.. 
뭐..?

서두는 여기서 접고, 본론으로 들어가보자



라이브러리, 커스텀훅을 사용하지 않고 슬라이드 구현


1. 버튼 슬라이드

구현하는 기능에 버튼, 자동 슬라이드가 같이 적용되고 있어 난이도를 고려하여 우선적으로 버튼 슬라이드를 구현.

가장 먼저 최상위 컴포넌트에서 상태
즉, state 를 관리하기 위하여 랜딩 페이지에서 useState 를 이용하여 2개의 state 값을 생성하였고 생성된 상태 값은 props 로 전달하여 슬라이드 구현 시작.

  1. useEffect Hook 과 fetch 함수를 이용하여 이미지 API 및 Mock data 를 호출.
// 슬라이드 컴포넌트로 props 전달 

const Landing = () => {
  const [imgList, setImgList] = useState({});

  useEffect(() => {
    fetch(' ip, mock data 경로 ')
      .then(res => res.json())
      .then(data => {
        setImgList(data);
      });
  }, [setImgList]);

  return (
   ...
          <Slider swiperList={imgList.landings} />
   ...
  1. swiperData 컴포넌트를 생성하여 map 메서드를 이용해 컴포넌트 재사용하여 슬라이드가 진행 될 이미지 구현.

  2. 이미지를 길게 펼치고 나타나는 이미지를 제외한 부분은 overflow-x: hidden을 주어 보이지 않게 스타일 지정.

  3. 이미지가 나열되어있는 태그부분에 style 의 transform 속성을 이용하여 translateX 값 할당.

이때 translateX 에 들어가는 값은
- ( 이미지 width 값 ) * ( 이미지배열의 index state 값 ) px 으로 입력하여 state 값이 변경되면 그 넓이만큼 이미지가 이동하여 슬라이드, 좌측으로 이동해야하기때문에 - 를 할당, + 로 할당 한다면 우측으로 이동.

  1. 이벤트 함수에 조건문을 활용하여 배열의 index state 와 배열의 length 가 같다면 배열의 첫 index로 이동, 반대의 경우 또한 구현.

const Slider = ({ swiperList }) => {
  const [currentIndex, setCurrentIndex] = useState(0);

  function handleSlide(currentIndex) {
    if (currentIndex === swiperList.length) {
      currentIndex = 0;
    } else if (currentIndex < 0) {
      currentIndex = swiperList.length - 1;
    }
    setCurrentIndex(currentIndex);
  }

  function handleSwipe(direction) {
    handleSlide(currentIndex + direction);
  }
  
  ...
  1. 버튼을 컴포넌트화 하여 재사용을 하여 두개의 버튼에 서로 다른 이벤트 값을 props 로 전달하여 각 버튼 클릭 시 좌우 이동 구현.

  2. 버튼별로 direction의 값을 다르게 설정하여 props 로 전달, 전달 받은 값에 따라 같은 컴포넌트에서 style 속성을 나누어 할당.

  return (
        ...
        <SliderButton direction="Prev" onClick={() => handleSwipe(-1)} />
        <SliderButton direction="Next" onClick={() => handleSwipe(1)} />
        ...
    
    
    // 아래는 버튼 컴포넌트 내용

import './SliderButton.scss';

export default function SlideButton({ direction, onClick }) {
  return <button onClick={onClick} className={`btn${direction}`} />;
}
  1. 버튼의 위치를 position : absolute 속성과 z-index 속성을 주어 최상위에 설정한 위치에 고정되도록 구현.
// SliderButton style 값

@mixin btn {
  z-index: 100;
}

// 각각 전달된 direction 값에 따라 style 값 변경 

.btnPrev {
  position: absolute;
  left: 0%;
  top: 45%;
  @include btn;
}

.btnNext {
  position: absolute;
  right: 0;
  top: 45%;
  @include btn;
}
  1. 마지막으로 transition-duration 속성을 주어 이미지가 슬라이드되는 시간을 늘려 부드럽게 슬라이드 되는 것을 구현.

2. 자동 슬라이드

로직이 점점 길이가 길어져 Slider 컴포넌트를 생성하여 슬라이드 부분 구현.

  1. 버튼 슬라이드와 같은 컴포넌트에 구현하기 때문에 따로 API 또는 Mock data 를 호출하지 않고 유지.

  2. 이미지가 슬라이드 되는 부분또한 같은 태그의 style을 사용하기에 추가 작성하지 않고 유지.

  3. 슬라이드 이미지 또한 버튼 슬라이드를 진행하며 map 메서드를 사용해 나열해주었기때문에 유지.

  4. useEffect 를 이용하여 랜딩페이지가 렌더링 될 때 settimeout 메서드 실행.

  useEffect(() => {
    const timeoutId = setTimeout(
      () =>
        setCurrentIndex(currentValue => {
          if (currentValue < swiperList.length - 1) {
            return setCurrentIndex(currentIndex + 1);
          } else {
            return setCurrentIndex(0);
          }
        }),
      2500
    );
    return () => clearTimeout(timeoutId);
  });
  1. settimeout 메서드 이용하여 이미지배열의 index state 값을 변경, 이때 조건문에 따라 이미지가 슬라이드 되는 것을 구현.

  2. 이미지배열의 index state 값이 이미지배열의 ( length -1 ) 값보다 작다면 state 값을 1을 추가하여 작성된 슬라이드 식에 대입 후, 작지 않다면 state 값을 0 으로 변경하여 슬라이드 식에 대입.

  3. 슬라이드가 멈추었다가 이동하는 것을 위하여 2.5 초를 할당.

  4. return 값에 cleartimeout 을 할당하여 슬라이드가 반복적으로 실행되는 것을 구현.


성장 포인트

먼저, 현업에서 슬라이드는 라이브러리를 사용한다는 이야기를 들었을때 나는 이 로직 자체가 상당히 꼬여있거나 귀찮기 때문에 직접 만들지 않고 가져다쓸 것이라고 생각해보았다.

자동 슬라이드와 비슷한 것을 떠올려보니 타이머였다.

타이머는 설정한 시간에 따라 나타냈고, 내가 원하는 자동 슬라이드 또한 설정한 시간에 따라 멈추었다가 이동하는 것과 비슷하다고 생각되어 타이머 제작하는 로직을 찾아보았고,

그 중심에는 setTimeout 과 setInterval 이 있었고 어떤것을 사용해야할지 찾아보았다.

setTimeout : 일정 시간이 지난 후에 함수를 실행
setInterval : 일정 시간 간격을 두고 함수를 실행

이렇게 가볍게 정리를 하고보니 setTimeout을 이용하여 이미지 슬라이드를 구현해야겠다고 생각했다.
다만, setTimeout 을 사용하기위해 여러가지 글과 영상을 찾아보았지만 setInterval 과 setTimeout 헷갈렸다.
그래서 아주 간단한 타이머를 만들며 이해했다.

하지만 나만의 로직을 그려서 구현하는 것이 정말 어려웠다. 

' 자동 슬라이드 ' 라는 하나의 목표만 바라보고 구현을 완성 시키려고 하다보니 너무나도 어려웠다.

그래서 ' 버튼 슬라이드 ' 또한 구현해야하기에 난이도가 조금 낮은 이것부터 구현해보자 하며 뼈대를 만들고 천천히 살을 붙이며 노력하였고 결국 나만의 로직으로 자동 슬라이드를 구현하였다.

필요한 부분을 단계를 밟아가며 구현하다보니 자동 슬라이드가 구현이 되었고,

이때 애자일하게 생각을 하는 법을 알 수 있었던 것 같다.

자동 슬라이드를 구현 하는 것을 절대 어려운 일은 아니였지만 그 어디에도 라이브러리, 커스텀 훅을 사용하지 않고 자동슬라이드를 구현한 글은 없었다.

< 응애.. >

아직 성장중인 나에게는 높은 난이도 였지만 금방 설렘으로 다가왔고, 결국 완성했다 ..ㅎ

물론 누군가에게는 이게 뭐가 어려워? 라고 생각할 수 있지만
나에게는 많은 것을 느낄 수 있었던 시간이었다 ^.^


자.. 마지막으로 ~

< 개똥이는 오늘도 성장한다 ~ ! >
profile
유연한 사고로 빠르게 습득하기.

5개의 댓글

comment-user-thumbnail
2022년 4월 9일

개똥이 화이팅!!! 고생 많으셨어요 규현님~!

1개의 답글
comment-user-thumbnail
2022년 4월 9일

규마이...

1개의 답글
comment-user-thumbnail
2022년 9월 3일

currentIndex값으로 map 부분을 조절하신 건가요??

답글 달기