React

넥스트를 app router 방식으로 개발하다보면 메타태그에서 같은 데이터를 중복으로 호출하는 경우가 발생한다.

https://stackoverflow.com/questions/77478097/avoiding-duplicate-database-calls-to-generate-metadata-in-next-13-14

 

 

다음은 Next.js 애플리케이션에서 속성 세부 페이지를 위한 메타데이터 생성을 구현하고,

캐싱을 통해 중복 API 호출을 방지하는 방법에 대한 설명입니다.

 

메타데이터 생성과 캐싱 처리

  1. 캐시 설정:
    • propertyCache라는 Map 객체를 사용하여 속성 데이터를 캐시합니다. 이 캐시는 속성 ID를 키로 사용하여 데이터를 저장합니다.

 


const propertyCache = new Map<string, PropertyProps | null>();

 

속성 데이터 가져오기 함수:

  • fetchPropertyCache 함수는 속성 ID를 받아 해당 ID에 대한 속성 데이터를 반환합니다.
  • 먼저 캐시를 확인하여 데이터가 있는지 확인합니다. 데이터가 있다면, 해당 데이터를 반환합니다.
  • 캐시에 데이터가 없다면, API 호출을 통해 데이터를 가져오고, 캐시에 저장한 후 반환합니다.

 

export async function fetchPropertyCache(id: string): Promise<PropertyProps | null> {
  if (propertyCache.has(id)) {
    return propertyCache.get(id) || null;
  }
  console.log("====================캐시 호출  -----");
  try {
    const res = await fetch(`${apiDomain}/api/properties/${id}`);
    if (!res.ok) {
      throw new Error("Failed to fetch property");
    }
    const property = await res.json();
    propertyCache.set(id, property);
    return property;
  } catch (error) {
    console.error(error);
    propertyCache.set(id, null);
    return null;
  }
}

 

메타데이터 생성:

  • generateMetadata 함수는 속성 ID를 받아 해당 속성에 대한 메타데이터를 생성합니다.
  • fetchPropertyCache 함수를 사용하여 속성 데이터를 가져옵니다.
  • 속성 데이터가 없는 경우, 기본 메타데이터를 반환합니다.
  • 속성 데이터가 있는 경우, 속성 이름과 설명을 포함한 메타데이터를 생성하여 반환합니다.

 

 

export async function generateMetadata({ params: { id } }: PropertiesDetailPageProps, parent: ResolvingMetadata): Promise<Metadata> {
  console.log("====================메타 데이터에서 호출  -----");
  const property = await fetchPropertyCache(id);
  if (!property) {
    return {
      title: "데이터가 없습니다.",
      description: "해당 속성에 대한 데이터를 찾을 수 없습니다.",
    };
  }

  return {
    title: '부동산 플래닛 | ' + property.name,
    description: property.description,
    openGraph: {
      images: property.images.map((image: string) => ({
        url: image,
        width: 800,
        height: 600,
        alt: property.name,
      })),
    },
  };
}

 

속성 세부 페이지 컴포넌트:

  • PropertiesDetailPage 컴포넌트는 속성 ID를 받아 속성 세부 정보를 표시합니다.
  • fetchPropertyCache 함수를 사용하여 속성 데이터를 가져오고, 데이터가 없는 경우 404 페이지를 반환합니다.
  • 데이터가 있는 경우, 속성 세부 정보와 이미지를 표시합니다.

 

const PropertiesDetailPage: NextPage<PropertiesDetailPageProps> = async ({ params }) => {
  if (!params.id) return notFound();
  let property: PropertyProps | null = null;

  const propertyDoc = await fetchPropertyCache(params.id);
  if (propertyDoc) {
    property = convertToSerializableObject(propertyDoc); 
  }
  
  if (!property) {
    return notFound();
  }

  const propertyData: PropertyCardProps = { property: property };

  return (
    <>
      <Suspense fallback={<Spinner loading={true} />}>
        <PropertyHeaderImage image={property.images[0]} name={property.name} />
      </Suspense>

      <section>
        <div className="container m-auto py-6 px-6">
          <Link
            href="/properties"
            className="text-blue-500 hover:text-blue-600 flex items-center"
          >
            <FaArrowLeft className="mr-2" />
            속성 목록으로 돌아가기
          </Link>
        </div>
      </section>

      <section className="bg-blue-50">
        <div className="container m-auto py-10 px-6">
          <div className="grid grid-cols-1 md:grid-cols-70/30 w-full gap-6">
            <Suspense fallback={<Spinner loading={true} />}>
              <PropertyDetails property={property} />
            </Suspense>

            <PropertyAside property={property} />
          </div>
        </div>
      </section>
      <PropertyImages images={property.images}  />
    </>
  );
};

 

요약

  • fetchPropertyCache 함수는 속성 데이터를 캐시하여 중복된 API 호출을 방지합니다.
  • generateMetadata 함수는 캐시된 데이터를 사용하여 메타데이터를 생성합니다.
  • PropertiesDetailPage 컴포넌트는 캐시된 데이터를 사용하여 속성 세부 정보를 표시합니다.

이와 같이 캐시를 활용하면 성능을 향상시키고 불필요한 API 호출을 줄일 수 있습니다.

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

우리들 각자가 타인을 정말로 이해할 수 있는 것은 우리들 자신이 만들어 낼 수 있는 감정뿐이다. -앙드레 지드

댓글 ( 0)

댓글 남기기

작성