SSR
Server-Side Rendering
서버에서 HTML을 생성하여 전송하는 렌더링 방식. SEO에 유리. Next.js, Nuxt.js가 대표적.
Server-Side Rendering
서버에서 HTML을 생성하여 전송하는 렌더링 방식. SEO에 유리. Next.js, Nuxt.js가 대표적.
SSR(Server-Side Rendering)은 사용자가 페이지를 요청할 때마다 서버에서 HTML을 동적으로 생성하여 전송하는 렌더링 방식입니다. 클라이언트는 이미 콘텐츠가 포함된 완성된 HTML을 받기 때문에, 초기 로딩 시 화면이 빠르게 표시됩니다.
SSR의 가장 큰 장점은 SEO와 소셜 미디어 공유입니다. 검색 엔진 크롤러나 SNS 봇이 JavaScript 실행 없이도 페이지 콘텐츠를 읽을 수 있어, SPA의 SEO 문제를 해결합니다. 메타 태그도 동적으로 생성할 수 있습니다.
Next.js의 getServerSideProps, Nuxt의 asyncData, Remix의 loader 등이 SSR을 구현합니다. 서버에서 데이터를 가져와 HTML에 포함시킨 후, 클라이언트에서 Hydration을 통해 React/Vue 앱으로 활성화됩니다.
SSR은 서버 부하가 증가하고 TTFB(Time To First Byte)가 SSG보다 느립니다. 하지만 실시간 데이터가 필요하거나 사용자별 맞춤 콘텐츠를 제공해야 할 때 필수적인 방식입니다. Streaming SSR로 응답 시간을 개선할 수 있습니다.
// Next.js SSR with getServerSideProps
// pages/dashboard.tsx
import { GetServerSideProps } from 'next';
import { getServerSession } from 'next-auth';
import { authOptions } from './api/auth/[...nextauth]';
interface DashboardProps {
user: { name: string; email: string };
stats: { visitors: number; revenue: number };
}
// 매 요청마다 서버에서 실행
export const getServerSideProps: GetServerSideProps = async (context) => {
// 인증 확인
const session = await getServerSession(context.req, context.res, authOptions);
if (!session) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
// 실시간 데이터 페칭
const [user, stats] = await Promise.all([
fetch(`${process.env.API_URL}/user/${session.user.id}`).then(r => r.json()),
fetch(`${process.env.API_URL}/stats`, {
headers: { Authorization: `Bearer ${session.accessToken}` }
}).then(r => r.json())
]);
return {
props: {
user,
stats,
},
};
};
export default function Dashboard({ user, stats }: DashboardProps) {
return (
<div>
<h1>안녕하세요, {user.name}님</h1>
<div className="stats">
<div>방문자: {stats.visitors.toLocaleString()}</div>
<div>매출: ₩{stats.revenue.toLocaleString()}</div>
</div>
</div>
);
}
// Next.js App Router SSR
// app/dashboard/page.tsx
async function Dashboard() {
const session = await getServerSession();
const stats = await fetch('https://api.example.com/stats', {
cache: 'no-store' // SSR 강제
}).then(r => r.json());
return <DashboardClient stats={stats} />;
}
기술 미팅에서:
"대시보드 페이지는 SSR이 맞아요. 실시간 데이터에 인증도 필요하니까요. 근데 서버 부하 걱정되면 캐싱 레이어 추가하거나 stale-while-revalidate 헤더 설정하면 됩니다."
기술 면접에서:
"SSR의 단점과 해결 방법은요?" - "TTFB가 느려질 수 있는데, Streaming SSR로 점진적 렌더링하거나, Edge Runtime에서 실행해서 지연 시간을 줄일 수 있습니다."
코드 리뷰에서:
"getServerSideProps에서 5개 API 순차 호출하고 있네요. Promise.all로 병렬화하면 응답 시간 반 이상 줄일 수 있어요. 의존성 없는 요청은 동시에 보내세요."