Next.JS 중요 개념을 정리해보자! SSR & ServerComponent

woong·2024년 3월 20일
1
post-thumbnail

내가 Next.js를 공부하며 배운 내용을 최대한 이해하기 쉽도록 정리하려고 한다.

부족한 제가 잘못 정리한 내용이 있다면 알려주세요.

NextJS란?

Next.JS는 Vercel이 개발한 오픈 소스 react 프레임워크이다. 서버 사이드 렌더링(SSR)을 사용하여 웹 사이트를 구축을 도와준다.

Next.Js는 새로운 방식의 프레임워크가 아닌 React를 기반으로 만든 프레임워크이다. 따라서 React의 기능과 생태계를 모두 활용할 수 있다.


CSR & SSR 그리고 Hydrate

서버 사이드 렌더링이란 웹 애플리케이션의 초기 렌더링을 서버에서 처리하는 방식이다. 기존 React의 클라이언트 사이드 렌더링(Client-Side Rendering, CSR)과 비교하면 조금더 이해가 쉬워진다. SSR을 이해하기 위해 먼저 CSR의 렌더링 방식을 알 필요가 있었다. React가 사용하는 CSR의 과정을 정리하면 다음과 같다.

먼저 CSR방식에서 클라이언트가 서버에 HTML 파일을 요청하면 서버는 클라이엔트에게 빈 HTML파일을 응답하게 된다.

React로 만들고 배포한 웹 애플리케이션에 들어가 개발자도구에서 JavaScript를 비활성화 시키면 다음과 같은 빈 HTML을 볼 수 있다.

<html lang="en">
  <body>
    <div id="root"></div>
   	<script src="js.js"></script>
  </body>
</html>

클라이언트는 빈 HTML파일을 로드하고 JavaScript파일을 다운로드하게 된다. JavaScript가 다운로드 완료되기 전까지 사용자는 하얀 빈 화면만 보게된다.

JavaScript 다운로드가 완료되면 JavaScript 파일에 포함된 React 코드가 실행된다. React코드 실행 과정을 간단히 나타내면 다음과 같다.

ReactDOM.render() 메서드 호출 -> 컴포넌트 트리 생성 -> 초기 렌더링 -> 이벤트 처리 및 상태 업데이트

정리하자면 CSR은 서버에 HTML파일을 요청하면 빈 껍데기를 던져주고, React 코드가 포함된 JS파일을 다운로드하게 한다. 다운로드가 완료되면 코드가 실행되면서 DOM을 그리게 된다. 즉, 요청을 보내면 완성된 HTML파일 자체를 주는것이 아닌 빈 HTML파일만 오고 클라이언트에서 안쪽 DOM을 채운다는 말이다.

반대로 SSR의 렌더링 과정을 알아보면서 비교해보자.

SSR도 처음엔 똑같이 서버에 HTML파일을 요청한다. 그러면 CSR과는 달리 사용자가 페이지를 요청할 때마다 서버에서 HTML을 생성하고 전달한다. (이 과정에서 데이터 패칭요청이 있다면 데이터 패칭 후 이를 바탕으로 HTML을 생성해 전달) CSR의 예시처럼 빈 HTML을 반환하는게 아닌 완성된 형태의(Pre-Rendering된) HTML을 반환한다는 의미이다.

클라이언트는 완성된 HTML을 받아 로드하고 JavaScript파일을 다운로드 하게 된다. CSR방식이라면 이 시점에서 사용자는 하얀 빈 화면만 보이겠지만 SSR을 사용하면 빈 화면이 아닌 기본적인 형태를 갖춘 페이지를 보게 되는것이다.

JavaSrcipt다운이 완료가 되면 다운된 코드들이 이미 보내진 HTML DOM 요소 위에서 한번 더 렌더링 및 이벤트 처리를 하면서, 각자 자기 자리를 찾아가며 매칭이 된다.

이 과정을 Hydrate라고 부른다.

처음에는 이 말을 이해하기 어려웠다. 정리해서 이야기 하자면, CSR은 화면이 나타남과 동시에 상호작용이 가능하다. 하지만 SSR은 서버가 클라이언트에게 완성된 HTML을 미리 보내기 때문에 사용자와 상호작용을 가능하게 만들어주는 JS코드가 아직 다운로드가 안되어 존재하지 않는다.

그렇기에 후발주자로 도착한 JS번들()이 미리 도착해있던 HTML DOM(스폰지)에 흡수되는 과정이 바로 Hydrate이다.

