ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

Issue

https://swiperjs.com/react

 

Swiper React Components

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

swiperjs.com

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„  ์‚ฌ์šฉ์ž์—๊ฒŒ ํŒ”๋กœ์šฐํ•  ๋งŒํ•œ ์นœ๊ตฌ๋ฅผ ์ƒ๋‹จ ๋ฐ”์—์„œ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

 

์ด๋•Œ ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•œ ๋ฒˆ์— ๋ชจ๋‘ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ดˆ๊ธฐ์— 8๋ช…์˜ Friend Figure๋งŒ ๋ณด์—ฌ์ฃผ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์˜€์„ ๊ฒฝ์šฐ์— ํ•œํ•ด์„œ, 8๊ฐœ์˜ ๋ฐฐ์ˆ˜๋กœ ์œ ๋™์ ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋Š” offset์„ query๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์„œ๋ฒ„์— API ํ†ต์‹ ์„ ํ•œ๋‹ค.

 

Carousel Slider ๊ธฐ๋Šฅ์€ ์ง€๊ธˆ๊นŒ์ง€ ์—ฌํƒ€ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋– ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ํ•˜๋“œ ์ฝ”๋”ฉํ•œ ๊ฒฝํ—˜์ด ๋งŽ์•˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒˆ์—๋Š” Carousel Slider ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ๋•Œ ๋Œ€ํ‘œ์ ์œผ๋กœ ๋งŽ์ด ์“ฐ์ด๋Š” Swiper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ๋กœ ํ•˜์˜€๋‹ค.

 

Swiper React ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์‚ฌ์ „ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ธํ„ฐ๋„ท์— ์ด๋ฏธ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ์ƒ๋žตํ•˜๊ณ  ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ ์Šค์Šค๋กœ ๊ณ ๋ฏผํ•˜๋ฉฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•œ ์ฝ”๋“œ๋ฅผ ์ค‘์ ์ ์œผ๋กœ ๊ธฐ๋กํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

Code

์šฐ์„  ์Šฌ๋ผ์ด๋” ๊ธฐ๋Šฅ๋งŒ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ๋Š” CarouselSlider ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณ„๋„๋กœ ์ƒ์„ฑํ•˜์—ฌ Presentation Component ๊ฐ„์— ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ฅผ ์„ฑ๋ฆฝ์‹œ์ผœ ์ฃผ์—ˆ๋‹ค.

 

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ ๋™์ž‘์ด ์›ํ™œํ•˜๊ฒŒ ๋˜๊ธฐ ์œ„ํ•ด์„  Swiper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” Swiper Component๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

 

์šฐ์„ , ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋Š” ๋์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, DB์— ์ €์žฅ๋œ ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋“ค์„ offset๊ฐ’์œผ๋กœ ๋งค๋ฒˆ next ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค API์„ ํ†ต์‹ ํ•˜์—ฌ ๊ฐ€์ ธ์™€์„œ ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ ๋ฐฐ์—ด์— ์ด์–ด์„œ ์ €์žฅํ•ด์ค˜์•ผ ํ•œ๋‹ค.

 

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์„ ๋•Œ ์ด๋ ‡๋“ฏ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ ๋™์ž‘์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณ„๋„์˜ swiper ๋ณ€์ˆ˜๋ฅผ ์ž์‹ ์˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด์— state ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์ฃผ๊ณ  ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ Swiper ์ปดํฌ๋„ŒํŠธ ๋‚ด props๋กœ ๋„˜๊ฒจ swiper๋ฅผ ์ธ์Šคํ„ด์Šค ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด useState์˜ setSwiper ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋…ธ๋“œ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ๋•Œ์ฒ˜๋Ÿผ ์„ค์ •ํ•ด ์คŒ์œผ๋กœ์จ, Swiper ์ปดํฌ๋„ŒํŠธ์— ์ข…์†๋˜์ง€ ์•Š๊ณ  swiper ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ๋™์ž‘์ด ์ผ์–ด๋‚˜๋„๋ก ์ปค์Šคํ„ฐ ๋งˆ์ด์ง•ํ•ด์ฃผ์—ˆ๋‹ค.

	( ... )

const [swiper, setSwiper] = useState(null);


	( ... )

return (
    <StyledSwiper ref={setSwiper}>
      {children}
    </StyledSwiper>
  );

