React를 사용하면서 Next.js에 대해 알게 되었다.
Next.js를 사용하니 참 편했다.
페이지 라우팅을 페이지 폴더에 이름 맞춰서 넣기만 하면, 알잘딱깔센... (이럴 때 쓰는 게 맞나 ㅎㅎ)
뭐 SSR? 서버 사이드 렌더링? SEO? 검색 엔진 최적화? 잘 해준다고 하는데,
그게 뭐죠? 라고 물어봤을 때 대답할 자신이 없다.
그래서 오늘 확실하게 정리해보려 한다.
서버에서 렌더링 준비하는 것을 허용하여 클라이언트에게 전체 웹페이지의 구성을 빠르게 전달할 수 있다.
그림을 보고 이해해보자.
SSR 구조의 웹 페이지가 구성되어 있을 때, 클라이언트가 해당 웹 페이지에 들어가는 상황이라면,
그래서 뭐가 좋다는건지 잘 감이 안 온다.
비교할 무언가가 필요하다..
기존의 SPA(Single Page Application)인 React, Vue, Angular 라이브러리 및 프레임워크로 제작된 웹 애플리케이션들이 모두 CSR 방식이다.
최근 대부분의 웹 애플리케이션이 SPA형태로 전환하면서 Front-End 영역과 Back-End 영역이 확실히 분리될 수 있었고 더불어 Webpack, rollup, TypeScript, babel 등이 등장하면서 각 영역의 전문성을 높이는 현재와 같은 형태로 발전되어 왔다고 한다.
그 전의 웹 개발자는 현재의 풀 스택 개발자와 유사한 포지션이었다.
그럼 CSR 방식의 웹페이지는 화면에 보이기까지 어떤 과정을 거칠까?
마찬가지로 CSR의 그림과 상황을 통해 이해해보자.
CSR 구조의 웹 페이지가 구성되어 있고, 클라이언트가 해당 웹페이지로 들어가는 상황이라면,
전체적인 페이지의 완료 시점은 SSR이 빠르고, CSR은 웹 페이지가 보여지는 시점에 곧 바로 인터랙션 할 수 있다.
이런 요소들이 웹페이지의 성능을 평가하는데 지표가 된다고 한다.
명칭도 있더라.
- TTV (Time to View) : 화면에 보여지는 시점
- TTI (Time to Interact) : 클라이언트가 웹페이지와 상호작용이 가능한 시점
SSR이 CSR에 비해 TTV가 빠르기 때문에 UX가 비교적 더 좋을 것이다.
그리고 HTML 파일에
<div id="app"></div>
이렇게 되어 있는 CSR에 비해 콘텐츠가 포함되어 있는 HTML이 노출되기 때문에 검색 엔진 최적화(SEO)를 할 수 있구나?!
그럼 SSR이 무조건 CSR보다 좋은 건가?
근데 자세하게 알아보니 막 SSR이 CSR에 비해 막 그렇게 좋다고도 할 수 없다.
각각의 장단점이 있는데, 역시 비교하며 살펴보자.
SSR 장점
- Pre-rendering 과정을 거치기 때문에 페이지 로딩이 빨라진다.
- 콘텐츠가 HTML에 담겨있어 CSR에 비해 효율적인 SEO가 가능하다.
- 페이지 소유권이 완전히 프론트엔드에 존재하기 때문에 프론트엔드, 백엔드 영역을 완전히 분리할 수 있다.
(흔히 JSP로 개발되었던 SSR 웹 페이지도 프론트엔드 영역에서 개발할 수 있다.)
SSR 단점
- 사용자가 클릭을 할 때마다 서버에 요청을 해서 서버에 과부하가 걸리기 쉽다.
- 필요한 페이지에 대해 그때그때 요청하며 HTML을 만들기 때문에 깜빡거리는 현상이 발생할 수 있다.
- TTI가 느려질 수 있어 사용자가 인터랙션 하지 못하는 시간이 길어질 수 있다.
CSR 장점
- TTV와 TTI가 일치하기 때문에, 인터랙션을 곧바로 할 수 있다.
- 처음에 모든 파일을 받아와 브라우저에서 모든 것을 처리하기 때문에 추후에 필요한 데이터를 갱신하여 적용할 수 있고 따라서 깜빡거리는 현상이 발생하지 않고 빠르게 적용된다.
- 위와 같은 이유로 서버 부하 비용을 줄일 수 있다.
- Lazy Loading이 가능하게 한다. (스크롤 내렸을 때 해당 이미지를 로드하는 것과 같이)
CSR 단점
- 초기화면 로딩 시간이 오래 걸린다. 규모가 커지면 좋지 않은 UX를 줄 수 있다.
실제로 서비스했던 앱 사용자 인터뷰 중 - 초기 로딩이 느려서 전반적으로 느리다는 선입견을 준다.
- 검색 엔진 최적화가 잘 되지 않는다.
장점과 단점들을 살펴보면 알 수 있듯이 각각의 특성이 필요할 수 있겠다는 생각이 든다.
그럼 SSR과 CSR에서 이러한 단점들을 보완할 수 있는 방법은 없을까?
CSR의 단점 중 큰 부분은 초기 화면을 보기까지 많은 시간이 걸릴 수 있다는 것인데 이를 해결하기 위해서는 사용자에게 보여지는 자바스크립트 파일을 효율적으로 분할해서 필수적인 것만 전송하는 방법으로 개선할 수 있을 것이다. 그리고 검색 엔진 최적화가 되지 않는 부분은 각 검색 엔진 별로 다른데, Google 검색엔진의 경우 자바스크립트 기반으로 분석하기 때문에 CSR에서도 충분히 SEO 최적화가 가능하다고 한다. 하지만 네이버 검색 엔진의 경우 역시 JavaScript 영향도를 측정하고 해석하는 일련의 과정을 거치지만 전통적인 HTML 페이지 분석보다 몇 배 이상의 리소스를 필요로 하기 때문에 SSR을 추천하고 있다.
자세한 내용은 SEO 포스팅에서 다룰 예정이다.
SSR의 단점을 개선하는 방법에는 TTI 시간을 어떻게 단축할 수 있을지 잘 설계하는 것 그리고 서버의 부하를 줄일 수 있는 방법을 찾는 것이다.
SSG 방식은 정적인 웹사이트를 HTML로 생성해 서버에 저장해두는 것을 뜻한다.
SSG 역시 SSR과 마찬가지로 Pre-rendering을 지원하는데,
미리 생성이 완료된 HTML 문서를 재활용하기 때문에 응답 속도가 매우 빠르고, 효율적인 SEO가 가능하다.
SSR 방식의 단점이었던 요청에 따라 서버에서 HTML을 계속 생성하는 방식이 아니라 이미 생성이 완료된 페이지를 재활용하기 때문에 응답 속도가 매우 빠르다.
Next.js가 좋은 평을 받는 이유는, React와 같은 CSR에서 SSR이 가능하게 하였고, 이 둘의 강점을 적절히 활용할 수 있게 하였기 때문이다.
첫 요청 페이지에 대해서는 SSG 혹은 SSR을 통해 서버에서 미리 pre-rendering 된 첫 화면을 빨리 보여줄 수 있다.
SSG를 적절히 사용한 Next.js에서 제공하는 전략
- Static Rendering(정적 렌더링) : 서버 측에서 미리 렌더링을 마치고 정적 HTML 파일을 생성해두어 웹 페이지를 빠르게 볼 수 있다.
getStaticProps() : 페이지를 렌더링 할 때 필요한 데이터를 사용자의 요청보다 먼저 빌드 시에 사용할 수 있다. 또한, 해당 데이터가 공개적으로 캐시 되어 있으므로 SEO 또한 효율적이다. 해당 메서드는 서버에서 실행되고 클라이언트에서 실행되지 않는다.
- Static Rendering with Incremental Static Regeneration(ISR) : 웹 페이지가 사전 렌더링 된다. 즉, 서버 측에서 빌드 시간에 정적 HTML이 생성되고 다음과 같은 경우 특정 웹 페이지에 대한 정적 HTML의 re-build가 트리거 된다.
서버 측에서 실행되는 메서드 내에 매개변수를 추가하여 백그라운드에서 오래된 페이지의 재검증 이후에 새 페이지가 브라우저에 제공된다.
Incremental Static Regeneration(ISR) 접근 방식은 트리거 될 때 revalidate prop이 있는 웹 페이지만 다시 빌드되게 한다.
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}
위와 같이 revalidate prop을 10으로 설정했을 때, 데이터에 변화가 있다면 10초마다 특정 페이지를 re-build 하는 트리거가 실행된다.
백그라운드에서 새로운 페이지가 모두 생성되었으면 해당 시간 이후에 요청하는 브라우저에게는 업데이트된 페이지를 보여주게 된다.
- Static Rendering with data fetched on server-side at request-time(Dynamic Server Side Rendering) : 정적 HTML은 빌드 시 미리 렌더링되지만 웹 페이지의 데이터 부분은 비어 있다.
그런 다음 브라우저가 웹 페이지를 요청할 때마다 웹 페이지의 데이터 부분이 서버 측에서 채워지고 미리 생성된 HTML이 요청 시 가져온 데이터로 채워진다. 이는 getServerSideProps() 요청 시 데이터를 가져와야 하는 웹페이지를 미리 렌더링 하는 메서드를 사용하여 구현된다. (getServerSideProps 메서드는 서버 측에서만 실행된다.)
즉, 브라우저 요청을 받은 서버 측에서 API를 호출하여 데이터를 가져오고, 서버 측에서 미리 렌더링 된 웹 페이지를 채운 다음 이 HTML을 반환하는 구조이다.
- Static Rendering with data fetched on client-side at request-time : 웹 페이지는 미리 렌더링 되지만 웹 페이지의 데이터 부분은 공백으로 남겨두고 클라이언트 측 에서 데이터를 가져와 채운다.
즉, 데이터를 요청해서 동적으로 가져오는 방식이다.
Next.js를 사용하면 동일한 웹 앱의 여러 페이지에 대해 서로 다른 사전 렌더링 전략을 선택할 수 있다.
대부분의 페이지에 정적 생성을 사용할 수 있고 다른 페이지에 Dynamic Server Side Rendering을 사용할 수 있는 하이브리드 웹 앱을 만들 수 있다.
- SSR은 서버 측에서 HTML을 Pre-rendering 할 수 있는 방식이다.
- CSR과 비교했을 때 장점과 단점이 있는데, 대표적으로 TTI와 TTV 성능 지표를 통해 비교해볼 수 있다.
- SSG는 정적으로 웹사이트를 저장해 두고 빠르게 화면을 보여주는 방식이다.
- Next.js는 SSR, CSR, SSG 방식을 적절히 사용하여 하이브리드 웹 애플리케이션을 만들 수 있는 React의 Framework이다.
https://d2.naver.com/helloworld/7804182
https://web.dev/rendering-on-the-web/
https://minsoftk.tistory.com/68
https://searchadvisor.naver.com/guide/seo-advanced-javascript
https://higher77.tistory.com/105
https://nextjs.org/docs/basic-features/data-fetching/get-static-props
[React] React 18 성능 개선 정리 (0) | 2022.06.02 |
---|---|
브라우저 (Browser) (0) | 2022.04.14 |
Selecolor - 프론트엔드 게임 제작 챌린지 (8) | 2022.02.13 |
프론트엔드 개발자 성장 가이드 후기 (0) | 2021.12.25 |
댓글 영역