[유데미x스나이퍼팩토리] 프로젝트 캠프 Next.js 1기 11일차

oweaj·2024년 6월 10일
0
post-thumbnail

metadata

  • 각 페이지의 맞는 특성, 내용, 관련 정보를 설정하여 SEO와 사용자 경험을 향상시킬 수 있다.
// root layout

export const metadata = {
  title: "Hello Word"
  description: "Let's learn next.js",
};

  • template : 동적 제목을 구성하기 위해 %s는 다른 페이지에서 제공되는 제목으로 대체됨
  • default : 제목이 제공되지 않을 때 사용할 기본 제목
// root layout

export const metadata = {
  title: {
    template: '%s | Hello Word',
    default: 'Next.JS 14 | Hello Word',
  },
  description: "Let's learn next.js",
};

------------------------------------------------

// login 폴더 -> layout

export const metadata = {
  title: 'Login',
};

위 코드 처럼 template에 %s를 설정하고 login폴더의 layout의 metadata를 보면 title의 %s에 "Login"이 대체가 되어 Login | Hello Word의 title이 보여지게된다.


  • 동적 경로
  • generateMetadata : 페이지별로 동적 메타데이터를 설정할 수 있게 해주는 예약된 이름의 함수
// blog 폴더 -> [id] 폴더 -> layout

interface IMetaProps {
  params: {
    id: string;
  };
}

export const generateMetadata = async ({ params }: IMetaProps) => {

  return {
    title: `Blog ${params.id} | Hello World`,
  };
};

만약 blog/2... blog/10 이런식의 동적 경로였을때 위처럼 generateMetadata 함수와 params를 활용해서 페이지별로 동적 메타데이터를 설정할 수 있다.

병렬 로딩

// ServerOne 컴포넌트
export default async function ServerOne() {
  await new Promise((resolve) => setTimeout(resolve, 4000));  // 4초 딜레이

  return (
    <>
      <h1>ServerOne Component</h1>
    </>
  );
}

------------------------------------------------------------

// ServerTwo 컴포넌트
export default async function ServerTwo() {
  await new Promise((resolve) => setTimeout(resolve, 2000));  // 2초 딜레이

  return (
    <>
      <h1>ServerTwo Component</h1>
    </>
  );
  

위의 각각 컴포넌트를 부모컴포넌트에 불러와 실행하게되면 ServerOne 컴포넌트는 4초 ServerTwo 컴포넌트는 2초의 딜레이로 총 로딩시간은 6초가 아니라 병렬 로딩으로 가장 로딩이 늦은 컴포넌트 시간인 4초가 총 로딩시간이된다.

❗️ 그러면 4초라는 로딩 지연 시간동안 사용자는 무슨 일이 일어나고 있는지 알 수 없고 사용자 경험에도 좋지 않다.

그래서 컴포넌트의 로딩 상태관리를 해줘야한다.

1) loading

  • 컴포넌트의 로딩 상태를 관리해줄 수 있는 파일
// about 폴더 -> page 파일

export default function About() {
  return (
    <>
      <h1>About Component</h1>
      <ServerOne />
      <ServerTwo />
    </>
  );
}
// about 폴더 -> loading 파일

export default function loading() {
  return (
    <>
      <AiOutlineLoading3Quarters className="w-10 h-10 animate-spin" />
      <h1>About loading ...</h1>
    </>
  );
}

위처럼 loading 시스템 파일을 활용해서 4초의 로딩지연 시간동안 로딩 컴포넌트를 보여줌으로써 사용자에게 로딩 중이라는 상황을 전달하여 사용자 경험에 좋은 영향을 줄 수 있다.

2) Suspense

  • Suspense는 각각의 컴포넌트를 개별로 멀티로딩을 하여 로딩상태를 관리 할 수 있다.
// about 폴더 -> page 파일

export default function About() {
  return (
    <>
      <h1>About Component</h1>
      // 해당 컴포넌트를 Suspense로 감싸줘야한다.
      // 로딩 될때 보여지는 부분을 fallback에 정의
      <Suspense fallback={<h1 className="text-blue-500">ServerOne 로딩중...</h1>}>
        <ServerOne />
      </Suspense>
      <Suspense fallback={<h1 className="text-orange-500">ServerTwo 로딩중...</h1>}>
        <ServerTwo />
      </Suspense>
    </>
  );
}

위 처럼 병렬로 처리되면서 각각 컴포넌트가 개별로 로딩이 가능하며 먼저 로딩이 되는 컴포넌트 순으로 랜더링 된다.

error

// error 컴포넌트
'use client';

export default function BlogError({ error, reset }: { error: Error; reset: () => void }) {
  return (
    <>
      <h1>BlogError Component : {error.message}</h1>
      <button onClick={reset}>try again</button>
    </>
  );
}

=> error 컴포넌트는 경로마다 중첩하여 지정할 수 있다.
  • error : 발생한 오류를 표시하고 오류에 대해 자세한 정보를 포함한 객체
  • reset : 에러가 발생한 컴포넌트를 다시 불려오려고 시도하는 함수
// blog 컴포넌트
'use client';

import BlogCard from '../components/blogCard';

export default function Blog() {
  return (
    <>
      <h1>Blog Component</h1>
      <BlogCard />
    </>
  );
}

--------------------------------------

//  blogCard 컴포넌트
export default function blogCard() {
  let random = Math.floor(Math.random() * 10 + 1);

  console.log(random);

  if (random < 3) {
    throw new Error('Random Test Error');
  }

  return (
    <>
      <h1>blogCard Component</h1>
    </>
  );
}

error test 조건에 따라 랜덤하게 BlogCard 컴포넌트가 에러를 던지면 가장 가까운 경로에 있는 error 컴포넌트를 찾아서 에러 페이지가 렌더링되고 다시 시도하는 버튼으로 reset 함수를 호출시켜 다시 시도를 수행한다.


profile
데굴데굴데굴데굴데굴

0개의 댓글