jhpka's blog

[Next.js] 렌더링 방식 선택

Admin User

렌더링 방식 비교

방식실행 시점속도최신성비용용도
SSG빌드 타임⚡⚡⚡낮음정적 콘텐츠
ISR빌드 + 주기적⚡⚡중간블로그, 제품 목록
SSR매 요청높음실시간 데이터
SSR + 캐싱매 요청 (캐시)⚡⚡중간사용자별 데이터
CSR클라이언트높음-상태, 인터랙션

Server Component vs Client Component

tsx
// Server Component (기본) - SSG/SSR
async function ProfileSection() {
  const data = await prisma.user.findFirst()
  return <div>{data.name}</div>
}

// Client Component - CSR
'use client'
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

ISR (Incremental Static Regeneration)

정적 페이지를 빌드 후에도 일정 시간마다 자동으로 재생성

tsx
export const revalidate = 3600 // 1시간마다 재생성

export default async function PostPage({ params }) {
  const post = await prisma.post.findUnique({
    where: { slug: params.slug }
  })
  return <MarkdownRenderer content={post.content} />
}

ISR 옵션:

  • revalidate = 3600 - 1시간마다 재생성
  • revalidate = false - ISR 비활성화 (순수 SSG)
  • revalidate = 0 - 매 요청마다 (SSR과 유사)

SSR + 캐싱

매 요청마다 렌더링하지만, 캐시 유효 기간 내 동일 요청은 재사용

text
첫 번째 요청: 요청 → DB 쿼리 → 렌더링 → 캐시 저장 (1초)
캐시 내 요청: 요청 → 캐시 반환 (1ms) ⚡
캐시 만료 후: 요청 → DB 쿼리 → 렌더링 → 캐시 갱신 (1초)
tsx
export const revalidate = 60 // 60초

async function UserDashboard({ userId }) {
  const data = await prisma.user.findUnique({
    where: { id: userId }
  })
  return <div>{data.name}</div>
}

컴포넌트 단위 선택

Next.js는 페이지/컴포넌트 단위로 렌더링 방식 선택 가능

tsx
// 현재 프로젝트 구조
CollapsibleSidebar (Server Component - SSR)
  └─ SidebarContent (Client Component - CSR)
      └─ profile data는 서버에서 전달

// 최적 패턴
async function Page() {
  const data = await fetchData()

  return (
    <div>
      <StaticContent data={data} />      {/* Server */}
      <InteractiveWidget data={data} />  {/* Client */}
    </div>
  )
}

현재 프로젝트 추천 전략

페이지/컴포넌트추천 방식이유
블로그 글SSG (ISR)글은 자주 안 바뀜
글 목록SSG (ISR)새 글 시간당 몇 개
프로필 페이지SSG프로필 거의 안 바뀜
About 페이지SSG정적 콘텐츠
사용자 대시보드SSR + 캐싱사용자마다 다름
검색 결과SSR매번 다른 결과
상호작용 요소CSR상태, 이벤트 핸들러

핵심 정리

프로젝트 개선사항

✅ 프로필 이미지 SSR로 전환 ✅ 부드러운 UI 트랜지션 추가 ✅ 마크다운 인라인 코드 렌더링 수정 ✅ Server/Client Component 최적 분리

배운 개념

  • Next.js App Router의 Server/Client Component 분리
  • SSG, ISR, SSR의 차이와 선택 기준
  • Tailwind CSS의 @apply와 transition
  • 마크다운 렌더러 커스터마이징

Best Practice

  1. 기본은 Server Component - 필요할 때만 CSR 적용
  2. 프로필 데이터는 SSR - 모든 페이지에서 동일하므로 최상단에서 fetch
  3. 상태 관리는 Client Component - localStorage, useState 등
  4. ISR 활용 - 블로그 글은 시간 주기로 재생성하여 성능과 최신성 모두 확보
댓글을 불러오는 중...