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 요소만 다시 렌더링하기 때문에 후속 페이지의 로드가 빠르다.
SEO 문제
구현한 웹 사이트가 검색 결과 상위에 노출되는 것이 필요하다면 SSR을 사용해서 웹 크롤러가 완성된 문서를 인식할 수 있게 해주는 것이 좋다.
초기 구동 속도 문제
모든 JavaScript가 다운로드 될 때까지 웹 사이트를 로드할 수 없기 때문에 이때 사용자는 빈 화면을 보게 된다. 사용자의 인터넷 속도가 빠르다면 큰 문제가 되지 않을 수 있지만, 사용자가 느린 인터넷 연결을 사용한다면 초기 로딩 시간이 길어져 사용자 경험에 부정적인 영향을 줄 수 있으므로 이러한 경우 SSR을 사용하는 것이 좋을 듯하다.
yarn start
스크립트를 실행하면 Next.js CLI 커맨드 중 하나인 next start
가 실행된다. next.js GitHub 레포지토리에서 해당 커맨드 실행 시 실행되는 코드를 확인할 수 있다. 따로 전달한 인자가 없고 에러가 발생하지 않아서 75번째 줄부터 확인했다.
startServer()
에서 리턴한 프로미스 객체 app
을 확인하기 위해 해당 함수가 위치한 파일을 찾아보았다.startServer()
는 서버를 생성하고 프로미스 객체를 리턴하는데, 에러가 발생하지 않았을 경우 50번째 줄이 실행된다.
여기에서 next()
를 통해 app을 만들어 이를 resolve하므로 next
를 찾아보았다. 파일을 확인해보니 next
는 createServer
라는 함수였다.
해당 파일에는 createServer()
함수가 2개 있는데, 아래에 있는 함수가 export 된다고 생각했다. 왜냐하면 첫 번째 createServer
는 클래스 내부에 있는 private
필드이므로 클래스 바깥에서 사용할 수 없을 것이고, 두 번째 createServer
처럼 NextServer
객체를 반환해야 이후에 .prepare()
메서드를 사용할 수 있기 때문이다.
정리해보면, next start
가 에러 없이 실행된 경우 우선 HTTP 서버를 생성한다. 그리고 listening 이벤트를 감지해서 NextServer
객체를 생성하고 해당 포트의 연결을 수신하는 HTTP 서버를 시작한다(..고 이해했다).