반응형

📝Server Component (SSR)

서버에서 자바스크립트 파일을 읽어 HTML을 만든 후 클라이언트에게 전달한다 Next에서는 기본적으로 App Router에서 서버 사이드 렌더링을 적용시키고 있다 만약 명시적으로 표현하려면 “use server”를 상단에 적어주면 된다

 

📝동작과정

  1. 서버에서 자바스크립트를 읽고 HTML 생성
  2. 클라이언트에게 보내 Javascript(이벤트 핸들러)와 Hydration한다
    • 이부분이 좀 이상한 게 있는데 server component를 사용하면 useState, onClick등과 같은 클라이언트에서 사용하는 이벤트 핸들러 따위를 사용할 수가 없다 고로 Hydration이 불가능해보이는데 잘 모르겠다

 

📝이점

  • Data Fetch
    • 렌더링에 필요한 데이터를 가져오는데 걸리는 시간과 클라이언트가 수행하는 요청 양을 줄일 수 있다
  • 보안
    • 네트워크에 잡히지 않기 때문에 어떤 URL로 HTTP 통신했는지 보이지 않습니다
  • 캐싱 (deafult 캐싱 이용)
    • 서버에서 렌더링하면 결과를 캐시하기 때문에 비용이 절감 될 수 있습니다.
await fetch('<http://localhost:8080/next>', {cache: 'force-cache'});
(캐싱전) → [1] interval 51, [2] interval 57
(캐싱후) → [1] interval 2, [2] interval 2

 

  • 번들 크기
    • 서버에서 그려서 주기 때문에 클라이언트가 서버 구성 요소용 JavaScript를 다운로드, 구문 분석 및 실행할 필요가 없기 때문에 인터넷 속도가 느리거나 성능이 떨어지는 장치를 사용하는 사용자에게 유용
  • 스트리밍

 

📝서버 렌더링

정적, 동적, 스트리밍의 세 가지 하위 집합이 존재한다

 

  • 정적 렌더링
    • 정적 렌더링을 사용하면 경로는 빌드 시 렌더링되거나 데이터 재검증 후 백그라운드에서 렌더링
    • 정적 렌더링은 경로에 사용자에게 개인화되지 않은 데이터가 있고 정적 블로그 게시물이나 제품 페이지와 같이 빌드 시 알 수 있는 데이터가 있는 경우 유용하다
  • 동적 렌더링
    • 동적 렌더링은 경로에 사용자에게 맞춤화된 데이터가 있거나 쿠키나 URL의 검색 매개변수와 같이 요청 시에만 알 수 있는 정보가 있는 경우 유용하다
  • 스트리밍
    • 서버에서 알아서 청크사이즈로 분리 후에 병렬로 처리해준다

 

Next.js가 사용된 기능과 API를 기반으로 각 경로에 가장 적합한 렌더링 전략을 자동으로 선택하므로 정적 렌더링과 동적 렌더링 중에서 선택할 필요가 없습니다

 

📝Client Component (CSR)

클라이언트에서 받은 Javascript를 해석해 HTML을 렌더링하는 방식으로 “use client” 지시어를 명시해야 사용이 가능하다 해당 지시어를 사용해야 useState같은 훅과 이벤트 핸들링이 사용 가능하다

 

📝동작과정

  1. 서버에서 HTML을 렌더링할 수 있게 자바스크립트 번들링을 보낸다
  2. 자바스크립트를 읽어 클라이언트에서 웹 브라우저가 그리기 시작한다
    • use client라고 해도 React처럼 아예 안 그리는 수준이 아니라 어느정도 그릴 순 있는 건 다 그려서 나온다 (개발자 도구에서 네트워크의 HTML을 확인해보면 알 수 있다)
  3. 이벤트 핸들링따위와 연결 할 수 있게 Hydration을 한다

 

📝SSR / CSR 주의사항

  • page.tsx가 use client면 포함되어있는 컴포넌트들도 client side rendering을 한다 → console.log 사용시 서버에 찍히는지 콘솔창에 찍히는지로 판단 가능
    • page.tsx가 use client일 때 하위 컴포넌트 use clinet 선언 안 해도 Hook 사용 가능 (알아서 지정해주는 것 같음)
    • use client만 아니면 A컴포넌트는 서버렌더링 B컴포넌트는 클라이언트 렌더링 나눌 수 있다하지만 page가 use client의 경우 하위 컴포넌트가 서버 렌더링하면 왜인지 모르겠다만 엄청나게 data fetch를 요청한다
  • SSR과 CSR 어떤게 동작한 지 궁금할 시 개발자도구 네트워크를 보면 SSR의 경우 서버에서 데이터 Fetch를 하기 때문에 잡히지 않고 CSR의 경우 잡힌다
  • 번들 크기를 줄이기 위해서는 클라이언트와 서버쪽에서 부담을 잘 분배해야한다
  • layout은 서버 컴포넌트로 두고 사용자의 이벤트 핸들링 따위가 들어간 컴포넌트의 경우는 따로 클라이언트 컴포넌트로 정의한다
  • 서버 구성요소를 클라이언트 요소로 가져오기는 지원되지 않지만 꼭 되게 하려면 {children}으로 받을 수 있다
/** ClientComponent **/
'use client'
 
// You cannot import a Server Component into a Client Component.
import ServerComponent from './Server-Component'
 
export default function ClientComponent({
  children,
}: {
  children: React.ReactNode
}) {
  const [count, setCount] = useState(0)
 
  return (
    <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
 
      <ServerComponent />
    </>
  )
}

/** ClientComponent **/
'use client'
 
import { useState } from 'react'
 
export default function ClientComponent({
  children,
}: {
  children: React.ReactNode
}) {
  const [count, setCount] = useState(0)
 
  return (
    <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
      {children}
    </>
  )
}

/** Page.tsx **/

import ClientComponent from './client-component'
import ServerComponent from './server-component'
 
// Pages in Next.js are Server Components by default
export default function Page() {
  return (
    <ClientComponent>
      <ServerComponent />
    </ClientComponent>
  )
}
  • 어떤 구성 요소를 사용해야할까? (서버 구성요소 / 클라이언트 구성요소)

반응형