[Next.js] Next.js(SSR 환경)에서 css 애니메이션이 작동 안하는 이유

2024. 7. 12. 16:35·Frontend

1. Next.js? 그냥 react 개발하듯이 하면 되지 않나?

방학 동안, Next.js 14를 익히고 싶어서 Next.js로 자기소개 사이트를 만들고 있다. 블로그 글을 읽으며 개발할 때 React와 어떤 차이점이 있는지 읽고 바로 작업에 들어갔다. 작업을 하며 라우팅 방식이나 서버 컴포넌트 같은 차이점 외에는 React와 별 다른 점이 없다고 생각하기도 했었다.(header 밖에 안 만들었을 때 그런 생각을 한 게 참…ㅋㅋㅋ). 하지만, 그 생각은 길게 유지되지 않았다. 왜냐하면 css 애니메이션이 동작하지 않았기 때문이다.

 

2. css 애니메이션이 작동하지 않아요

내가 좋아하는 음악의 앨범 커버, 노래 제목, 가수 이름이 적혀있는 MusicCard 컴포넌트가 있고, 그 MusicCard 컴포넌트들이 일렬로 오른쪽에서 왼쪽으로 무한히 재생되는 컴포넌트인 MusicSlide를 제작하려고 했다. 따라서 MusicSlide.css를 생성해서 애니메이션(transition, transform..) 코드를 입력했다.(tailwind css를 쓰고 싶었지만 애니메이션 관련 코드들은 따로 파일로 만들었다.)

 

문제점은, 애니메이션이 재생이 되지 않는다는 것이었다! 그런데 이상하게도 vscode에서 코드를 수정하고 저장하면 그 때는 애니메이션이 재생이 되었다. 도대체 왜 이런 일이 발생했나 이해가 되지 않았다. 혹시 로컬 환경이라서 이런 일이 발생했나 싶어서 vercel로 배포를 해서 살펴봤는데도 애니메이션이 재생되지 않았다. 코드를 이리저리 수정해봐도 도저히해당 버그가 수정되지 않았다.

 

그러다가 문득 내가 Next.js를 써서 이런 일이 발생했나하는 생각이 들었다. 그래서 해당 컴포넌트에서 next/dynamic을 import해와서 ssr 옵션을 false로 만들어줬다(해당 컴포넌트를 서버 사이드 렌더링이 아닌, 클라이언트 사이드 렌더링(CSR)로 구동시킨다는 뜻). 그랬더니 애니메이션이 정상적으로 작동이 되었다!

'use client';

import React, { useRef, useEffect, useState } from 'react';

// 애니메이션 작동을 위해서 dynamic import를 통해 CSR 강제
import dynamic from 'next/dynamic';

import MusicCard from './MusicCard';
import slides from '@/constants/Slides';
import uuid from 'react-uuid';
import './MusicSlide.css';

const MusicSlide = ({ reverse = false }) => {
  const carouselRef = useRef<HTMLDivElement>(null); // 캐러셀의 참조를 저장할 useRef를 선언
  const loadedImageCount = useRef(0); // 로드된 이미지 수를 저장할 useRef를 선언
  const [isLoaded, setIsLoaded] = useState(false);

    (...)
    
}

export default dynamic(() => Promise.resolve(MusicSlide), { ssr: false });

 

 

3. 서버 사이드 렌더링에서는 왜 css 애니메이션이 동작하지 않을까 물어봤다

서버 사이드 렌더링 환경에서 왜 애니메이션이 작동되지 않았을까. 바로 Slack에 질문을 남겼다.

Slack에 남긴 질문

그리고 머지않아 답변이 왔다.

Slack 답

SSR 환경에서는 ref를 통한 DOM 조작이 동작하지 않아서 그런 일이 발생한 것이었다.

답변을 정리해봤다

정리하자면, 위의 사진과 같다. SSR 환경에서는 ref를 통한 DOM 요소의 접근이 잘 동작하지 않아서 css 애니메이션이 재생되지 않았던 것이었다. 그리고 이에 대한 해결책으로는 forwardRef를 통해서 DOM 요소에 접근하면 되는 것이었다.

 

4. 그러면 이제 고쳐볼까

따라서 MusicSlide.tsx에 개별 이미지 요소를 가리키는 ref 배열인 imageRefs를 새로 만들어서 MusicCard.tsx에 전달해줬다.

 

