기본적인 페이지 구조

// /app/layout.tsx

import './globals.css';
import type { Metadata } from 'next';

import { Urbanist } from 'next/font/google';

import Footer from '@/components/Footer';
import NavBar from '@/components/NavBar';

const font = Urbanist({ subsets: ['latin'] });

export const metadata: Metadata = {
  title: 'Store',
  description: 'Store',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang='en'>
      <body className={font.className}>
        <NavBar />
        {children}
        <Footer />
      </body>
    </html>
  );
}

NavBar에서 admin의 카테고리 fetching

//actions/get-categories.ts

import { Category } from '@/types';

const URL = `${process.env.NEXT_PUBLIC_API_URL}/categories`;

const getCategories = async (): Promise<Category[]> => {
  const res = await fetch(URL);

  return res.json();
};

export default getCategories;
import Container from '@/components/ui/container';
import Link from 'next/link';
import MainNav from '@/components/MainNav';
import getCategories from '@/actions/get-categories';

// 캐시 하지 않겠다.
export const revalidate = 0;

export default async function NavBar() {
  const categories = await getCategories();

  return (
    <div className='border-b'>
      <Container>
        <div className='relative px-4 sm:px-6 lg:px-8 flex h-16 items-center'>
          <Link href='/' className='ml-4 flex lg:ml-0 gap-x-2'>
            <p className='font-bold text-xl'>STORE</p>
          </Link>
          <MainNav data={categories} />
        </div>
      </Container>
    </div>
  );
}

MainNav는 카테고리를 받아서 Link 컴포넌트로 렌더링

export default function MainNav({ data }: MainNavProps) {
  const pathname = usePathname();
  const routes = data.map((route) => ({
    href: `/category/${route.id}`,
    label: route.name,
    active: pathname === `/category/${route.id}`,
  }));
  return (
    <nav className='mx-2 flex items-center space-x-4 lg:space-x-6'>
      {routes.map((route) => (
        <Link
          key={route.href}
          href={route.href}
          className={cn(
            'text-sm font-medium transition-colors hover:text-black',
            route.active ? 'text-black' : 'text-neutral-500'
          )}
        >
          {route.label}
        </Link>
      ))}
    </nav>
  );
}