[React] SSR과 CSR 적용 (in 오즈의_제작소)

Lee_Sangmin·2022년 7월 10일
0

business

목록 보기
2/2
post-thumbnail

렌더링(Rendering)이란?

웹 프로그래밍에서의 렌더링이란 서버로부터 HTML파일을 받아 브라우저에 뿌려주는 일련의 과정을 뜻한다.

  • 렌더링 과정

브라우저(Loader)가 서버로부터 정보들을 불러온다.

→ 렌더링 엔진이 Parsing을 통해 HTML문서를 DOM트리로 만든다.

→ 외부 css파일과 함께 포함된 스타일 요소를 파싱해 CSSOM트리를 만든다.
(스타일은 브라우저 스타일 > 사용자 정의 스타일 > html tag 스타일 순으로 처리되며 나중 처리되는 스타일이 우선적으로 적용된다.)

→ 브라우저는 DOM트리와 CSSOM을 결합하여 렌더트리를 구축한다.

→ 뷰포트 내에서 노드들의 위치와 크기를 계산하는 과정이 진행된다.
(해당 과정을 레이아웃 단계 혹은 리플로우 라고 부른다.)

→ 렌더링 엔진이 페인트 이벤트를 발생시켜 렌더링 트리 그려낸다.
(해당 과정을 페인팅 또는 래스터화 라고 부른다.)


SSR(Server Side Rendering)

전통적인 웹 어플리케이션의 렌더링 방식.

요청시마다 서버에서 처리한 후 새로고침으로 페이지에 대한 응답.

  • MPA(Multiple Page Application)

전통적인 웹 애플리케이션 구성 방식이다. SSR방식과 일맥상통한다.
MPA 애플리케이션의 가장 큰 단점은 프론트엔드와 백엔드가 강하게 결합되어 있다는 것인데,
가령 사용자가 main이라는 페이지를 요청한다면 다음과 같은 과정을 거치기 때문이다.

  1. 'main'에 대한 페이지 정보를 서버에 요청한다.
  2. 'main'에 대한 요청을 받은 서버는 해당하는 UI 및 필요한 데이터를 HTML데이터로 파싱한다.
  3. 브라우저는 전달받은 HTML 데이터를 지정된 인코딩으로 변환하여 사용자에게 보여준다.

브라우저는 해당 과정을 거치면서 페이지를 갱신하며, 사용자의 모든 이동에 대하여 페이지 새로고침이 발생하게된다. 새로고침은 로딩 시간의 합을 증가시키며 이로인해 사용자 경험이 나빠질 수밖에 없다. 현재는 페이지 이동없이 화면을 전환할 수 있는 수준까지 단점을 극복해냈지만, 근본적으로 페이지 이동시에 새로고침 되는 문제를 해결할 수는 없었다.

  • SSR을 채택해야 하는 상황 예시

네트워크가 느리거나 메인스크립트가 커서 로딩이 느릴 때.
(CSR은 한번에 모든 것을 불러오지만 SSR은 페이지마다 나눠불러오기 때문)

SEO(serach engine optimization : 검색 엔진 최적화)가 필요할 때.

최초 로딩이 빨라야하는 사이트를 개발 할 때.

웹 사이트가 상호작용이 별로 없을 때.

보안이 필요한 주요 비즈니스 로직을 숨겨야 할 때.

CSR(Client Side Rendering)

클라이언트에서 JS를 통해 렌더링하는 방식.

  • SPA(Single Page Application)

MPA 애플리케이션의 단점을 개선해줄 수 있는 방법이다. CSR방식과 같은 말이다.
SPA는 브라우저에 로드되고 난 뒤에 페이지 전체를 서버에 요청하는 것이 아닌, 최초 한번 전체 페이지를 다 불러온 후 HTML에 번들링 된 js가 실행되면서 페이지 렌더링한다.
그리고 렌더링 후 클라이언트 요청에 따라 페이지 특정 부분만 재 렌더링하는 웹 어플리케이션 개념이다.

모든 페이지를 Javascript안에 포함해두고, 동적으로 화면이 갱신되는 것처럼 보이게 하는 것이다.
페이지에 담는 정보가 커지게 된다면 Javascript파일이 비대해져 애플리케이션의 쵝 렌더링 속도가 느려지게 되고, SEO에 굉장히 취약하다는 단점이 존재한다.

  • CSR을 채택해야 하는 상황 예시

네트워크가 빠르거나, 메인 스크립트가 가벼울 때.

서버의 성능이 좋지 않을 때.

사용자에게 보여줘야 하는 데이터의 양이 많을 때.
(로딩창을 띄울 수 있는 장점)

SEO가 필요없는 페이지를 구축할 때.

웹 어플리케이션에 사용자와 상호작용할 것들이 많을 때.
(아예 렌더링 되지 않아서 사용자의 행동을 막는 것이 경험에 오히려 유리함.)


