티스토리 뷰

Router 

redirect 기능처럼 컴포넌트에서 버튼을 클릭해서 동적 라우팅을 구현할 수 있다. 참고로 app 내부의 컴포넌트는 서버 컴포넌트 이기 때문에 사용자가 클릭해서 클라이언트 라우팅을 시키려면 버튼 컴포넌트는 따로 클라이언트 컴포넌트로 빼줘야 한다.

 

예시 코드

products 상세페이지 서버 컴포넌트

src/app/products/[item]/page.tsx

import { Metadata } from "next";
import React from "react";
import { typesOfItem } from "@/app/shared/const";
import { getProduct } from "@/service/products";
import { notFound, redirect } from "next/navigation";
import Image from "next/image";
import GoProductsBtn from "@/components/GoProductsBtn";
type Props = {
  params: {
    item: string;
  };
};

export const revalidate = 3;

export function generateMetadata({ params: { item } }: Props): Metadata {
  return {
    title: `제품의 이름: ${item}`,
  };
}

export default async function ProductItemDetailPage({
  params: { item },
}: Props) {
  const product = await getProduct(item);

  if (!product) {
    redirect("/products");
  }

  //서버 파일에 있는 데이터 중 해당 제품의 정보를 찾아서 그걸 보여준다.
  return (
    <>
      <div>{product.name} DetailPage</div>
      <Image
        src={`/images/${product.imageUrl}`}
        alt={product.name}
        width={300}
        height={300}
      />
      <GoProductsBtn />
    </>
  );
}

// 모든 제품의 디테일 페이지를 미리 만들어둠(SSG)
//? generateStaticParams도 비동기 함수처리 가능
export async function generateStaticParams() {
  return typesOfItem.map((itemName) => ({ item: itemName }));
}
  • SPA 방식에 익숙해져서 GoProductsBtn 부분을 <button onClick ~ > 이런 식으로 작성했었는데 클라이언트에서 동적 라우팅 시키는 것이라는 사실을 염두하면 따로 클라이언트 컴포넌트로 빼주는 게 맞다.

src/components/GoProductsBtn.tsx

"use client";
import { useRouter } from "next/navigation";
import React from "react";

export default function GoProductsBtn() {
  const router = useRouter();
  return (
    <button
      onClick={() => {
        router.push("/products");
      }}
    >
      제품 페이지로 이동
    </button>
  );
}
  • 여기서 onClick 이벤트를 처리해주는데 useRouter 이라는 함수를 next/navigation 에서 import해온다.

Q. useRouter 가 2개인데 어느 객체에서 import 해와야 하나요? 

참고로 12버전 pages 기반에서는 next/router 에서 import 해왔다.
(버전마다 임포트 해오는 객체가 다르니 잘 보고 가져와야 한다.)

  • 13버전(app기반): import { useRouter } from "next/navigation";
  • 12버전(pages기반): import { useRouter } from "next/router";

Next 이미지 컨텐츠 최적화 오류 

에러 메세지

warn-once.js:16 Image with src "/_next/static/media/clothes.08a4a46d.jpg" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.

내용: 큰 이미지 컨텐츠가 최적화가되지 않고 동작하고 있다는 뜻

해결방법: priority 속성을 줘서 lazy load를 비활성화 시키고 우선순위를 높여 pre-load시킨다.

  • priority={true} 혹은 priority 만 주면 된다.(기본값이 false)
//코드 중략

  return (
    <>
      <div>{product.name} DetailPage</div>
      <Image
        priority={true}
        src={`/images/${product.imageUrl}`}
        alt={product.name}
        width={300}
        height={300}
      />
      <GoProductsBtn />
    </>
  );
}

ref: https://nextjs.org/docs/pages/api-reference/components/image#priority

 

Components: <Image> | Next.js

Good to know: If you are using a version of Next.js prior to 13, you'll want to use the next/legacy/image documentation since the component was renamed. This API reference will help you understand how to use props and configuration options available for th

nextjs.org

 

댓글