Skip to content

페이지별 렌더링

렌더링 방식

  1. static
    • 빌드 타임에 HTML 생성
    • 데이터 페칭 없음
    • 정적 HTML
  2. SSG
    • 빌드 타임에 HTML 생성
    • getStaticProps로 데이터 페칭
    • 정적 HTML + JSON
  3. ISR
    • 빌드 타임에 HTML 생성 + 주기적으로 재생성
    • getStaticProps + revalidate
    • 정적 HTML + JSON + 백그라운드 업데이트
  4. SSR
    • 런타임에 서버에서 HTML 생성
    • getServerSideProps로 데이터 페칭
    • 요청할 때마다 서버에서 렌더링
  5. CSR
    • 클라이언트에서 JS로 렌더링
    • useEffect, SWR, React Query 등으로 데이터 페칭
    • 빈 HTML + JS 번들

현재 페이지별 렌더링 구조 및 의문점

  • article: SSR

    • 검색 엔진에서 article 내용을 크롤링해가야 되고
    • 매번 최신 데이터를 보여줘야 하니 SSR
  • profile: SSR

    • 사용자별로 프로필도 SEO 중요하고
    • 내 게시글과 좋아하는 게시글의 최신 데이터를 보여줘야 하니 SSR
  • editor/new: static

  • user/login: static

  • user/register: static

    • 위 세가지 페이지는 단순히 폼만 존재하니 static
  • editor/[slug]: SSR

  • user/settings: SSR

    • 인증된 사용자에서만 데이터를 입력 받으니 SEO는 필요 없는데 왜 SSR을 쓴걸까?
    • 그 전에 있던 데이터가 입력되어있어야 돼서? 단순히 렌더링 속도가 빨라서?
    • 그럴거면 그냥 CSR을 써도 괜찮지 않을까?
      대체 SSR과 CSR의 렌더링 속도는 얼만큼 차이가 나는걸까?
      궁금해져서 editor/[slug] 페이지를 SSR(getServerSideProps)과
      CSR(useSWR)로 했을 때의 performance를 측정해봤다.
      Pasted image 20250612163858
    • 어떤 환경이든간에 getServerSideProps로 서버에서 데이터를 받아와서 렌더링 하는게 더 빠르긴하다.
    • 근데 요청이 많으면 서버에 부하가 가지 않을까란 생각에 CSR을 쓰는게 좋지 않을까 했는데
    • 서버에 부하가 안 가려고 csr을 쓴다기엔 네트워크 환경이 좋지 못한 브라우저는 어떡하지? 라는 생각이 들어서 ㅋㅋㅋ 잠깐 네트워크 환경에 따라 렌더링을 다르게 하는건 어떨까 했지만
    • 결론적으로 페이지 로드와 동시에 폼이 채워진채로 등장하는 SSR을 사용하는게 맞다고 판단했다.
  • 관련 자료

getInitialProps과 getServerSideProps

서버에서 데이터를 페칭해올 때 원본 레포에선 다 getInitialProps 함수를 썼다.

찾아보니 next.js v9.3 이전 환경에서 서버 사이드 렌더링을 하려면
getInitialProps 함수밖에 못 썼다고 한다.

근데 지금은 보통 SSR을 하려면 getServerSideProps를 쓰지 않는가.
둘은 어떤 차이가 있는걸까?

  • getInitialProps

    • getInitialProps는 페이지를 처음 로드할 땐 서버에서 실행되지만,
      next/link나 next/router로 클라이언트에서 페이지를 이동할 땐 클라이언트에서 실행된다.
      그래서 서버랑 클라이언트 둘 다 실행될 수 있는 함수다.
  • getServerSideProps

    • 반면에 getServerSideProps는 오직 서버에서만 실행된다.
      페이지를 요청할 때마다 서버에서 데이터를 가져오고,
      클라이언트에서 페이지를 이동해도
      Next.js가 백그라운드에서 서버에 요청해 JSON 데이터를 받아온다.
  • 그래서 뭘 쓰는게 좋을까?

    • 무조건 서버사이드를 하려면 getServerSideProps를 써야된다!!가 아니라,
      각각 어떨때 쓰는게 비교적 좋은걸까?
    • getInitialProps는 처음엔 서버에서 실행되니까 데이터가 불러와진 이후부터는
      헤더든 사용자가 빠르게 이동할 수 있을거다.
    • 근데 getInitialProps는 클라이언트에서도 실행되니까
      클라이언트에 api key나 db가 노출 될 가능성이 있다.
    • 그래서 보안이 중요한 페이지에는 getServerSideProps를 쓰는게 좋을거 같다.
    • 결론적으로 아래와 같은 결정을 내렸다.
      • article: getServerSideProps (article은 SEO가 중요하니까)
      • profile: getInitialProps (탭바로 이동하고 있으니까 처음만 SSR)
      • editor/[slug]: getServerSideProps (글쓴이인지 확인해야되니까 보안 중요)
      • user/settings: getServerSideProps (당연히 보안 중요)
  • 관련 자료

useSWR로 갖고오기 VS useEffect로 갖고오기

앞서 editor/[slug]user/settings에서 CSR과 SSR을 비교할 때
SSR 코드를 CSR로 바꾸는데 두 가지 방법이 생각났다.
첫 번째는 useEffect를 쓰는 것이고, 두 번째는 useSWR을 쓰는 것이다.

useEffect는 데이터 페칭 로직을 완전히 커스터마이징할 수 있어서
복잡한 비즈니스 로직이나 특수한 요구사항이 있을 때 유연하다.

또한 정말로 한 번만 데이터를 가져오면 되는 상황에서는
useSWR의 백그라운드 갱신이나 캐싱 기능이 오히려 불필요한 오버헤드가 될 수 있다.
특히 정적인 데이터나 설정값을 가져올 때는 useEffect가 더 적절하다.

하지만 useEffect는 모든 것을 직접 구현해야 한다는 부담이 있다.
또한 같은 데이터를 여러 컴포넌트에서 사용할 때
각각 별도로 API를 호출하게 되어 네트워크 요청이 중복된다.
전역 상태 관리를 위해서는 Context API나 별도의 상태 관리 라이브러리를 추가로 도입해야 한다.

반면 useSWR은 데이터 페칭에 특화된 라이브러리답게
캐싱, 백그라운드 갱신, 에러 처리, 로딩 상태 관리를 자동으로 해준다.
같은 키로 여러 컴포넌트에서 호출해도 실제로는 한 번만 API를 호출한다.
하지만 복잡한 데이터 변환이나 특수한 에러 처리가 필요한 경우에는 오히려 제약이 될 수 있다.