서문

최근 아시는 분들과 프론트 개발에 대해 이야기를 나누다가 이런 이야기를 하였습니다.

너 CRA 없이 React 프로젝트 셋팅은 할 수 있냐?

곰곰이 생각해보니 React를 배울 때 부터 Create-React-App 을 사용한 개발만 해왔기에 CRA 없이 한번도 React 프로젝트 셋팅을 해보지 않은 사실을 알고 부끄러움을 느꼈습니다.

대략적으로 Webpack + Babel + ReactJS + Live-Server를 설정하고 나머진 필요할 때 설치하면 되지 않을까? 란 생각을 하였지만 실제로 설정을 해보니 쉽지 않았습니다.

그래서 복습도 하고 다시 한번 정리도 할 겸 이 시리즈를 시작하게 되었습니다 :)

이 글은 제가 이해한 지식을 바탕으로 서술 되었기 때문에 글에 잘못된 내용이 있다면 댓글로 가르침을 주시면 정말 정말 감사하겠습니다.

이 포스팅에서 사용한 예제는 여기서도 확인 하실 수 있습니다.


ReactJS 프로젝트에 필요한 것은 무엇 일까?


이 문제에 대한 대답을 찾기 위해 React 공식 문서를 찾아보았습니다.

교과서만 보면 수능 만점을 맞을 수 있습니다.

그리고 React 공식 문서를 제대로 안 읽은 것을 꾸짖는 것 처럼 1번째 Installation 섹션에 관련 내용이 나와있었습니다.. 쥐구멍은 어디인가?

Installation 섹션을 보면 리액트 개발을 위한 여러가지 방법들을 설명하고 있습니다.

1. Don't require configuration to get started.

React 공식 문서는 최고의 사용자 경험과 개발자 경험을 위해 통합 개발 도구를 사용하는 것을 추천하고 있습니다.

추천되는 개발도구들은 다음과 같습니다.

  • Create React App : single-page app을 만들때 사용하는 도구
  • Next.js : Node.js를 사용한 server-rendered website 만들때 사용하는 도구
  • Gatsby : static content-oriented website를 만들때 사용되는 도구

또한 React docs에 따르면 위 도구들은 다음과 같은 특성들을 도와준다고 합니다.

  • Scaling to many files and components (많은 파일들과 컴포넌트들로 확장)
  • Using third-party libraries from npm (npm으로 부터 라이브러리 사용)
  • Detecting common mistakes early ( 이른 실수 발견 )
  • Live-editing CSS and JS in development ( 개발 할때 CSS 와 JSS 실시간 변경 확인)
  • Optimizing the output for production ( production 을 위한 결과물 최적화 )

2. Creating a Toolchain from Scratch

공식 문서는 또한 사용자가 스스로 JavaScript 도구들을 사용하여 처음부터 구성을 할때 다음과 같은 도구들을 사용하라고 되어있습니다.

  • Package Manager : 다른 라이브러리의 쉬운 활용을 위해 Yarn 또는 npm 사용
  • bundler : 사용자가 모듈 코드를 작성하고 작성한 코드의 최적화 로딩 시간을 위해 webpack이나 Parcel의 사용
  • compiler : modern JavaScript 코드를 작성하고 지원하지 않는 브라우저에서 작동하게 하기 위해 Babel을 사용.

또한 사용자가 직접 만든 도구를 설정할 때 production을 위한 다음과 같은 설정을 하라고 되어 있습니다.

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin()

결론


문서의 내용을 바탕으로 스스로 React 개발 환경을 설정하기 위해서는 아래와 같은 우선 순위가 있다고 생각하였습니다.

필수사항

  • Package Manager
  • Bundler
  • Compiler

개발 편의성을 위한 선택 사항

  • Lint
  • Live Dev Server

이제 우선 순위가 정리 되었으니 파일을 만들고 차례대로 설정을 해보겠습니다.

Getting Started


우선 프로젝트 설정을 위한 파일을 하나 생성하고 기본 파일 구조를 위해 src 폴더와 public 폴더를 만들도록 하겠습니다.

$ mkdir react-a-to-z && cd react-a-to-z
$ mkdir -p src public

Package Manager - npm

package manager는 yarn 과 npm이 있습니다만 저는 npm 사용이 좀 더 익숙하기에 npm 을 사용하도록 하겠습니다. 둘 중 어떤 것을 사용하셔도 무방합니다.

$ npm init -y

Bundler - Webpack

Webpack은 Front-end 개발을 할 때 필요한 많은 설정 들을 지원해주는 강력한 도구 입니다. React app은 Component라는 모듈 단위로 개발되는데 개발되는 component들을 묶어 주는 역할을 합니다.

$ npm install --save-dev webpack webpack-cli 

설치가 완료 되면 프로젝트 파일에 있는 package.json 파일에 다음과 같은 명령어를 추가해 줍니다.

...

"scripts": {
    "build": "webpack --mode production",
},
...

Webpack을 제대로 사용하기 위해서는 webpack.config.js 파일을 생성해주고 추가적인 설정을 해줘야 합니다.

const path = require("path");

module.exports = {
        mode: "development",
    entry: {
        main: './src/index.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'build')
    },
      resolve: { extensions: ["*", ".js", ".jsx"] },
};

위의 설정 들을 간략히 설명하자면 다음과 같습니다.

  • entry: 파일들을 묶기 위해 Webpack이 바라보는 파일 시작점
  • output: bundle된 파일의 결과물을 위한 설정
  • mode: production or development
  • resolve: import 될 수 있는 파일 확장자 명