์œ„์˜ ์„ค์ •๋งŒ์œผ๋ก  ์›ํ™œํ•œ ๋™์ž‘์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. Swiper ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ด๋‹นํ•ด ์ค„ ๊ฐ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉ์‹œ์ผœ์ฃผ์—ˆ๋‹ค๋ฉด, ์ด์ œ๋Š” ์ด๋ฅผ ์‹ค์ œ ์„ค์ • ๊ฐ’ ๊ฐ์ฒด์— ์ •๋ณด๋กœ ๋ฐ”์ธ๋”ฉํ•ด์ฃผ์–ด ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ props๋กœ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•œ๋‹ค.ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„  Carousel Slider์˜ ๊ธฐ๋ณธ ๋””์ž์ธ์„ ์ฐจ์šฉํ•˜์ง€ ์•Š๊ณ  ๋””์ž์ด๋„ˆ ๋ถ„์ด ์ฃผ์‹  ์‹œ์•ˆ๋Œ€๋กœ ์Šคํƒ€์ผ ์ปค์Šคํ„ฐ ๋งˆ์ด์ง•ํ•ด์•ผ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฒ„ํŠผ ์š”์†Œ ๋˜ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚ด๊ฐ€ ์„ค์ •ํ•œ ๊ฐ’์œผ๋กœ ๋žœ๋”๋ง๋˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค.

	( ... )

const navigationPrevRef = useRef(null);
const navigationNextRef = useRef(null);

	( ... )

const swiperParams = {
    navigation: {
      prevEl: navigationPrevRef.current,
      nextEl: navigationNextRef.current,
    },
    onBeforeInit: swiper => {
      swiper.params.navigation.prevEl = navigationPrevRef.current;
      swiper.params.navigation.nextEl = navigationNextRef.current;
      swiper.navigation.update();
    },
    slidesPerView: 1,
    onSwiper: setSwiper,
  };

์ด์ œ next ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๊ฒฝ์šฐ์— ์„œ๋ฒ„์—์„œ ์ƒˆ๋กœ์šด ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด react-redux useDispatch์™€ friends Module์—์„œ offset๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผœ ์ฃผ๋Š” increaseFriendOffset๊ณผ ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์„œ๋ฒ„์—์„œ ๊ฐ€์ ธ ์˜ค๋Š” friendList ๋‘ ์•ก์…˜ ์ƒ์„ฑ ํ•จ์ˆ˜๋ฅผ importํ•˜์—ฌ ์ด๋ฒคํŠธ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ trigger ์‹œ์ผœ ์ฃผ์—ˆ๋‹ค.

 

์ด๋•Œ ์ถ”๊ฐ€์ ์œผ๋กœ ์กฐ๊ฑด ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์—ˆ๋Š”๋ฐ, ๋งŒ์•ฝ์— next ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ API ํ†ต์‹ ์„ ํ•จ๊ณผ ๋™์‹œ์— ๋‹ค์Œ ์Šฌ๋ผ์ด๋“œ๋กœ ๋„˜์–ด๊ฐ€๊ณ  ๋‹ค์‹œ ๋’ค๋กœ ๋Œ์•„๊ฐˆ ๊ฒฝ์šฐ์—๋Š” ๋ณ„๋„์˜ API ํ†ต์‹ ์„ ํ•˜์ง€ ์•Š๊ณ  ์ „์— ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ๊ฐ€์ ธ ์˜จ ๋ฐ์ดํ„ฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— Click ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋”๋ผ๋„ ํ•ด๋‹น ๋ฒ„ํŠผ prev ๋ฒ„ํŠผ์ผ ๊ฒฝ์šฐ์—๋Š” ๋ฆฌํ„ด๋˜๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.

 

๋˜ํ•œ ์ด์ „ ์Šฌ๋ผ์ด๋“œ๋กœ ๋Œ์•„๊ฐ”๋‹ค๊ฐ€ ๋‹ค์‹œ ๋‹ค์Œ ์Šฌ๋ผ์ด๋“œ๋กœ ์ด๋™ํ•˜์˜€๊ณ  ํ•ด๋‹น ์ด๋™๋œ ์Šฌ๋ผ์ด๋“œ๊ฐ€ ๋งˆ์ง€๋ง‰ ์Šฌ๋ผ์ด๋“œ์ผ ๊ฒฝ์šฐ์—๋Š” swiper.isEnd ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ง€๋ง‰ ์Šฌ๋ผ์ด๋“œ์ธ์ง€ ์‹๋ณ„ํ•˜๊ณ  ๋งž๋‹ค๋ฉด isPrev ์‹๋ณ„ ๋ณ€์ˆ˜๋ฅผ false๋กœ ๋ฐ”๊ฟ”์ฃผ์—ˆ๋‹ค.

const nextSlide = () => {
    if (isPrev) {
      if (swiper.isEnd) isPrev = false;
      return;
    }

    batch(() => {
      dispatch(increaseFriendsOffset("recommendFriendList"));
      dispatch(friendList());
    });
  };

 

useLayoutEffect๋ฅผ ํ†ตํ•ด ์Šฌ๋ผ์ด๋“œ ์ด๋™

๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ  API ํ†ต์‹ ์„ ์™„๋ฃŒํ•˜์—ฌ ๊ทธ ๋‹ค์Œ ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋ฆฌ๋•์Šค ์Šคํ† ์–ด์— ์ ์žฌํ•˜๋Š” ๊ฒƒ๊นŒ์ง„ ์„ฑ๊ณตํ•˜์˜€์ง€๋งŒ ํ•ด๋‹น ๊ฐ’์„ useEffect ๋‚ด์—์„œ ์ฒ˜๋ฆฌํ•˜๋‹ค ๋ณด๋‹ˆ ์ œ๋Œ€๋กœ ๋™์ž‘์ด ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

 

ํ˜„์žฌ CarouselSlider ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด์„ ํ†ตํ•ด map ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ทธ๋ ‡๊ฒŒ ์™„์„ฑ ๋œ  JSX๋Š” children ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋„˜๊ฒจ์ค€๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น children ๊ฐ์ฒด๋ฅผ useEffect ๋‚ด์— ์˜์กด์„ฑ ๋ฐฐ์—ด์— ํ• ๋‹นํ•ด ์ฃผ์–ด ํ•ด๋‹น ๊ฐ’์ด ๋ฐ”๋€” ๊ฒฝ์šฐ์— ์Šฌ๋ผ์ด๋”๊ฐ€ ์‹ค์ œ ํ™”๋ฉด ์ƒ์—์„œ ๋’ค์— ์ด์–ด ๋ถ™์–ด์ง๊ณผ ๋™์‹œ์— ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ์˜๋„ํ•œ ๊ฒƒ์ด์—ˆ๋Š”๋ฐ, ๊ธฐ๋Šฅ์ด ์ œ๋Œ€๋กœ ๋™์ž‘๋˜์ง€ ์•Š์•˜๋‹ค.

	    ( ... )

return (
    <Container>
      <Name>๋งž์ถค์นœ๊ตฌ ์ถ”์ฒœ</Name>
      <CarouselSlider>
        {completeContents[0].map((friendList, index) => {
          return (
            <SwiperSlide key={index}>
              <FriendList>
                {friendList.map(
                  ({ id, nickname, image_url, follows }, index) => {
                    return (
                      <FriendFigure
                        key={index}
                        nickname={nickname}
                        image_url={image_url}
                        follows={follows}
                      />
                    );
                  }
                )}
              </FriendList>
            </SwiperSlide>
          );
        })}
      </CarouselSlider>
    </Container>
  );

์›์ธ์„ ๊ณฐ๊ณฐํžˆ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ useEffect์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” Rendering๊ณผ Paint๊ฐ€ ๋ชจ๋‘ ์ผ์–ด๋‚œ ๋’ค์— ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€ ๋œ ์Šฌ๋ผ์ด๋”๊ฐ€ ์•ˆ์ •์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š๊ณ  ์ด๋กœ ์ธํ•ด ๋‹ค์Œ ์Šฌ๋ผ์ด๋“œ๋กœ Switching๋˜์ง€๋„ ์•Š์•˜๋˜ ๊ฒƒ์ด๋‹ค.

 

์ด์— ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด๋‹ˆ useLayoutEffect ๋ผ๋Š” Hooks๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

https://ko.reactjs.org/docs/hooks-reference.html#uselayouteffect

 

Hooks API Reference – React

A JavaScript library for building user interfaces

ko.reactjs.org

The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.

์ฆ‰, ํ™”๋ฉด์— ์ตœ์ข…์ ์œผ๋กœ ๋ณด์—ฌ์ง€๊ธฐ ์ „์— DOM ํŠธ๋ฆฌ๊ฐ€ ๊ตฌ์„ฑ๋˜๊ณ  ํ•ด๋‹น DOM ํŠธ๋ฆฌ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ฐธ์กฐํ•˜์—ฌ ๋™๊ธฐ์ ์œผ๋กœ ๋ฆฌ๋žœ๋”๋ง์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์“ธ ์ˆ˜ ์žˆ๋Š” Hooks ์˜€๋‹ค.

 

์ด์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด children์— ํ•ด๋‹นํ•˜๋Š” ์นœ๊ตฌ ๋ฆฌ์ŠคํŠธ ๋ ˆ์ด์•„์›ƒ์ด ๋ชจ๋‘ ๋žœ๋”๋ง๋œ ์ดํ›„์— ๋‹ค์Œ ์Šฌ๋ผ์ด๋“œ๊ฐ€ ๋„˜์–ด๊ฐ€์ง€๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๊ณ  ๊ธฐ๋Šฅ ๋™์ž‘์— ์„ฑ๊ณตํ•˜์˜€๋‹ค.

useLayoutEffect(() => {
    if (swiper) swiper.slideNext();
  }, [children]);

 

๋™์ž‘ ์˜์ƒ

๋Œ“๊ธ€
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG
more
ยซ   2024/10   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