원티드 프리온보딩 챌린지 10월(CSR / SSR with Next.js) 사전 과제

wonyu·2022년 9월 27일
0

CSR이란 무엇인가?

CSR: Client-side Rendering

클라이언트 측(브라우저)에서 화면을 구성하는 것이다.
최초 요청 시에 데이터를 제외한 HTML, CSS, JavaScript 등의 리소스를 응답 받고, 이후에는 클라이언트에서 필요한 데이터만 요청해서 JavaScript로 DOM을 렌더링한다.

CSR에 대한 간략한 설명으로는 이 과정을 이해하기 어려웠다. 따라서 렌더링 할 때 CSR 방식을 사용하는 SPA의 구현 과정을 생각해보면 좀 더 이해하기 쉬우리라 생각했다.

SPA (Single Page Application)은 단일 페이지로 구성된 웹 애플리케이션이다. SPA를 구현할 때는 하나의 HTML 파일(ex. index.html)을 먼저 생성하는데, 이 파일은 데이터가 들어있지 않은 빈 파일이며, 이 파일의 body에 root div를 만든다. 그리고 JavaScript 파일을 생성한다. JavaScript를 이용해서 이 root 위치에 페이지와 컴포넌트들을 렌더링하고 이벤트 리스너를 달거나 화면을 업데이트 해줄 수 있다. 이러한 방식으로 브라우저에서 직접 렌더링을 하게 되는 것이다.

다시 CSR로 돌아와서, JavaScript까지 읽은 후에 화면을 그리는 것까지 마쳐야 사용자가 컨텐츠를 볼 수 있기 때문에 초기 구동 속도는 SSR에 비해 느리다. (SSR에서는 서버에서 렌더링 된 HTML을 반환하면 클라이언트 측에서는 이를 다운로드하여 바로 사용자에게 보여준다.) 한 번 전체 페이지를 로딩한 이후에는 사용자가 다른 경로를 요청하더라도 페이지를 새로고침해서 다시 받아오지 않고 필요한 DOM 요소만 다시 렌더링하기 때문에 후속 페이지의 로드가 빠르다.

CSR의 장단점

장점

  • 서버와 클라이언트 간 트래픽 감소
    • 페이지를 이동할 때마다 서버에 새 페이지를 모두 요청하는 것이 아니라 JavaScript를 사용하여 필요한 부분만 요청하므로 매번 모든 리소스를 주고 받지 않아도 된다. 따라서 서버-클라이언트 간 트래픽이 감소하며 속도가 빠르다.
  • 사용자 경험 향상
    • CSR을 사용하면 사용자의 행동에 따라 필요한 부분만 로드하기 때문에 SSR에 비해 빠른 인터랙션이 가능하다.

단점

  • SSR에 비해 초기 구동 속도가 느림
    • SSR은 이미 서버에서 렌더링된 HTML을 클라이언트 측에 전달한다. 그리고 JavaScript 파일이 아직 불러와지지 않았어도 사용자는 콘텐츠를 볼 수 있다. 하지만 CSR은 HTML, CSS, JavaScript와 다른 리소스들을 다운로드 한 뒤에 브라우저에서 렌더링을 하기 때문에 초기 구동 속도가 SSR에 비해 느리다.
  • SEO(검색 엔진 최적화)에 어려움이 있음
    • 최초 문서에는 데이터가 존재하지 않고, 데이터가 들어있는 문서를 보여주려면 JavaScript 파일을 실행해야 한다. 하지만 대부분의 웹 크롤러 봇은 JavaScript 파일을 실행하지 못하기 때문에 빈 페이지로 인식하게 된다.

SPA로 구성된 웹 앱에서 SSR이 필요한 이유

  1. SEO 문제
    구현한 웹 사이트가 검색 결과 상위에 노출되는 것이 필요하다면 SSR을 사용해서 웹 크롤러가 완성된 문서를 인식할 수 있게 해주는 것이 좋다.

  2. 초기 구동 속도 문제
    모든 JavaScript가 다운로드 될 때까지 웹 사이트를 로드할 수 없기 때문에 이때 사용자는 빈 화면을 보게 된다. 사용자의 인터넷 속도가 빠르다면 큰 문제가 되지 않을 수 있지만, 사용자가 느린 인터넷 연결을 사용한다면 초기 로딩 시간이 길어져 사용자 경험에 부정적인 영향을 줄 수 있으므로 이러한 경우 SSR을 사용하는 것이 좋을 듯하다.

Next.js 프로젝트 세팅 후 yarn start 스크립트를 실행했을 때 실행되는 코드에 대한 설명

yarn start 스크립트를 실행하면 Next.js CLI 커맨드 중 하나인 next start 가 실행된다. next.js GitHub 레포지토리에서 해당 커맨드 실행 시 실행되는 코드를 확인할 수 있다. 따로 전달한 인자가 없고 에러가 발생하지 않아서 75번째 줄부터 확인했다.

startServer()에서 리턴한 프로미스 객체 app을 확인하기 위해 해당 함수가 위치한 파일을 찾아보았다.startServer()는 서버를 생성하고 프로미스 객체를 리턴하는데, 에러가 발생하지 않았을 경우 50번째 줄이 실행된다.

여기에서 next()를 통해 app을 만들어 이를 resolve하므로 next를 찾아보았다. 파일을 확인해보니 nextcreateServer 라는 함수였다.

해당 파일에는 createServer() 함수가 2개 있는데, 아래에 있는 함수가 export 된다고 생각했다. 왜냐하면 첫 번째 createServer는 클래스 내부에 있는 private 필드이므로 클래스 바깥에서 사용할 수 없을 것이고, 두 번째 createServer처럼 NextServer 객체를 반환해야 이후에 .prepare() 메서드를 사용할 수 있기 때문이다.


정리해보면, next start가 에러 없이 실행된 경우 우선 HTTP 서버를 생성한다. 그리고 listening 이벤트를 감지해서 NextServer 객체를 생성하고 해당 포트의 연결을 수신하는 HTTP 서버를 시작한다(..고 이해했다).


0개의 댓글