이 설정들은 Webpack의 동작을 정의하는 설정들입니다. 다음으로 Webpack이 동작할 때 Html과 CSS파일을 인식하기 위한 추가적인 설정을 해보겠습니다.

html 설정

$ npm install --save-dev html-webpack-plugin clean-webpack-plugin

CSS 설정

$ npm install --save-dev mini-css-extract-plugin css-loader sass-loader file-loader 

위 라이브러리들이 다 설치가 되었으면 webpack.config.js 파일에 설정을 추가해 보겠습니다.

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
        mode: "development",
    entry: {
        main: './src/index.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            hmr: true,
                            reloadAll: true
                        }
                    },
                    'css-loader',
                    'sass-loader'
                ]
            }, 
            {
                test: /\.(png|jpg|svg|gif)/,
                use: [
                    'file-loader'
                ]
            }
        ]
    },
    resolve: {
        extensions: [ '*', '.js', '.jsx' ]
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'webpack-react-start-kit',
            template: './public/index.html'
        }),
        new MiniCssExtractPlugin({
            filename: '[name].css',
            chunkFilename: '[id].css'
          }),
    ]
}

이어서 처음 생성한 public 폴더에 index.html 폴더를 만들도록 하겠습니다.

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>React A to Z</title>
</head>

<body>
  <div id="root"></div>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
</body>

</html>

지금 설정한 Webpack 설정들은 다음과 같습니다.

HTML

  • html-webpack-plugin : Webpack이 실행 될 때 public 파일에 설정한 html 파일을 기준으로 결과물을 만들어줍니다.
  • clean-webpack-plugin : Webpack이 실행될 때 이전에 나온 결과물을 제거합니다.(최신 결과물 만을 유지하기 위해)

CSS

  • Sass-loader , css-loader : Webpack을 실행할 때 CSS와 Sass 파일을 적용해 주는 패키지 입니다.
  • mini-css-extract-plugin : css 결과물을 여러 개의 chunk 파일로 분리 시켜주는 라이브러리 입니다.

Compiler - Babel

React component 들은 JavaScript ES6+ 문법과 JSX 문법으로 작성됩니다. 이 코드를 그대로 쓰는 경우 지원하지 않는 브라우저에서는 코드가 동작하지 않으므로 Babel을 사용하여 Transpiling 을 해줘야 합니다.

$ npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react

설치된 라이브러리들에 대한 설명을 해드리자면 아래와 같습니다.

  • @babel/core : babel 사용을 위한 코어 라이브러리
  • babel-loader : Webpack을 사용할 때 babel을 적용하기 위한 라이브러리
  • @babel/preset-env : JavaScript ES6 코드를 ES5로 compiling 해주는 라이브러리
  • @babel/preset-react : JSX 코드를 JavaScript 코드로 변환시켜 주는 라이브러리

설치가 다 되셨으면 Babel 적용을 위한 설정 파일을 만들도록 하겠습니다.

.babelrc 파일을 만들고 다음과 같이 입력 해주시면 됩니다.

{
    "presets": ["@babel/preset-env", "@babel/preset-react"]
}

Babel과 Webpack 연동

React 프로젝트를 위한 필수 항목을 다 설치하였습니다. 마지막으로 Babel과 Webpack을 연동해 보겠습니다.

우선 Webpack 설정 파일 webpack.config.js 파일을 만들고 아래와 같은 설정을 입력해주세요.

module.exports = {
    ...,
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
        exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            }
        ]
    }
};

이제 필요한 도구를 모두 설정하였습니다.

Creating React Components

이제 React 라이브러리를 설치하고 컴포넌트를 만들어 보도록 하겠습니다.

$ npm install react react-dom 

src/Index.js

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(<div>Hello React</div>, document.getElementById('root'));

파일을 저장하고 나서 npm run build 를 실행시켜 보시면 build 파일이 생성되어 있고 내부에

index.htmlmain.bundle.js 파일이 생성되어있습니다. html 파일을 열어보시면 결과는 다음과 같습니다.

image.png

이로써 필수 요구사항을 모두 만족한 React 프로젝트가 생성되었습니다.

선택 사항 - live Dev Server

다음으로 선택 사항 중 실시간 개발 서버를 적용해 보도록 하겠습니다.

$ npm install webpack-dev-server

설치가 완료되면 webpack.config.js 파일에 다음 설정을 추가해 주세요.

...

module.exports = {
    ...,
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './build',
        noInfo: true,
    open: true,
        port: 9000,
    after: function(app, server) {
                 app.listen(3000, function () {
                console.log("Webpack dev server is listening on port 9000");
            })
          }
    },
    plugins: [
        ...,
        new webpack.HotModuleReplacementPlugin()
    ]
    ...
}

저희가 설치한 webpack-dev-server 라이브러리는 express 기반의 개발 서버로 코딩의 변경 사항을 실시간으로 적용해서 보여주는 역할을 합니다.

package.json 에 다음과 같은 명령어를 추가하고 바로 실행해 보도록 하겠습니다.

"scripts": {
    ...,
    "start": "webpack-dev-server"
} 

npm run start 명령어를 커맨드 창에서 실행하면 브라우저가 켜지면서 실행 결과를 보여줍니다.

image.png

이제 index.js 파일을 변경하시면 변경사항이 바로 저장되는 것을 보실 수 있습니다.

마무리..


이제 React 프로젝트 셋팅을 완료 하였습니다.

다음 시리즈는 이 완성된 프로젝트를 사용하여 TDD를 이용한 컴포넌트 개발을 해보도록 하겠습니다.

긴 글 읽어주셔서 정말 감사합니다.