Server Side Rendering의 약자로
서버쪽에서 렌더링 준비를 끝마친 상태로 클라이언트에 전달하는 방식이다.
가장 중요한 것은 서버에서 렌더 될 준비를 끝마친 상태로 HTML 응답을 브라우저(클라이언트)에 보내는 것입니다. 그 의미가 바로 렌더링이라는 의미입니다.
브라우저의 렌더링은 HTML, CSS, JavaScript 파일을 받아와 이를 읽고 파싱해서 실행한 결과물로 화면에 그려내는 과정이지만 서버 사이드에서의 렌더링이란 HTML 파일 내에 내용이 있느냐 없느냐입니다. 내용이 있다면, 렌더링이 된 것입니다.
2,3 단계에서 HTML에 대한 렌더링 준비는 완료된 상태이므로 클라이언트는 화면 컨텐츠 자체는 확인 할 수 있지만 상호작용은 불가능한 상태이다.
이후 클라이언트가 자바스크립트를 다운로드 받고 브라우저가 Javscript 프레임워크를 실행하여 성공적으로 컴파일하면 사용자 조작이 실행되고 이제 웹 페이지는 상호작용 가능해진다.
다음과 같이 더 간단히 나타낼 수 있는데 중요한 포인트는
서버에서 이미 '렌더 가능한' 상태로 클라이언트에 전달되기 때문에, JS가 다운로드 되는 동안 사용자는 무언가를 보고 있을 수 있는점 이다.
2단계 - 보기 가능, 4단계 - 상호작용 가능
Client Side Rendering의 약자로, 말 그대로 SSR과 달리 렌더링이 클라이언트 쪽에서 일어납니다. 서버는 요청을 받으면 클라이언트에 HTML과 JS를 보내주고, 클라이언트는 그것을 받아 렌더링을 시작합니다.
CSR은 서버가 HTML 파일을 줄 때, 렌더가 준비가 된 파일이 아니기 때문에
SSR과 다르게 먼저 컨텐츠를 볼 수 없습니다. 즉, HTML 파일 안에는 아무런 내용이 없고 그 내용은 JS 파일을 받아 실행을 시켜야 확인 할 수 있습니다. 더 간단히 정리된 이미지를 보면 다음과 같다.
예를 들어 vue나 react를 보면 index.html 파일의 바디 태그 안에 특별한 내용이 없는 경우를 많이 봤을텐데 이후에 index.html에 연결된 js들이 다운되고 실행되면 index.js에서 화면을 더 만들어주거나 다른 화면을 붙여주는 등 화면에 렌더링하게 됩니다.
로딩시간은 첫 페이지를 로딩하는 것과 나머지를 로딩하는 것 두가지로 볼 수 있는데,
첫 페이지 로딩 시간
CSR의 경우 HTML, CSS와 모든 스크립트들을 한 번에 불러옵니다. 반면 SSR은 필요한 부분의 HTML과 스크립트만 불러오게 됩니다. 따라서 SSR이 더 빠릅니다.
나머지 페이지 로딩 시간
첫 페이지를 로딩한 후, 사이트의 다른 곳으로 이동하는 식의 동작을 가정해봅시다. CSR은 이미 첫 페이지 로딩할 때 나머지 부분을 구성하는 코드를 받아왔으므로 빠릅니다. 반면, SSR은 첫 페이지를 로딩한 과정을 정확하게 다시 실행합니다. 그러므로 CSR이 SSR보다 빠릅니다.
검색 엔진은 자동화된 로봇인 '크롤러'로 웹 사이트를 읽어들입니다. CSR은 JS를 실행시켜 동적으로 컨텐츠가 생성되기 때문에 JS가 실행되어야 metadata가 바뀌었습니다. 이전 크롤러는 JS를 실행시키지 않았기 때문에 SEO 최적화가 필수적이었지만 구글이 이러한 이유로 JS 파일을 해석해서 내용을 찾아주기 시작했기 때문에 그 트렌드를 바꾸고 있다고 합니다.
결론은 SSR이 서버 사이드에서 컴파일되어 클라이언트로 넘어오기 때문에 크롤러에 대응하기 용이합니다.
매번 서버에 요청을 하기 때문에 SSR이 서버 자원을 더 많이 사용합니다.
전체적인 구조는 도메인 네임을 통해 NginX 웹서버에 접근하면 NginX는 EC2 내부의 다른 포트에서 동작하고 있는 express 서버에 접근합니다. express 서버는 일부가 완성된 html 문서를 NginX를 한번 거쳐서 express와 같은 WAS와 연결하는 방식을 reverse proxy라고 합니다. reverse proxy는 외부 사용자들에게 WAS가 어떤 포트에서 동작하는지 숨겨 보안적으로 강화하기 위한 목적이 있습니다.
이러한 흐름으로 사용자는 어느 정도 화면이 만들어진 html 문서를 처음 응답으로 받아볼 수가 있는데, CSR보다는 훨씬 빠른 화면 로딩 속도를 보여줍니다.
app.get('/', (req, res) => {
const indexFile = path.resolve(path.join(__dirname, '../client/index.html'));
const app = ReactDOMServer.renderToString(<App />);
fs.readFile(indexFile, 'utf8', (err, data) => {
if (err) {
console.error('Something went wrong:', err);
return res.status(500).send('Oops, better luck next time!');
}
const result = data.replace('<div id="root"></div>', `<div id="root">${app}</div>`)
return res.send(result);
});
}
리액트를 사용한다면 개발자는 express.js에서 대략 위와 같은 코드를 작성하는데 ReactDOMServer.renderToString을 사용한다는 점을 빼면 CSR에서 렌더링하던 방식과 크게 다른 것은 없습니다.
renderToString은 리액트가 컴포넌트 구조를 파악하고 HTML string으로 바꿔주는 동작을 합니다.
작업을 마치면 개발자 도구에서 html을 받아온 결과가 일부 완성된 것을 확인할 수 있습니다. 첫 html을 받아온 이 시점 이후부터는 더는 SSR이 아닌 CSR로 바뀝니다.
일단 CSR + SSR 환경이므로 첫 html을 받아온 후에도 CSR 환경을 동작시키기 위한 JavaScript를 불러오는 script 태그가 여전히 들어가있는 상태입니다. 그래서 html을 받아온 후 JS 파일을 가져와 CSR로 동작시키기 때문에 SSR에서 CSR로의 변경이 가능합니다.
참고사이트
SSR vs CSR
SSR과 CSR의 차이