SSR과 CSR의 차이점

  • 초기 View로딩 속도
    CSR은 최초 로딩시 HTML,JS,CSS 모두 불러와 SSR보다 조금 느린 현상.
    CSR은 최초 로딩 이후의 요청들에 대해서는 인터렉션이 빠르다.
    SSR은 정보가 많은 B2C 웹 서비스등에서 서버의 부담이 크다.

  • SEO(검색 엔진 최적화) 문제
    일반적인 웹크롤러,봇 들은 HTML내용만 수집하여 빈 페이지로 인식한다.
    js가 실행이 완료되어 렌더링 되기 전까지 HTML은 빈 화면이기 때문이다.

  • 보안 문제
    SSR에서는 사용자에 대한 정보를 서버 측에서 세션으로 관리했음.
    CSR의 경우는 쿠키말고는 사용자에 대한 정보를 저장할 공간이 마땅치 않다.

  • 진화
    위의 문제들을 해결하기위해 Angular는 버전업, React는 서버사이드 렌더링 문제를 고려하여 개발 됨.
    React와 Vue로 만든 프레임워크인 Next.js와 Nust.js등이 나오고 사용률이 증가중.


SSR과 CSR의 상호보완

최근에는이 두 가지 렌더링 방식의 단점을 상호보완하여 첫 번째 페이지 로딩에서는 서버 사이드 렌더링(SSR)을 사용하고, 그 후에 모든 페이지 로드에는 클라이언트 사이드 렌더링(CSR)을 활용하는 방법을 많이 사용한다.

  • Next.js

일반적으로 SSR과 CSR을 상호보완하는 형식을 적용하기 위한 프로젝트 세팅에서 Next.js를 많이 사용한다.
React만으로 SSR을 구현하는게 불가능한건 아니지만, 과정이 굉장히 복잡하다.

'오즈의 제작소' 에서도 Next.js를 사용한다.
굿즈 상품을 판매하는 사이트이기 때문에 검색엔진 최적화(SEO)가 중요해 SSR의 사용이 필요하다.

CSR을 사용하는 구조에서도 검색엔진 최적화가 가능하긴 하다.
react-helmet 패키지로 SEO에 필요한 메타태그들을 변경하고
react-snap 패키지를 통해 html파일을 분리하고 SEO친화적으로 바꿔낸다.

오즈의 제작소에서의 적용

  • 코드
import React from 'react';
import { Helmet } from 'react-helmet';
import PropTypes from 'prop-types';

const JsonLdSEO = (index) => {
  const jsonLd = [
    {
      '@context': 'http://schema.org',
      '@type': 'SoftwareApplication',
      name: '굿즈 제작 정보가 다! 오즈의 제작소',
      url: 'https://ozjejakso.com/aboutus',
      
      applicationCategory: '검색엔진',
      applicationSubCategory: '굿즈 제작 업체 검색엔진',
      offers: '굿즈 제작 업체 소개',
      aggregateRating: '10.0',
      operatingSystem: 'Windows 7, OSX 10.6, Android 1.6',
    },
    // ~~,
    // ~~,
    // ~~,
  ];

  return (
    <>
      <Helmet>
        <script type="application/ld+json">
          {JSON.stringify(jsonLd[index])}
        </script>
      </Helmet>
    </>
  );
};
JsonLdSEO.propTypes = {
  index: PropTypes.number,
};

export default JsonLdSEO;

앞서말한 react-helmet을 통해 CSR 환경 (가령 꿀팁페이지)에서도 SEO를 적용할 수 있도록
SEO관련 정보를 함수에 담아두어 index로 찾아 꺼내어 적용하는 구조.

		// _app.js의 일부.

        <Head>
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
          />
          <style>{fontFace}</style>

          <title>{title}</title>
          <meta name="description" content={description} />

          {/* Open Graph */}
          <meta property="og:type" content="website" />
          <meta property="og:title" content={title} />
          <meta property="og:description" content={description} />
          <meta property="og:url" content="https://ozjejakso.com" />
          <meta property="og:site_name" content="오즈의 제작소" />
          <meta
            property="og:image"
            content="https://ozjejakso.com/image/~~~.png"
          />
              
		// og:type: 페이지의 유형
	  	// og:site_name: 사이트의 이름
  		// og:title: 페이지의 이름(제목)
	  	// og:description: 페이지 간단 설명
  		// og:image: 페이지 대표 이미지 주소
	  	// og:url: 페이지 주소

          {/* Twitter Card */}
          <meta name="twitter:card" content="~~~" />
          <meta name="twitter:site" content="@ozjejakso" />
          <meta name="twitter:creator" content="@ozjejakso" />
          <meta name="twitter:title" content={title} />
          <meta name="twitter:description" content={description} />
          <meta name="twitter:url" content="https://ozjejakso.com" />
          <meta
            name="twitter:image"
            content="https://ozjejakso.com/image/~~~.png"
          />
        </Head>

	  	// twitter:card: 페이지의 유형
  		// twitter:site: 사이트의 이름
  		// twitter:title: 페이지의 이름
	  	// twitter:description: 페이지 간단 설명
  		// twitter:image: 페이지 대표 이미지 주소
	  	// twitter:url: 페이지 주소

