[Next.js] 페이지 이동시 로딩 처리하기

2022. 4. 19. 10:21Library,Framework

728x90

Next JS는 SSR 프레임워크이긴 하지만 Link 컴포넌트나 Router를 통한 Client Side Navigation (페이지 전환이 JS를 통해 이루어짐)이 가능하기 때문에 페이지 이동시 CSR 앱만큼이나 좋은 UX경험을 전달할 수 있습니다. 이번 포스트에서는 Next JS에서 라우터를 통한 페이지 이동을 할 때 좋은 사용자 경험을 위해 적용할 수 있는 로딩 처리 방법에 대해 알아보겠습니다.

 

로딩처리를 하지 않은 경우 (클릭하면 일정시간동안 아무 변화없음)

 

커스텀 로딩 스피너, nprogress의 Progress바를 통한 로딩처리

 


 

Router 이벤트

위에서 보이는바와 같이 로딩 처리를 하고 안하고의 차이는 웹앱을 사용하는 사용자 입장에선 매우 큽니다. 가벼운 페이지나 SSG를 방식을 통해 생성된 페이지는 괜찮을 수도 있지만 서버사이드 랜더링을 해야 하는 페이지에서 좀 무거운 작업을 하게 된다면 로딩 상태를 알릴 수 있는 Spinner나 Progress 바는 없어서는 안 될 존재입니다. 이런 로딩 처리를 손쉽게 처리할 수 있게 해 주는 게 바로 Router Event로 라우트 주소가 변경되었을때 트리거 되는 이벤트입니다. 

 

페이지간의 로딩을 구현하기 위해서는 아래 3가지 Router 이벤트가 필요합니다.

 

  • routeChangeStart(url, { shallow }) - 라우트가 변경되기 시작할때 트리거 됩니다
  • routeChangeComplete(url, { shallow }) - 라우트가 완전히 변경되었을 때 트리거 됩니다
  • routeChangeError(err, url, { shallow }) - 라우트 변경 중에 에러가 발생했거나, 취소되었을 때 트리거 됩니다
    • err.cancelled - 내비게이션 작업이 취소되었는지에 대한 여부

 


NProgress를 통한 로딩 처리

 

NProgress: slim progress bars in JavaScript

NProgress.start() — shows the progress bar NProgress.set(0.4) — sets a percentage NProgress.inc() — increments by a little NProgress.done() — completes the progress Download v Perfect for Turbolinks, Pjax, and other Ajax-heavy apps.

ricostacruz.com

npm i nprogress // 또는 yarn add nprogress

 

_app.js (커스텀 App 컴포넌트)

import { useEffect } from "react";
import Router from "next/router";
import NProgress from "nprogress";
import "nprogress/nprogress.css";

const MyApp = () => {
    useEffect(() => {
        const start = () => {
          NProgress.start();
        };
        const end = () => {
          NProgress.done();
        };

        Router.events.on("routeChangeStart", start);
        Router.events.on("routeChangeComplete", end);
        Router.events.on("routeChangeError", end);

        return () => {
          Router.events.off("routeChangeStart", start);
          Router.events.off("routeChangeComplete", end);
          Router.events.off("routeChangeError", end);
        };
      }, []);
  	...생략
  }

 

 

위와 같은 방법으로 nprogress 패키지를 설치한 뒤 nprogress 애니메이션 API를 Next JS의 라우터 이벤트에 바인딩해주기만 하면 정상적으로 적용됩니다. 

 


커스텀 로딩 처리

커스텀 로딩 처리라곤 하지만 사실 크게 달라지는 건 없습니다.

 

똑같이 라우터 이벤트를 사용하지만 nprogress의 애니메이션을 바인딩하는 대신 로딩 상태만 변경하고 해당 상태에 따라 반환하는 컴포넌트만 변경해주면 됩니다.

 

import { useEffect, useState } from "react";
import Router from "next/router";
import FullScreenLoading from "components/FullScreenLoading";

const MyApp = () => {
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const start = () => {
      // NProgress.start();
      setLoading(true);
    };
    const end = () => {
      // NProgress.done();
      setLoading(false);
    };

    Router.events.on("routeChangeStart", start);
    Router.events.on("routeChangeComplete", end);
    Router.events.on("routeChangeError", end);

    return () => {
      Router.events.off("routeChangeStart", start);
      Router.events.off("routeChangeComplete", end);
      Router.events.off("routeChangeError", end);
    };
  }, []);

  return loading ? (
    <FullScreenLoading />
  ) : (
    <메인 컴포넌트/>
  );
};

export default MyApp;

 

필자의 경우 FullScreenLoading의 애니메이션을 CSS로 구현했지만 Loading.io에서 SVG나 GIF 형태로 입맛에 맞게 다운로드해서 적용하면 페이지 이동시 적용하신 로딩 이미지/애니메이션을 확인하실 수 있습니다.