역할 흐름

export default async function getListingById(params: IParams) {
  try {
    const { listingId } = params;
    const listing = await prisma.listing.findUnique({
      where: {
        id: listingId,
      },
      include: {
        user: true,
      },
    });

    if (!listing) {
      return null;
    }

    return {
      ...listing,
      createdAt: listing.createdAt.toISOString(),
      user: {
        ...listing.user,
        createdAt: listing.user.createdAt.toISOString(),
        updatedAt: listing.user.updatedAt.toISOString(),
        emailVerified: listing.user.emailVerified?.toISOString() || null,
      },
    };
  } catch (error: any) {
    throw new Error(error); 
  }
}

서버 컴포넌트인 Listing Page

// 서버컴포넌트에서도 다행히도 params에 접근할 수는 있다.
async function ListingPage({ params }: { params: IParams }) {
  // 서버 컴포넌트 이기 때문에 DB에 직접 조회해서 가져올 수 있음.
  const listing = await getListingById(params);
  const currentUser = await getCurrentUser();

  // listing이 없을때...
  if (!listing) {
    return (
      <ClientOnly>
        <EmptyState />
      </ClientOnly>
    );
  }

  return (
    <ClientOnly>
      <ListingClient listing={listing} currentUser={currentUser} />
    </ClientOnly>
  );
}

상세정보를 가져온후 화면에 렌더링 하는 과정