리액트를 공부하기 시작하면서 흔히 CRA을 이용해서 리액트 프로젝트를 만들기 시작한다.
만일 CRA를 이용하지 않으면 어떻게 리액트 프로젝트를 구성할지 막막한 사람들에게 공유하고자 이번 글을 번역했다.
물론 나에게도...
리액트 프로젝트를 여러 번 경험한 사람에게도 리액트 프로젝트를 밑바닥에서부터 생성하고 설정하는 것은 쉬운 일이 아닙니다. 그런 이유로 보통 우리는 create-react-app이라는 도구를 사용합니다. 명령어로 간편하게 필요한 보일러플레이트를 설치할 수 있습니다. 그 후로 바로 애플리케이션 코드를 작성할 수 있습니다.
리액트를 처음 시작하는 사람 혹은 프로젝트를 설정하는 데에 많은 시간을 쓰기를 원하지 않는 사람들에게는 create-react-app이 매우 매력적인 선택지입니다. 하지만, create-react-app의 도움 없이 어떻게 리액트 프로젝트를 설정할 수 있는지 알아보는 것 또한 매우 흥미로울 것입니다.
이 방법은 CRA에서 단순히 명령어를 실행시키는 것만큼 쉽지는 않습니다. 하지만 여러분들의 개발 커리어에 나름 도움이 되고 쓸모가 있을 거라 확신합니다. 또한, 이 가이드를 통해서 여러분들만의 보일러플레이트를 만들 수도 있고 create-react-app에서 불필요하다고 생각되는 것들을 없앨 수도 있을 겁니다.
이번 가이드에서는 프로젝트에 특정한 프로젝트 구조를 사용하지는 않을 예정입니다. 왜냐하면 프로젝트 구조는 개발자들마다 생각이 다 다르고 다른 환경에서 일을 하기 때문입니다. 그래서 여러분들이 선호하는 프로젝트 구조를 사용하시면 됩니다! :)
자 그러면 본격적으로 시작하겠습니다.
Step 1: Creating the folder that will host our project
새로운 디렉터리를 생성해보겠습니다.
mkdir my-react-project
생성이 되면 해당 디렉터리로 이동하겠습니다.
cd my-react-project
Step 2: Initializing the project
프로젝트를 초기화하기 위해서 npm명령어를 실행시키도록 하겠습니다.
npm is a package, version and dependencies manager made for JavaScript. If you haven't installed npm yet, you need to directly install Node.js, since they work together and npm is included in Node.js installation as well. Node.js will let us execute JavaScript on server side.
// npm 뿐만 아니라 yarn 혹은 bower와 같은 다른 패키지 매니저를 사용하셔도 됩니다.
npm과 Node.js가 설치되어있다고 가정하고 아래 명령어를 실행시키겠습니다.
npm init
위 명령어는 package.json이라고 하는 파일을 생성시킬 것입니다. 해당 파일에는 디펜던시와 스크립트들을 명시할 수 있습니다.
파일을 생성할 때에, 터미널에서는 새로운 프로젝트의 정보과 관련하여 몇 가지 질문들을 합니다. 만약에 스킵하고 싶다면 엔터 키를 연달아서 치시면 됩니다. 혹은 프로젝트를 생성할 때 아래와 같이 명령어를 칠 수도 있습니다.
npm init -y
생성된 package.json은 아래와 같이 생길 것입니다.
{
"name": "my-react-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Step 3: Installing dependencies
리액트 어플리케이션을 만들기 위해서는 몇 가지 디펜던시들을 설치해야 합니다.
React dependencies
react
: 리액트 자바스크립트 라이브러리react-dom
: DOM 엘리먼트를 관리하기 위한 패키지react-router-dom
: 리액트 라우터의 DOM 바인딩을 포함하는 라이브러리
npm install react react-dom react-router-dom
Webpack dependencies
또한, 우리 프로젝트가 웹상에서 원활하게 돌아가게 하기 위해서는 모듈 번들러가 필요로 합니다. 웹팩은 프로젝트 내의 모든 자바스크립트 파일들을 번들링 하고 브라우저에서 돌아가도록 필요한 자원들을 준비해줍니다.
우리는 개발 환경에서만 웹팩이 필요하기 때문에, 관련 디펜던시들을 --save-dev 혹은 -D 옵션을 이용하여 설치하도록 하겠습니다.
webpack
: 번들러webpack-cli
: 웹팩 CLI
npm install --save-dev webpack webpack-cli
Babel dependencies
바벨은 자바스크립트 컴파일러입니다. 자바스크립트 ES6을 ES5로 변환시켜줍니다. 왜냐하면 현재 모든 브라우저가 ES6를 지원하지 않기 때문입니다.
@babel/core
: 바벨 컴파일러 코어@babel/preset-react
: 리액트 기능들을 지원하는 플러그인들을 포함하는 패키지
npm install --save-dev @babel/core @babel/preset-react
의도한 대로 자바스크립트 파일들을 변환하기 위해 바벨을 설정해야 합니다.
먼저, 터미널에서 설정 파일을 생성해줍니다.
touch .babelrc
다음으로 아래 코드들을 추가합니다..babelrc
{
"presets": [
"@babel/preset-react"
]
}
Loaders for Webpack
웹팩은 파일들을 전처리하기위해 로더(loaders)가 필요합니다. 자바스크립트 파일 이외의 정적 리소스들을 번들링 하는데 유용합니다.
babel-loader
: Babel용 로더html-loader
: HTML용 로더style-loader
: DOM에 스타일을 주입하는 로더css-loader
: CSS용 로더sass-loader(*)
: SASS/SCSS용 로더
(*) sass-loader가 반드시 필요한 것은 아닙니다. CSS 전처리기를 사용하는 경우에 필요합니다. 마찬가지로 LESS, PostCSS, Stylus 등을 위한 로더가 존재합니다.
npm install --save-dev babel-loader html-loader style-loader css-loader sass-loader
Webpack plugins
번들링을 할 때에 웹팩 플러그인이 필요합니다.
html-webpack-plugin
: 번들들을 제공하는 HTML 파일을 만들 때 필요합니다.
Note: 프로덕션 빌드 환경에서는 MiniCssExtractPlugin을 사용하는 것을 추천합니다. 해당 플러그인은 CSS를 별도의 파일로 추출하고 CSS가 포함된 모든 자바스크립트 파일에 대해 파일을 생성합니다.
로더와 플러그인의 차이점은 로더는 스타일을 <style> 태그
안에 설정하지만, 플러그인은 <link> 태그를
이용해서 외부 파일을 HTML에 연결합니다.
Server dependencies
우리 어플리케이션은 서버를 필요로 합니다. 그래서 서버와 관련된 디펜던시 또한 설치해야 합니다.
express
: Node.js 프레임워크. 서버 파일을 만들고 서버 리퀘스트를 처리하는데 필요합니다.nodemon
: 파일 디렉터리에 변화를 감지하여 서버를 리프레쉬합니다.
npm install express
npm install --save-dev nodemon
Step 4: Configuring Webpack
다음 단계는 설정 파일에 웹팩 로더와 플러그인을 넣는 것입니다. 번들 과정에서 어떻게 행동해야 하는지 알려주는 과정입니다.
설정 파일을 만들어줍니다.
touch webpack.config.js
설정 파일을 채우기 전에, 실제로 웹팩이 어떻게 동작하는지 확인해봅시다.
먼저, 웹팩에게 우리 어플리케이션의 entry point을 알려주어야 합니다. 이 entry point는 index.js라고 하는 자바스크립트 파일이 될 것입니다.
또한, output file을 명시해야 합니다. 최종적으로 번들된 자바스크립트 파일이 될 것입니다. 그리고 HTML 파일에 삽입되는 유일한 파일이 될 것입니다.
이 지점에서 dist 폴더가 중요합니다. 이 폴더는 번들링 과정의 한 부분으로 생겨나는 디렉터리입니다. 해당 폴더에는 번들링의 결과로 생겨나는 정적 파일들이 저장됩니다.
웹팩이 파일의 타입에 따라 적절하게 변환해주어야 합니다. 우리는 자바스크립트, HTML, CSS 그리고 SASS/SCSS을 변환합니다. 그러나 추후에 만일 이미지, 폰트와 같은 다른 종류의 파일들을 다룰 일이 있다면 해당 파일에 맞는 로더들이 필요로 합니다.
마지막으로, 우리는 필요한 플러그인들을 설정해주어야 합니다. HtmlWebpackPlugin, 브라우저로 제공될 HTML을 만들어 주는 플러그인을 설정해주어야 합니다.
webpack.config.js
const path = require("path")
const webpack = require("webpack")
const HTMLWebpackPlugin = require("html-webpack-plugin")
module.exports = {
entry: "./index.js",
output: {
filename: "bundle.js",
path: path.resolve("dist"),
publicPath: "/",
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: "babel-loader"
},
{
test: /\.html$/,
use: "html-loader"
},
/* plain CSS를 사용한다면 첫번째를,
css 전처리기를 사용한다면 두번쨰를 사용하시면 됩니다.*/
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader"
]
},
]
},
plugins: [
new HTMLWebpackPlugin({
template: "index.html"
}),
]
}
Step 5: Creating the HTML template
간단한 HTML 파일을 생성합니다. 이 템플릿 파일은 HTMLWebpackPlugin에 의해 새로운 파일로 생성됩니다.
index.html
<html>
<head>
<title>My React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
Step 6: Creating the server
서버로 사용할 자바스크립트 파일을 만들겠습니다. 포트를 열고 몇 가지 설정을 한 후에 요청을 만들어보겠습니다.
touch app.js
우리는 이 파일을 app.js라고 부르겠습니다. 물론, 원하는 이름대로 해도 상관은 없습니다. 하지만, 대문자만 조심해주세요. 그 이유는 곧 알게 되실 겁니다.
app.js
const express = require("express");
const app = express();
const path = require("path");
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`The app server is running on port: ${port}`);
});
const DIST_DIR = path.join(__dirname, "dist");
const HTML_FILE = path.join(DIST_DIR, "index.html");
app.use(express.join());
app.use(express.static("public"));
app.use(express.static("dist"));
app.get("/", (req, res) => {
res.sendFile(HTML_FILE, function(err) {
if (err) {
res.status(500).send(err);
}
});
});
3000번 포트를 통해 연결하는 새로운 서버를 시작합니다. 그런 다음, 웹팩에 의해 생성된 HTML 파일을 루트 URL로 보냅니다. (즉, 이 HTML 파일이 우리 어플리케이션의 홈페이지입니다.) 마찬가지로, public*과 *dist 디렉터리 또한 URL을 통해 파일들을 제공할 수 있습니다.
Step 7: Creating the React app
이제 App.js파일을 생성하겠습니다. 이 파일이 바로 우리 리액트 어플리케이션의 메인 컴포넌트입니다. (대문자가 사용되었습니다!)
App.js
import React from "react";
const App = () => {
return <div>Hello, World!</div>;
};
export default App;
이 컴포넌트의 렌더링은 아까 위에서 언급된 HTML 파일에 주입됩니다. 결국 우리는 브라우저를 열었을 때 Hello, World를 볼 수 있게 되는 겁니다.
어떻게 이게 가능한지 한번 살펴보겠습니다.
Step 8: Creating the entry point for the React app
이번 단계에서는 우리 앱의 라우팅을 지정하고 DOM에서 React의 콘텐츠가 삽입되는 위치를 지정합니다.
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import App from "./App.js";
import "./styles.scss";
const appRouting = (
<Router>
<Switch>
<Route exact path="/" component={App} />
</Switch>
</Router>
);
ReactDOM.render(appRouting, document.getElementById("root"));
URL의 경로가 정확히 루트일 때, App 컴포넌트가 렌더링 되도록 알려주었습니다. 또한, 렌더링 되는 콘텐츠들이 인덱스 도큐먼트에 아이디가 root인 태그 안으로 위치하도록 했습니다.
Step 9: Defining the scripts
이제 scripts를 셋업 하도록 하겠습니다. 이를 통해 우리 앱을 빌드하고 구동할 수 있도록 하겠습니다.
다시 package.json으로 돌아와 오면 아래와 같은 부분이 있습니다.
{
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
...
}
이제 run 명령어와 build 명령어를 추가하도록 하겠습니다.
{
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rm -rf dist && webpack --mode development",
"dev": "nodemon app.js"
}
...
}
Step 10: Builiding and running our app
마지막 단께로 빌드와 구동입니다.
먼저 아래 명령어를 통해 번들링을 시작합니다.
npm run build
그 후에, 서버를 구동합니다.
npm run dev
이제 우리 앱은 localhost:3000
에서 준비가 완료되었습니다!
이제 우리가 직접 설정한 리액트 어플리케이션이 준비가 완료되었습니다!
이번 튜토리얼 여러분들에게 도움이 되셨으면 좋겠습니다.
감사합니다!
'개발 > Frontend' 카테고리의 다른 글
[번역] Virtual DOM 이 뭔데? (한번 만들어보기!) (0) | 2021.06.06 |
---|