웹팩을 쓰는이유?
개발을 실제로 할때 HTML파일 하나만 있어도 자바스크립트를 쓸수 있지만 실제 실무에서는 컴포넌트가 하나가 아니다.
컴포넌트가 20개라고 치면 하나의 HTML파일에 엄청나게 긴 코드가 있을것이고 코드의 유지보수가 매우 힘들어질 것입니다.
페이스북으로 예를 들면 페이스북의 컴포넌트는 20000개가 넘는다고합니다(지금은 바뀌었을수도 있습니다)
<script type="text/babel" src="index.js">와 같이 스크립트를 가져오게 되면 스크립트간에 중복이 발생합니다.
개발자의 원칙은 중복을 제거해야됩니다.
중복제거가 쉽지가 않습니다.
소크라라는 사람이 웹팩이라는 시스템을 만들어 냅니다
여러개의 자바스크립트 파일을 한번에 합쳐서 하나의 자바스크립트 파일로 만들어주는 역할을 하는 것이 웹팩입니다.
합치면서 바벨도 적용할수 있고 필요없는 코드를 제거할수도 있습니다.
웹팩을 알려면 노드도 알아야합니다!
노드는 서버나 백엔드를 담당하는 것이 아닌 자바스크립트 실행기라고 이해하시면 되겠습니다.
리액트를 하기 위해서는 웹팩을 돌리기 위한 자바스크립트 실행기가 필요하기 때문에 노드가 필요하다고 생각하시면 이해가 편하실겁니다.
먼저 터미널을 생성하시고 npm init이라는 명령어를 쳐주세요!(노드 깔려있어야합니다)
npm init
저는 끝말잇기 폴더 안에서 실행했습니다.
npm init을 실행하면 가장먼저 패키지 이름을 적으라는 내용이 나오는데 한글은 안되나봅니다..
저는 그냥 cine로 하겠습니다!
그러면 package.json 파일이 생기네요.
여기에 리액트 개발에 필요한 패키지를 넣어주겠습니다.
npm i react react-dom
설치를 하니까 디펜던시가 추가 되었네요!
웹팩도 설치할게요!!
npm i -D webpack webpack-cli
리액트 개발을 할때 필요한 웹팩을 설치했습니다.
-D 옵션이 붙는것은 배포할때 말고 개발할때만 쓰겠다는 의미이며 웹팩의 경우 개발할때만 필요합니다.
디펜던시스도 추가 되긴 하였지만 dev디펜던시스로 따로 추가가 되었습니다.
client.jsx
원래는 class를 이런식으로 작성해도 되지만 클래스가 많아질경우 유지보수가 어려워 지기 때문에 WordRelay를 따로 만들어 주겠습니다.
const React = require('react');
const ReactDom = require('react-dom');
const WordRelay = require('./WordRelay'); // 경로 맞춰주셔야합니다.
ReactDom.render(<WordRelay />, document.querySelector('#root'));
const WordRelay = require('./WordRelay');은 따로 분리시켜줄 WordRelay파일을 끌어오기 위해 사용하였습니다.
WordRelay.jsx
const React = require('react');
const { Component } = React;
class WordRelay extends Component{
state = {
};
render() {
}
}
module.exports = WordRelay;
따로 분리를 시킨 WordRelay에서도 React를 불러와야합니다.
클래스 부분의 경우 class WordRelay extends React.Component라고 써주어야하지만 윗쪽에
const { Component } = React; 를 작성해 줌으로서 class WordRelay extends Component로 줄일수 있습니다.
module.exports = WordRelay; 도 추가로 작성해주셔야 다른 파일에서 해당 파일을 끌어다 쓸때 ㅍ리요한 코드입니다.
index.html
<html>
<head>
<meta charset="UTF-8">
<title>끝말잇기</title>
</head>
<body>
<div id="root"></div>
<script src="./dist/app.js"></script>
</body>
</html>
index에서 보면 문제가 script에서 js파일을 하나만 끌어올수 있다는 것입니다.
웹팩을 이용해 js파일들을 하나로 묶어주기 위함이라고 했었죠??
webpack.config.js
const path = require('path'); // 노드에서 경로를 쉽게 가져오도록 도와주는 것
module.exports = {
name: 'word-relay-setting', // 사실은 필요없음
mode: 'development', // 실서비스에서는 production으로 변경
devtool: 'eval', // 빠르게 하겠다
resolve: {
extensions: ['.js', '.jsx']
},
entry: {
app: ['./client'],
}, // 입력
output:{
path: path.join(__dirname, 'dist'),
filename: 'app.js'
}, // 출력
};
module.exports안에 몇가지 설정을 해주어야합니다.
name은 굳이 필요없지만 그냥 작성해주겠습니다.
mode: 'development' 는 실서비스를 할때는 production으로 변경해줍니다.
devtool: 'eval' 는 빠르게 하겠다는 의미라고 합니다.
resolve: {
extensions: ['.js', '.jsx']
},
의 경우는 entry 안에 app: ['./client']에서 client뒤에 확장자 명을 생략해주기 위해서 작성해주는 것입니다.
entry 의 경우 입력을 담당합니다.
또한 entry안에서 client.jsx가 WordRelay.jsx를 불러 오고 있기 떄문에 WordRelay.jsx는 작성하지 않아도됩니다.
output은 출력을 담당합니다.
path의 경우 dist의 실제 경로는 C:... 이지만 path.join를 사용함으로서 현재 폴더의 dist폴더를 말합니다.
path를 사용함으로서 경로를 알아서 합쳐주게 되는것이죠
터미널창에서 webpack이라는 명령어를 사용하면 에러가 발생합니다.
webpack이라는 명령어를 등록을 해주거나 package.json의 scripts부분에 작성해주어야합니다.
package.json
이렇게 작성해주면 npm run dev 명령을 사용하여 실행할수 있습니다.
또 npx webpack을 사용해서 실행할수도 있습니다.
이 명령어를 실행하면 dist폴더 안에 app.js파일이 생깁니다.
뭔가 이해하기는 힘들겠지만 webpack으로 jsx파일들을 묶어줬나봅니다.
entry를 읽어서 app.js에 한파일로 만들어 주었습니다.
근데 실행을 하면 에러가 발생합니다.
ReactDom.render(<WordRelay />, document.querySelector('#root'));
해당 부분을 이해할수 없다는 에러입니다.
JSX를 사용하기 위해서는 바벨을 가지고 왔었죠??
웹팩에도 바벨이라는 것을 추가해주고 처리해줍니다.
또 바벨안에서도 JSX를 설정을 해주어야합니다.
우선 바벨을 설치해볼까요??
npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader
babel-core라는 것은 바벨의 기본적인것이 들어있는 것이고 babel/preset-env가 브라우저에 맞게 최신문법도 옛날 문법을 지원해줍니다.
babel/preset-react를 받아야 JSX를 인식할수 있습니다.
babel-loader는 babel과 webpack을 연결해줍니다.
이제 다시 웹팩을 설정하겠습니다.
webpack.config.js
module를 작성합니다.
module은 entry의 파일을 읽고 모듈을 적용해서 output으로 뺀다고 이해하실수 있습니다.
rules는 여러개의 규칙을 적용할수 있기 때문에 배열로 적용합니다.
(에러가 나시는 분들은 npm i -D @babel/plugin-proposal-class-properties 해주세요)
이제 WordRelay.jsx파일을 이렇게 수정한뒤 실행시켜 주시면
실행이 됩니다!
이제 본격적으로 끝말잇기 게임을 만들어볼까요??
const React = require('react');
const { Component } = React;
class WordRelay extends Component{
state = {
word: '네이버',
value: '',
result: '',
};
onSubmitForm = (e) => {
e.preventDefault();
if(this.state.word[this.state.word.length -1] === this.state.value[0]){
this.setState({
result: '딩동댕',
word: this.state.value,
value: '',
});
this.input.focus();
} else {
this.setState({
result: '땡',
value: '',
});
this.input.focus();
}
};
onChangeInput = (e) => {
this.setState({ value: e.target.value});
};
input;
onRefInput = (c) => {
this.input = c;
};
render() {
return (
<>
<div>{this.state.word}</div>
<form onSubmit={this.onSubmitForm}>
<input ref={this.onRefInput} value={this.state.value} onChange={this.onChangeInput} />
<button>입력!</button>
</form>
<div>{this.state.result}</div>
</>
)
}
}
module.exports = WordRelay;
구구단 때와 마찬가지로 해당 코드를 작성하여 실행하면 끝말잇기 게임이 실행됩니다!
'SPA > React' 카테고리의 다른 글
[React] 게임으로 배우는 리액트 - 반복문 (map, key) (0) | 2022.06.01 |
---|---|
[React] 게임으로 배우는 리액트 - import와 require 비교 (0) | 2022.05.31 |
[React] 게임으로 배우는 리액트 - Hooks (0) | 2022.05.29 |
[React] 게임으로 배우는 리액트 - ref로 초점맞추기 (0) | 2022.05.28 |
[React] 게임으로 배우는 리액트 - Fragment, setState (0) | 2022.05.27 |