프로젝트를 진행하면서 캐러셀을 만들 일이 생겼다. 수 많은 리액트 라이브러리가 있지만, 공부를 하고 한 번도 만들어 본적 없는 것을 라이브러리로 만드는게 내키지 않았다.
그래서 순수하게 나만의 carousel을 만들기로 했다.
사실 캐러셀은 기본 구조만 알면 만드는 일은 어렵지 않다. 캐러셀을 구성하는 수 많은 방법 중에 나는 가장 기본적인 방법을 적용했다.
이것만 알면 된다.
4가지를 코드로 구현하면 정말 간단하게 나온다.
<OverFlow>
<SlideContainer>
{infiniteElements.map((e, index) => (
<SlideInner key={index}>
<SlideItem>
<img src={e} alt="사진" />
</SlideItem>
</SlideInner>
))}
</SlideContainer>
</OverFlow>
스타일 코드는 더 간단한다.
import styled from "styled-components";
export const OverFlow = styled.div`
overflow: hidden;
`;
export const SlideContainer = styled.div`
width: ${(props) => props.width};
transform: ${(props) => props.transform};
transition: transform 0.5s;
`;
export const SlideInner = styled.div`
width: 100vw;
float: left;
`;
export const SlideItem = styled.div`
width: 100%;
`;
끝이다. 이렇게 간단하게 캐러셀을 만들 수 있다. 하지만 이대로 끝내기 아쉬운 느낌이 들 것이다. 왜냐면 아이템의 마지막 요소에서 다음으로 넘어가면 아무것도 안 나오기 때문이다.!
그렇다면 무한 캐러셀을 만들어야하지 않겠나!
무한 캐러셀은 기본 캐러셀보다 손 봐야 할 것이 많다. 일단 원리만 알면 어렵지 않게 구현이 가능하다!
기본 원리는 이것만 기억하자.
이 세 가지가 무한 캐러셀의 핵심이다. 하지만 문제는 transition 통해 요소가 밀리고 있는데 마지막에 도달했을 때, transition 효과를 제거해서 미리 요소의 위치를 옮겨놔야 한다.
styled-component의 Props를 이용해서 transition={LAST || FIRST ? `transform 0s` : `transform 0.5s`}
을 적용시키면 마지막과 끝에서 transition을 적용하지 않고 요소를 바꾸게 된다.
일단 이렇게 하면 부드럽게 넘어가는 것이 구현이 안되지만 원하는 구현은 끝난다. 그렇다면 어떻게 마지막 디테일을 잡을 수 있을까?
리액트를 이용해서 state 변경을 통해 index를 props로 전달해서 확인하는데 이런 상황에서 요소를 바꿀 수 있는 방법은 더 고민을 해 봐야한다.
순수 자바스크립트였다면 돔 요소 조작을 통해 구현이 가능하지만 리액트는 그렇게 사용하면 안도이...
무한 캐러셀이 약간 흠이 있게 구현이 되었지만 아주 간단하게 구현할 수 있어 라이브러리를 굳이 쓰지 않아도 되겠다는 생각이 들었다. 리액트를 잘하고 싶다...제발.
무한 스크롤을 구현했다. 하지만 문제가 발생했다. 다른 곳은 모두 괜찮지만 딱 하나의 상황에서 사진이 늦게 나온다. 이건 왜 그러는지 전혀 이해가 가지 않는다.
일단 구현 방법은 기존의 방식과 다르지 않지만, transition과 index를 상태로 관리해서 스타일을 적용하도록 코드를 구성했다.
const replaceSlide = (index) => {
setTimeout(() => {
setCurTransition("");
setCurIndex(index);
}, 500);
};
const handleSlide = (index) => {
setCurIndex(index);
if (index - 2 < 0) {
index += ORIGINSIZE;
replaceSlide(index);
} else if (index - 2 >= ORIGINSIZE) {
index -= ORIGINSIZE;
replaceSlide(index);
}
setCurTransition(initTransition);
};
replace
함수는 마지막이나 처음 요소에 접근했을 때 상반되는 같은 요소에 바로 접근하기 위한 로직이다. 위에서 설명한 것으로 가장 앞 요소는 맨 뒤에 복제하고, 맨 뒤의 요소는 맨 앞에 복제한다.
이를 다이렉트로 순식간에 보내주기 위해 transition 효과를 없애고, 인덱스를 변경한다.
하지만 1에서 2로 넘어가는 상황에서 이미지가 느리게 로드 되고 있다. 다른 경우는 밀리는 것이 확실하게 확인할 수 있는데 어떤 문제가 있는지 찾을 수가 없다...
또 굴레에 빠져버린 것이다..