거의 알고리즘 일기장

프론트주니어의 개발기록 1 - next.js를 쓰지않고 react ssr 해보기 본문

web

프론트주니어의 개발기록 1 - next.js를 쓰지않고 react ssr 해보기

건우권 2021. 7. 13. 20:21

해본 이유

회사에서 신규프로젝트의 프론트 부분을 맡게 되었다...


이번 프로젝트는 검색엔진에 노출이 잘되어야하는 프로젝트여서, seo에 유리한 ssr로 해야했다. 

먼저, 이 프로젝트는 react를 이용할 예정임으로 react에서 ssr을 적용하는 경우를 생각해보았다.


1. react 자체적으로 ssr을 구현한다.
2. next.js 등 라이브러리 붙여서 편안하게~ 개발한다.

당연히 서비스를 만드는건 2번이고, 1번은 어떻게 하는지 호기심이 들어서 해보았다.


1차 시도 

솔직히 어떻게 하는지 감도 안잡혀서 구글신께 여쭤봤더니 한글로 되어있는 괜찮은 글을 찾았다.

https://minoo.medium.com/next-js-%EC%B2%98%EB%9F%BC-server-side-rendering-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-7608e82a0ab1

 

Next.js 처럼 Server-side-rendering 구현하기

안녕하세요. Next.js 없이 Client-side-rendering을 Server-side-rendering 으로 바꾸는 방법을 작성해보았습니다.

minoo.medium.com

이 글은Typescript + React + Server-side rendering + Code-splitting 으로 환경설정하는 방법 에 대해서 설명해주는데, 
cra부터 시작하는게 아니고.. 처음부터 세팅하는거라 조금 난이도가 있다.

 

처음부터 따라해보았고 결과물까지 도달할수있었지만, 플로우는 이해가 가나 스압이 있어.. 진짜 꼼꼼히 읽어보지는 않아 100% 이해했다고 생각하긴 어려웠다. 
(react나 webpack등에 익숙하지 않다면 조금 괴로울수도 있다.)


2차 시도

1차 시도 후에 한 2 ~ 3주가 지난후에 다시 시도해보았는데.. 하나도 기억이 나지 않았다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

그래서 이번에는 이것저것 (ts, hot-reload, code-splitting)을 다빼고, ssr로 바꾸기만 하는데에 집중해서 해보았다.

(물론 유튜브 튜토리얼 보면서 했다. ㅋㅋㅋㅋ)



구현 순서는 다음과 같다.


1. cra를 만든다.

npx create-react-app my-app

2. 필요한 패키지들을 깐다.

@babel/preset-env //모든 es6 기능을 컴파일할 모든 plugin이 들어있다.
@babel/preset-react //JSX로 작성된 코드들을 createElement 함수를 이용한 코드로 변환해 주는 바벨 플러그인이 내장되어 있다.
@babel/register //One of the ways you can use Babel is through the require hook. The require hook will bind itself to node's require and automatically compile files on the fly
express //웹 및 모바일 애플리케이션을 위한 일련의 강력한 기능을 제공하는 간결하고 유연한 Node.js 웹 애플리케이션 프레임워크
ignore-style //A babel/register style hook to ignore style imports when running in Node. 이럴때 에러가 나는데 그걸 해결해주는 모듈

3. server/server.js 만들어서 다음과 같이 채워넣는다.

import express from "express";
import fs from "fs";
import path from "path";

import React from "react";
import { renderToString } from "react-dom/server";

import App from "../src/App";

const PORT = 8000;

const app = express();

// build된 index.html파일을 읽어서 react에서 제공하는 renderToString을 이용해서 <App/>의 엘리먼트들을 채워넣는다.
// <div id="root">여기에</div>
app.use("^/$", (req, res, next) => {
    fs.readFile(path.resolve("./build/index.html"), "utf-8", (err, data) => {
        if (err) {
            console.log(err);
            return res.status(500).send("some error happened");
        }
        return res.send(
            data.replace(
                '<div id="root"></div>',
                `<div id="root">${renderToString(<App />)}</div>`
            )
        );
    });
});


//이건 경로를 바꿔주는것 (build로)
app.use(express.static(path.resolve(__dirname, "..", "build")));


//이건 연결됨을 알리는 console을 띄워주는것
app.listen(PORT, () => {
    console.log(`app launched on ${PORT}`);
});

4. server/index.js를 만들고 다음과 같이 채워넣는다.

require("ignore-styles"); //위에 설명해 두었다.

require("@babel/register")({
    ignore: [/(node_module)/],
    presets: ["@babel/preset-env", "@babel/preset-react"],
});

//server.js 실행
require("./server");

5. src/index.js에서 render를 hydrate로 바꾼다.

6. 명령어를 실행한다.

yarn build && node server/index.js

7. 완료 (App.js에 만든 카운터는 생략하였다.)

결과물

저번에 react18 글이 기억나서, react 18 alpa 버전을 깔아서 code spliting을 해볼까 했으나 아직 pipeToNodeWritable   api는 없었다.

그렇다면 loadable component를 써야하는데.. 추가하기엔 조금 귀찮아서 생략하였다.


결론

1차 2차 모두 ssr이 잘 됨을 확인할수 있었다. (1차로 한건 따로 깃에 올리지 않고 회사노트북에 있는데, 코로나가 심각해져서 재택을 하는 중이라 생략하였다.)

 

그리고 결과적으로 내린 판단은

1. react 18이 정식 릴리즈 되지 않았다.
2. next.js는 편하다.
3. 구글신이 next.js에 대한 많은 정보를 가지고 계시다.

 

그래서 신규 프로젝트는 next.js로 하는데에 확신이 굳었다.

 

프론트주니어의 개발기록이라는 이름으로 계속 신규 프로젝트로 인해서 배우는것들을 기록할 예정이다! (할수 있겠지?..ㅋㅋ)

반응형
Comments