따라서 이러한 과정이 끝나기 전까지는 사용자와의 상호작용이 불가능하고 Hydrate과정이 끝나야 비로소 상호작용이 가능하게 되고 렌더링이 끝나게 된다.

하지만 주의해야할 점이 있다. 방금 설명한 Nextjs의 SRR은 전통방식의 SSR과는 조금 결이 다르다.

Nextjs에서의 SSR은 초기 로딩이 빠르다는 강점이 있는 전통 SSR과 인터렉션에 강점이 있는 CSR의 장점을 합친거라고 할 수 있다.


서버컴포넌트? 클라이언트컴포넌트?

React가 18버전으로 업데이트 되면서 추가된 새로운 기능이 바로 서버컴포넌트(RSC) 라는 개념이다. 개인적으로 공부하면서 가장 헷갈렸던 개념이 바로 서버컴포넌트와 SSR의 차이였다.

"서버컴포넌트? 그거 뭐 SSR의 상위버전 같은건가?"

결론적을 말하자면 서버컴포넌트(RSC)는 SSR과 다른 개념이다. 서로 상호보완하는 관계정도로 생각하면 된다. 위의 SSR을 이해하고 새로 업데이트된 서버컴포넌트가 무엇인지 이해하면 이 둘이 다르다는걸 알 수 있다.

먼저 클라이언트컴포넌트에 대해서 간단하게 짚고 넘어가보자.

클라이언트컴포넌트(RCC)

사실 이건 우리가 잘 알고 있는 React컴포넌트를 말하는것이다. 단지 서버컴포넌트의 등장으로 표준 React컴포넌트에 이름을 붙혀서 클라이언트 컴포넌트라는 새로운 이름으로 불리게(리브랜딩) 되었다고 생각하면 이해하기 쉽다.

서버컴포넌트(RSC)

그럼 서버컴포넌트는 무엇일까? 서버컴포넌트는 말 그대로 서버에서만 렌더링 되는 컴포넌트를 말한다. 다시 말하자면 서버컴포넌트는 서버에서만 존재하고 서버에서 해석되며 렌더링된다는 말이다.

위에서 SSR의 방식을 설명할때 후발주자로 넘어온 JS파일을 HTML DOM에 넣어주는 Hydrate작업을 거쳐야 비로소 "완전히 사용가능한 상태" 즉, 렌더링이 완료된다고 설명했다.

하지만 서버컴포넌트는 서버에서만 해석되고 실행되니 클라이언트에서 실행되는 React의 Hook과 Web API 그리고 EventHandler 등의 코드는 사용할 수 없고 사용자 상호작용이 불가능하다는 의미이다.

또한 서버에서 한번 렌더링 된 값은 클라이언트로 전송되어 제자리에 고정되기 때문에 다른곳으로 라우팅되지 않는 이상 변경되지 않는다. 이말은 서버 컴포넌트가 리렌더링 될 이유가 없다는 말이다. 즉, 서버컴포넌트는 리렌더링되지 않는다.

따라서 서버컴포는트는 후발주자로 넘오는 JS번들에 담겨오지 않는다. 이미 서버에서 전부 렌더링되었고, 한번 렌더링된 값은 고정되어 있고, 사용자 상호작용에 필요한 React의 Hook과 Web API 그리고 EventHandler등도 쓰지 못하니 JS번들에 들어있을 이유가 전혀 없는것이다.

여기서 추가적으로 조금 더 생각해보면 서버컴포넌트가 서버서만 존재하고 실행된다는 말은 컴포넌트가 서버인프라에 접근할 수 있다 말이다. 따라서 서버컴포넌트에서 바로 DB와 파일 시스템에 접근이 가능해진다.


정리

"리액트 서버 컴포넌트는 서버 사이드 렌더링의 대체재가 아닙니다. 하지만 사용자 경험 향상을 위해 함께 사용할 수는 있습니다."

서버 컴포넌트가 SSR을 대체할 수 있는건 아니다. SSR과 서버 컴포넌트가 함께 사용된다면, 초기에 서버에서 빠르게 렌더링한 다음, SSR을 통해 이를 HTML로 렌더링하여 웹 애플리케이션 초기 로딩을 빠르게 만들 수 있다. 따라서 RSC 반드시 둘 중 하나를 선택할 필요도 없고 필요에 따라 RSC와 SSR을 적절히 함께 사용하는것이 더욱 효과적일 것이다.

profile
안녕하세요! 👋

0개의 댓글