SSR을 사용할 수 있는 환경에서 보편적으로 가장 많이 사용하는 Head tag.

기본적인 meta tag외에 open-graph와 twitter-card를 작성하여 두었다.
오즈의 제작소 페이지를 흔히 잘 아는 sns를 통해 공유할 때, 우선적으로 활용되는 정보를 지칭하는 부분.

다음과같은 카드 형식의 웹사이트 기본 정보를 표시함을 뜻한다.


  • 글을 쓴 뒤의 생각

next.js에서 사용할 수 있는 패키지 next-seo에 대해서 알게 되었다.
반복 사용되는 SEO tag들에 대해서 보다 더 편리하게 작성 가능할 수 있어, 사용하는 구조로 수정을 해보고 싶다.

SSR을 사용 이유 중 보안적 측면의 이점을 간과하고 있었다.
지난 2분기에 제작한 '오즈의 제작소' 내 결제 페이지와 관련하여, 사용자 정보를 네트워크에서 확인할 수 없게 하는게 중요하다는 걸 몰랐다.
해당 정보를 어떤 방식으로 공격자가 공격할 수 있는건지 알아보고, 볼 수 없는 구조로 수정해야한다.


ETC

  • 참조

https://velog.io/@ru_bryunak/%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4%EB%9E%80

https://www.huskyhoochu.com/what-is-spa/

https://velog.io/@bumsu0211/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95%EA%B3%BC-%EC%B5%9C%EC%A0%81%ED%99%94

https://blog.martinwork.co.kr/devops/2019/05/24/server-side-rendering01.html


https://velog.io/@vagabondms/%EA%B8%B0%EC%88%A0-%EC%8A%A4%ED%84%B0%EB%94%94-SSR%EA%B3%BC-CSR%EC%9D%98-%EC%B0%A8%EC%9D%B4#:~:text=CSR%EC%9D%98%20%EA%B2%BD%EC%9A%B0%20HTML%2C%20CSS,%EC%9C%BC%EB%A1%9C%20SSR%EC%9D%B4%20%EB%8D%94%20%EB%B9%A0%EB%A5%B4%EB%8B%A4.&text=%EC%B2%AB%20%ED%8E%98%EC%9D%B4%EC%A7%80%EB%A5%BC%20%EB%A1%9C%EB%94%A9%ED%95%9C,%EC%9D%98%20%EB%8F%99%EC%9E%91%EC%9D%84%20%EA%B0%80%EC%A0%95%ED%95%98%EC%9E%90.

https://velog.io/@sunaaank/React-deep-dive

https://ctdlog.tistory.com/47#:~:text=Next.JS%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%20%EA%B0%80%EC%9E%A5%20%ED%81%B0%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20SSR,%EB%A0%8C%EB%8D%94%EB%A7%81%20%EB%90%A0%20HTML%EC%9D%84%20%EB%B3%B4%EB%83%84.

https://byseop.netlify.app/csr-seo/


https://velog.io/@bumsu0211/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95%EA%B3%BC-%EC%B5%9C%EC%A0%81%ED%99%94

https://velog.io/@hjkdw95/SSR%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC%ED%95%98%EB%8A%94-%EB%98%90%EB%8B%A4%EB%A5%B8-%EC%9D%B4%EC%9C%A0

https://velog.io/@nemo/getServerSideProps-getStaticProps#:~:text=%EC%96%B8%EC%A0%9C%20%EC%82%AC%EC%9A%A9%ED%95%98%EB%82%98%3F,-%EC%9A%94%EC%B2%AD%20%EC%8B%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0&text=Next.js%EB%8A%94%20getServerSideProps%EB%A5%BC,%EC%98%A4%EB%8A%94%20%EA%B2%83%EB%8F%84%20%EA%B3%A0%EB%A0%A4%ED%95%B4%EB%B4%90%EC%95%BC%20%ED%95%9C%EB%8B%A4.

https://kyounghwan01.github.io/blog/React/next/next-seo/#%E1%84%8F%E1%85%A1%E1%84%8F%E1%85%A1%E1%84%8B%E1%85%A9%E1%84%90%E1%85%A9%E1%86%A8-%E1%84%86%E1%85%B5%E1%84%85%E1%85%B5%E1%84%87%E1%85%A9%E1%84%80%E1%85%B5-%E1%84%8B%E1%85%B5%E1%84%89%E1%85%B2

https://goddino.tistory.com/172![](https://velog.velcdn.com/images/dltkdals224/post/b2eca8ff-3bc2-46fb-8a66-a049d1ae7d27/image.png)

profile
FE developer

0개의 댓글