본문 바로가기
IT/React

서버 사이드 렌더링

by 봉즙 2019. 11. 25.

서버 사이드 렌더링을 구현하면서 사용자가 웹 서비스에 방문햇을 때 서버쪽에서 초기 렌더링을 대신해준다. 그리고 사용자가 html을 전달받을 때 그 내부에서 렌더링된 결과물이 보인다.

 

서버사이드 렌더링 장점

리액트로 만든 SPA(single page application)은 검색 엔진 클롤러 봇 처럼 자바스크립트가 실행되지 않는 환경에서는 페이지가 제대로 나타나지 않아 서버에서 클라이언트 대신 렌더링을 해 주면 검색 엔진이 페이지의 내요응ㄹ 제대로 수집해 갈 수 있다. 구글 검색 엔진은 다른 검색 엔진과 달리 검색 엔진에서 자바스크립트를 실행하는 기능이 탑재되어 있으므로 제대로 페이지를 크롤링해 갈 때도 있지만, 모든 페이지에 대해 자바스크립트를 실행하 주지 않는다. 그렇기에 웹서비스의 검색엔진 최적화를 위해서라면 서버사이드 렌더링을 구현해 주는 것이 좋다.

초기 렌더링의 성능을 개선할 수 있다. 자바스크립트 파일 다운로드가 완료되지 않은 시점에서도 html상에서 사용자가 볼 수 있는 콘텐츠가 있기 때문에 대기시간이 최소화된다.

 

서버 사이드 렌더링의 단점

원래 브라우저가 해야 할 일을 서버가 대신 처리하브로 서버 리소스가 사용된다는 단점이 있어 사용자가 많은경우 캐싱과 로드 밸런싱을 통해 성능을 최적화 해야한다.

구조가 복잡해지기도 한다.

 

서버 사이드 렌더링과 코드스플리팅 충돌

서바 사이드 렌더링된 결과물이 브라우저에 나타나며 자바스크립트 파일이 로딩되고 자바스크립트가 실행되며 아직 불러오지 않은 컴포넌트를 null로 렌더링하며 페이지에서 코드 스플리팅된 컴포넌트들이 사라지고 로딩된 이후 제대로 나타나는 현상이 발생한다. 이를 해결하려면 라우트 경로마다 코드 스플리팅된 파일중에서 필요한 모든 파일을 브라우저에서 렌더링하기 전에 미리 불러와야한다.

 

서버 사이드 렌더링용 엔트리

엔트리는 웹팩에서 프로젝트를 불러올 때 가장 먼저 불러오는 파일이다. 서버 사이드 렌더링을 할 때는 서버를 위한 엔트리 파일을 따로 생성해야 한다.

서버에서 리액트 컴포넌트를 렌더링할 때는 ReactDOMServer의 renderToString이라는 함수를 이용한다.

const html = ReactDOMServer.renderToString(
    <div>Hello Server Side Rendering!</div>
);

엔트리 파일을 웹팩으로 불러와 빌드하려면 config/path.js에 있는 module.exports 부분에

  ssrIndexJs: resolveApp('src/index.server.js'),//서버사이드 렌더링 엔트리,
  ssrBuild: resolveApp('dist')//웹팩 처리후 저장 경로

를 추가해준다.

웹팩 환경 설정을 위해서는 config/webpack.config.server.js 파일을 생성하여

const paths = require('./paths');

module.exports = {
    mode: 'production', //프로덕션 모드로 설정하여 최적화 옵션들을 활성화
    entry: paths.ssrIndexJs, //엔트리 경로
    target: "node", //node환경에서 실행될 것이라는 걸 암시
    output: {
        path: paths.ssrBuild, //빌드 경로
        filename: 'server.js', //파일 이름
        chunkFilename: 'js/[name].chunk.js', //청크 파일 이름
        publicPath: paths.servedPath //정적파일이 제공될 경로
    }
};

웹팩 기본 설정을 작성해준다.

웹팩의 로더 또하 설정을 해주어야한다. 로더는 파일을 불러올 때 확장자에 맞게 필요한 처리를 해준다.

 

부라우저에서 사용할 때는 결과물 파일에 리액트 라이브러리와 어플리케이션에 관한 코드가 공존해야하나 서버에슨 ㄴ결과물 안에 리액트 라이브러리가 들어있지 않아도node_modules를 통해 바로 불러와 사용할 수 있다. 서버를 위해 번들링할 때는 node_modules에서 불러오는 것을 제외하고 번들링하는 것이 좋으며 wepack-node-externals라는 라이브러리를 사용한다.

 

PreloadContext

서버사이드 렌더링을 할 때는 useEffect나 componentDidMount에서 설정한 작업이 호출되지 않는다. 렌더링하기 전에 API를 요청한뒤 스토어에 데이터를 담아야 한다. 서버환경에서 이러한 작업을 하려면 클래스형 컴포넌트가 가지고 있는 constructor이나 render함수 자체에서 처리해야한다.  대신 PreloadContext를 만들고 Preloader 컴포넌트를 만들어 이를 처리할 수 도 있다.
PreloadContext는 서버사이드 렌더링을 하는 과정에서 처리해야하는 작업을들 실행하고 만약 기다려야하는 promise가 있다면 프로미스를 수집한다. 수집된 프로미스들이 끝날 대까지 기다렸다 다시 렌더링하면 데이터가 채워진 상태로 컴포넌트들이 나타난다.

 

renderToStaticMarkup 함수는 리액트를 사용하여 정적인 페이지를 만들 때 사용한다. 또한 rednerToString보다 처리속도가 빠르다.

 

서버사이드 렌더링 후 브라우저에서 어더한 파일을 사저에 불러와야할지 알아내고 해당 파일들의 경로를 추출하기 위해ChunkExtractor와 ChunkExtractorManager를 사용한다.

 

Loadable Components를 사용하면 성능을 최적화 하기 위해 모든 자바스크립트 파일을 동시에 받아 오고 렌더링처리하기 위해서는 loadableReady라는 함수를 사용한다.

hydrate는 render 함수 대신 사용하며 기존에 렌더링된 결과물이 있는 경우 새로 렌저이하지 않고 UI에 이벤트만 연동함으로서 성능 최적화

 

Next.js : 프레임워크 최소한의 설정으로 데이터 로딩, 코드 스플링 등을 간단하게 처리하지만 리액트 라우터와는 호환 X

Razzle : Next.js처럼 서버사이드 렌더링을 도와준다.

'IT > React' 카테고리의 다른 글

JWT  (0) 2019.12.02
Koa  (0) 2019.11.27
코드 스플리팅  (0) 2019.11.22
리덕스  (0) 2019.11.19
SPA  (0) 2019.11.18

댓글