MusicSlide.tsx 에서

  // 각각의 MusicCard 컴포넌트 내의 개별 img 요소를 가리키는 ref 배열
  const imageRefs = useRef(slides.map(() => createRef<HTMLImageElement>()));

 

MusicCard.tsx에서

import React, { forwardRef } from 'react';

interface Props {
  albumCover: string;
  songTitle: string;
  artist: string;
  onLoad: () => void;
}

// forwardRef를 사용함으로써 DOM 조작 가능
const MusicCard = forwardRef<HTMLImageElement, Props>(
  ({ albumCover, songTitle, artist, onLoad }, ref) => {
    return (
      <div className="p-8">
        <img
          ref={ref}
          src={albumCover}
          alt="Album Cover"
          className="w-48 h-24 rounded-t-lg object-contain"
          onLoad={onLoad}
        />
        <div className="text-left">
          <h3 className="text-xs font-semibold whitespace-nowrap">
            {songTitle}
          </h3>
          <p className="text-xs text-gray-500 whitespace-nowrap">{artist}</p>
        </div>
      </div>
    );
  }
);

export default MusicCard;

 

 

5. 하지만 고치지 못했다

하지만 애니메이션은 실행이 안되었다.... 애초에 Next.js를 사용하면서 css 애니메이션을 활용하려는 것이 잘못된 접근이었나하는 생각이 들어서 새로운 애니메이션 라이브러리를 도입해볼까 한다.

 

이런 시행착오 속에서, 비록 버그를 고치지는 못했지만 ref와 forwardRef에 대해서, Server Side Rendering의 구조에 대해서 더 확실히 배울 수 있었다. 이 또한 값진 경험이겠지...ㅋㅋㅋ

저작자표시 비영리 변경금지 (새창열림)

'Frontend' 카테고리의 다른 글

'react-datepicker'에서 날짜 상태를 관리할 때 겪었던 시행착오  (0) 2024.08.03
프로젝트 팀원 코드를 보고 컴포넌트 만드는 법 배우기(typescript + clsx)  (1) 2024.07.21
[HTML] HTML 구조, <script> 태그, HTML 박스모델 등에 대한 요약  (0) 2024.03.14
[Vite + TS] Vite에서 svg 파일을 못 읽을 때(@svgr/rollup 사용)  (1) 2024.03.02
[React, TS] 프로젝트를 진행하며 상태 관리에 대해 알게 된 것들  (2) 2024.01.13
'Frontend' 카테고리의 다른 글
  • 'react-datepicker'에서 날짜 상태를 관리할 때 겪었던 시행착오
  • 프로젝트 팀원 코드를 보고 컴포넌트 만드는 법 배우기(typescript + clsx)
  • [HTML] HTML 구조, <script> 태그, HTML 박스모델 등에 대한 요약
  • [Vite + TS] Vite에서 svg 파일을 못 읽을 때(@svgr/rollup 사용)
퀵차분
퀵차분
Web Developer 🥐
  • 퀵차분
    QC's Devlog
    퀵차분
  • 전체
    오늘
    어제
    • 분류 전체보기 (178)
      • Frontend (31)
      • Fedify (4)
      • Study (42)
        • NestJS (2)
        • Node.js (3)
        • Modern JS Deep Dive (13)
        • SQL (1)
        • Network (1)
        • 프롬프트 엔지니어링 (4)
        • 인공지능 (9)
        • 시스템프로그래밍 (11)
        • 선형대수학 (1)
      • Intern (4)
      • KUIT (21)
      • Algorithm (48)
        • Baekjoon(C++) (26)
        • Programmers(JavaScript) (22)
      • 우아한테크코스(프리코스) (4)
      • Project (10)
        • crohasang_page (3)
        • PROlog (4)
        • Nomadcoder (2)
      • 생각 (4)
      • Event (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    오블완
    프로그래머스 자바스크립트
    자바스크립트
    타입스크립트
    javascript
    백준
    next.js
    음악추천
    KUIT
    티스토리챌린지
    프로그래머스
    HTML
    typescript
    react
    시스템프로그래밍
    인공지능
    fedify
    프론트엔드
    알고리즘
    리액트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
퀵차분
[Next.js] Next.js(SSR 환경)에서 css 애니메이션이 작동 안하는 이유
상단으로

티스토리툴바