Client-Side Rendering (CSR)
클라이언트 측 렌더링은 웹 페이지의 초기 요청 시 서버가 최소한의 HTML, CSS 및 JavaScript만 제공하고, 그 이후에 JavaScript가 실행되어 동적으로 콘텐츠를 가져오고 렌더링하는 방식이다.
CSR는 초기 로딩 속도가 빠르며, 클라이언트에서 캐싱이 용이하여 사용자 경험을 개선할 수 있습니다. 그러나 검색 엔진 최적화(SEO)에는 취약하다.
Server-Side Rendering (SSR)
서버 측 렌더링은 서버에서 페이지의 초기 렌더링을 수행하고 완전한 HTML을 클라이언트에 전송하는 방식이다. 서버에서는 요청을 받으면 데이터를 가져와 페이지의 HTML을 생성하여 클라이언트에게 보내준다.
SSR는 검색 엔진 최적화(SEO)에 유리하며 초기 렌더링 속도가 빠르고, 첫 화면이 더 빨리 보여지는 등의 장점이 있다. 그러나 서버 부하가 높을 수 있고, 클라이언트 측에서의 렌더링이 필요한 경우 추가적인 로직이 필요할 수 있다.
Server Component
Server Component는 서버 측에서 렌더링되는 컴포넌트로 애플리케이션을 렌더링할 때 서버에서 실행되고 완전한 HTML로 클라이언트에 제공된다. 이는 서버 측에서만 실행되고 클라이언트에는 결과적으로 일반적인 HTML이 전달되어 사용자에게 더 빠른 첫 페이지 로드를 제공한다.
Next.js에서는 /app
디렉터리 내부에 컴포넌트를 만들면 기본적으로 Server Component가 된다. 따라서 Server Component로 만들기 위해 별도의 작업은 필요 없다.
Server Component 서버 측에서 렌더링 되므로, onClick
과 같은 Event Listener나 useState
와 같은 React Hooks은 브라우저 환경의 코드로 사용할 수 없다.
Server Component에 대한 Next.js 공식 문서
Client Component
Client Component 서버에서는 생성되지 않고, 클라이언트에서 JavaScript를 실행하여 렌더링된다. 이는 사용자와 상호 작용하거나 클라이언트 측에서 동적으로 업데이트가 필요한 컴포넌트에 사용된다.
Client Component를 정의하기 위해서는 컴포넌트 파일 최상단에 use client
를 추가해야 한다.
Client Component는 클라이언트(브라우저) 측에서 렌더링 되므로, onClick
과 같은 Event Listener나 useState
와 같은 React Hooks 등 브라우저 환경의 코드로 사용할 수 있다.
Client Component에 대한 Next.js 공식 문서
usePathname는 현재 페이지의 경로를 가져오는 데 사용된다. usePathname는 현재 페이지의 경로를 문자열로 반환한다. 이는 Next.js 애플리케이션 내에서 어디서든 사용할 수 있으며, 현재 페이지의 경로를 동적으로 액세스해야 하는 경우 유용하다.
import { usePathname } from "next/navigation";
const path = usePathname();
<Link href="/meals" className={path.startsWith("/meals") ? classes.active : undefined}>Browse Meals</Link>
<Link href="/community" className={path === "/community" ? classes.active : undefined}>Foodies Community</Link>
페이지를 이동할 때마다 경로가 업데이트되며, 해당 경로를 실시간으로 가져올 수 있다.
Client Component를 효율적으로 활용하기 위해서는 대부분의 컴포넌트가 서버 컴포넌트로 유지되고, 필요한 컴포넌트만 클라이언트 컴포넌트로 변환하는 것이 좋다. 대부분의 컴포넌트에서 서버 컴포넌트의 이점을 잃지 않도록 하려면 가능한 컴포넌트 트리 가장 아래로 내려가서 useClient
를 추가하는 것이 좋다.
<NavLink href="/meals">Browse Meals</NavLink>
<NavLink href="/community">Foodies Community</NavLink>
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import classes from "./nav-link.module.css";
const NavLink = ({ href, children }) => {
const path = usePathname();
return (
<Link
href={href}
className={
path.startsWith(href)
? `${classes.link} ${classes.active}`
: classes.link
}
>
{children}
</Link>
);
};
export default NavLink;
이처럼 main-header
컴포넌트에서 usePathname
을 통해 현재 페이지 경로를 가져와야 하는 부분은 nav-link
컴포넌트로 분리하여 해당 컴포넌트에서 useClient
를 추가해주는 것이 좋다