INFCON 2023 - SSR의 기쁨과 슬픔: 렌더링의 변화의 흐름을 통해 알아보는 SSR과 Streaming SSR

dev_hyun·2023년 9월 18일
2

INFCON 2023

목록 보기
2/2

참고자료: SSR의 기쁨과 슬픔: 렌더링의 변화의 흐름을 통해 알아보는 SSR과 Streaming SSR

1. Rendering의 변천사

Static Web Site
웹 서버에서 정적인 HTML 파일을 중심을 제공
URL 을 통해 해당 디렉토리에 있는 파일을 내려주는 방식

Common Gateway Interface
정적인 HTML 제공이 아닌 외부 프로그램을 호출한 결과를 제공

Server Side Template
웹 서버에서 정적인 HTML을 제공하는 게 아니라 Server Application에서 로직에 따라 HTML을 생성해서 내려주는 방식

문제점

  • UI가 복잡하지 않고 단순했을 때에는 충분했다.
    - 기능 구현이 server단과 클라이언트 단에 모두 구현이 되어야 한다.
  • Server에서 API 나 데이터베이스 query에서 시간이 오래걸리면 화면이 늦게 노출된다.

Client Side Rendering
모든 랜더링을 클라이언트에서 처리하는 방식
서버에서는 API만 데이터로 내려주고 view로직은 모두 클라이언트에 있다.
개념적으로는 Static Web Site와 거의 비슷하다.
별도의 서버가 없이 CDN으로 배포를 하기 때문에 배포 속도도 빠르고 관리해야 할 부분이 적어진다.

  • 트래픽 대응을 할 필요성이 없다(CDN에서 처리)
  • URL에 따른 라우팅 처리도 클라이언트 단에서 처리가 가능(SPA)


문제점

  • 어느 페이지에 접속을 하더라도 하나의 index.html만을 바라보기 때문에 meta태그가 모두 같은 문제가 발생
  • 그렇기에 크롤러 입장에서는 client에서 HTML을 만들기 직전의 HTML만 받아올 수 있다.
  • 동적인 meta태그들을 만들어 줄 수가 없다.
  • 성능적인 측면에서는 body태그가 비어있다가 js에 의해 채워지는데 모바일 웹뷰에서는 매우 느리게 동작할 수 있다.
  • 광고 매체 스크립트 등에 의해서 메모리 누수가 취약하다(새로고침이 되지 않기 때문에)

Server Side Rendering
node.js의 발전으로 Client와 Server에서 같은 언어를 쓸 수 있게 되면서 다시 Rendering 의 책임을 Server에서 처리하려고 한다.
같은 언어를 Client와 Server에서 쓸 수 있다는 점 때문에 거의 대부분의 뷰 로직을 Client와 Server에서 공유할 수 있다.
Server에서 HTML String을 생성하는 측면에서는 Server Side Template 기반의 Rendering과 유사한 측면이 있다.

단점

  • 더 이상 serverless가 아니게 되므로 server 관리 책임이 생김 (프론트에서 서버관리가 필요)
  • 관리해야하는 server가 있기 때문에 트래픽이 몰릴 경우 스케일 업, 스케일 아웃 등의 추가 작업이 필요하다.
  • docker 등으로 말아서 배포할 경우 빌드 및 배포 시간이 CSR 대비해서 길어진다..
  • 세팅이 복잡하다.
    - 이는 next.js, remix, vite-plugin-ssr 등이 등장하면서 조금 쉬워지긴 했다.
  • CSR 경험만 있던 사람들에게는 다소 개념이 복잡하게 느껴질 수 있다.

Streaming SSR

기존의 SSR의 단점을 보완하기 위한 방법
Streaming SSR이란 가장 빠르게 그릴 수 있는 부분을 먼저 랜더링을 진행하고 이후는 Node.js의 스트림을 이용해 점진적으로 렌더링 하는 방식이다.
renderToPipeableStream 함수를 이용해 <Suspense> 태그를 기준으로 렌더링을 진행한다

기본 개념

Streaming SSR에서는 Shell, Suspense로 경계 지어진 컴포넌트를 기준으로 렌더링을 처리
Suspense로 감싸진 바깥 영역을 Shell이라고 부른다.(GNB 등 data fetching이 필요없는 부분)

  • shell이 먼저 렌더링 된 후에 Suspense 부분을 렌더링 하는

적용 과정

적용 과정은 해당 pdf자료를 보는게 더 좋을 것 같다.



이때 javascript yield 키워드가 나오는데 오랜만에 보는 것 같고 잘 사용해본적이 없는데 그래서 잠깐 설명한다.
yield는 마치 return처럼 동작하고 정해진 구간을 순서대로 실행한다.
'function*'로 만든 함수를 생성기(generator) 라고 부르고 이는 화살표 함수를 만들 수 없다.

function* generator() {
  console.log('generator started...');
  let value = 1;
  while (value < 4) {
    yield value++;
  }
  console.log('generator finished...');
}

// case 1
for (let value of generator()) {
  console.log(value);
}
// === 실행 결과 ===
// generator started...
// 1
// 2
// 3
// generator finished...


// case 2
let iterator = generator();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

여기서는 chunck들을 차례대로 실행하는 것이다.

SSR을 끝낸뒤 겪은 문제

1. Docker 기반으로 배포를 하면서 배포하는 도중에 404 에러가 발생했던 문제
도커 이미지를 만들면서 build시 생성되었던 번들 파일이 배포가 진행되고 어떤 pod는 이전 버전의 번들을 가지고 있고, 다른 pod는 새버전의 번들 파일을 가지게 되어서 생겼던 문제

  • build를 docker로 진행해서 매번 이미지를 만들때마다 번들 파일은 날아가서 404에러가 많이 발생했다고 한다.

해결법

  • 번들 파일들을 모두 s3에 올리고, vite 내에서도 번들을 불러오는 건 cloudfront + s3를 통해서 불러오도록 수정
  • 이렇게 되면 번들이 계속해서 누적된 상태로 s3에 올라가 있어서 404 에러를 방지할 수 있다.

2. 두번 빌드해야 하던 문제
빌드 시점에 들어가야하는 환경변수들이 있다.
도커 이미지 생성 시에도 해당 환경변수들이 있어야하는데 만약 prod와 stage버전 두개를 배포를 따로 가야한다면 이미지를 두개 만들거나 build를 각각 가지고 있어야 한다.

해결법

  • 빌드 타임 환경변수를 런타임으로 변경
  • SSR이므로 서버에서 런타임 환경변수를 통해 서버에서 렌더링 될때 변수로 관리하여 넣어줌



자주 쓰이는 ssr프레임워크인 next.js를 사용하지 않고 직접 구축했다는게 대단한 것 같다.
next.js를 사용할때도 힘들었었던 경험들이 있었는데 능력자이신 것 같다

profile
하다보면 안되는 것이 없다고 생각하는 3년차 프론트엔드 개발자입니다.

0개의 댓글