인프런 웹 게임을 만들며 배우는 React
강의를 듣고 정리함
이전까지는 각 컴포넌트를 만들 때 마다 html에 새로운 script태그를 생성해 작성했었다. 그런데 한 페이지에 컴포넌트가 엄청나게 많기 때문에 기존 방식으로는 html문서가 너무 길어져서 유지보수가 어렵고 가독성이 떨어진다. javascript에서는 module.exports
를 사용해 다른 파일의 객체를 불러올 수 있다.
기본적인 구조는 아래와 같다.
// npm 객체 불러오기
const React = require('react');
const { Component, useState, useRef } = React;
// hooks
const GuGuDan () => {
// state 설정
const [value, setValue] = useState('');
...
// 함수 만들기
const onChange = (e) => {
setValue(e.target.value);
}
...
// ref 사용하기
const inputRef = useRef(null);
// jsx 리턴
return (
// jsx 코드
);
}
// class
class GuGuDan extends Component () {
// 생성자: state 설정
constructor(props) {
super(props);
this.state = { value: '', ... };
}
// 함수 만들기
onChange = (e) => {
this.setState({
value: 'new value',
});
}
// ref 사용하기
input;
onRefInput = (c) => { this.input = c; }
// jsx 그리기
render () {
return (
// jsx 작성
);
};
}
// module로 만들어서 가져갈 수 있게 하기
module.exports = GuGuDan;
const React = require('react');
const ReactDom = require('react-dom');
// 다른 파일의 객체 불러오기
const GuGuDan = require('./GuGuDan'); // 현재 위치 기준 가져올 파일 경로
// ReactDom으로 html에 불러온 모듈 객체 넣어주기
ReactDom.render(<GuGuDan />, document.querySelector('#root'));
webpack
등장webpack.config.js
로 모든 것이 실행됨client.jsx
, GuGuDan.jsx
로 쪼개진 파일들을 app.js
에 통합할 예정app.js
에 코드가 자동생성된다. 타인이 알아보기 힘들게 난독화(Code Obfuscating)되어있다. webpack
webpack-cli
webpack.config.js
핵심 구성요소npm i -D 패키지명
으로 설치한다.@babel/core : 기본바벨
@babel/preset-env : 최신문법을 브라우저가 지원하는 옛날 문법으로 변경해줌
@babel/preset-react : react jsx 지원
@babel-loader : babel과 webpack 연결
"devDependencies": {
"@babel/core": "^7.17.8",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"babel-loader": "^8.2.4",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2"
}
webpack.config.js
작성하기// webpack.config.js
const path = require('path'); // 파일경로 조작하는 내장 라이브러리
// const { webpack } = require('webpack');
// 플러그인에 사용되는 npm 모듈
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
// webpack.config.js
// 1. npm 모듈
module.exports = {
// webpack 세팅 이 안에 작성
};
webpack.config.js
파일이 굉장히 복잡해진다.preset
, plugin
들을 지운 후 webpack을 빌드해보고 에러메시지가 뜰 때마다 하나씩 추가하면 이해하기 쉽다고 한다.// webpack.config.js
module.exports = {
name: 'webpack-setting-name',
mode: 'development', // 실 서비스 시: production
devtool: 'eval', // 실 서비스 시: hidden-source-map
resolve: {
extensions: [ '.js', '.jsx'], // entry.app에 불러올 파일 확장자 지정
},
entry: { // 사용할 모든 파일들. 다른 파일에서 불러와서 사용하는 파일들은 생략
// GuGuDan.jsx는 client.jsx에서 불러오니 패스
// resolve.extensions에서 확장자 지정하면 app에서 파일 확장자 생략 가능
app: ['./client'],
},
module: {
rules: [{
// 정규표현식 : js, jsx 파일에 룰 적용
test: /\.jsx?$/,
// webpack에서 jsx 읽기 위해 babel dusruf
loader: 'babel-loader',
options: {
// presets: plugin들의 모음
presets: [
'@babel/preset-env', '@babel/preset-react'
],
// plugin: 추가 기능을 위한 확장 프로그램
plugins: [],
},
}],
},
output: {
// __dirname: 현재 파일 경로
// path.join(a, b): a 경로에 b 폴더 생성 후 경로 반환
path: path.join(__dirname, 'dist'),
filename: 'app.js',
},
};
presets: [['preset1', {설정1: 값, 설정2: 값...}], 'preset2']
@babel/preset-env
는 설정 중요: preset-env
는 최신 코드를 각 브라우저에서 지원하는 옛날 문법에 맞게 바꿔주는 패키지. 지원할 브라우저만 따로 적어주면 webpack 빌드 시 자원을 많이 아낄 수 있다.// webpack.config.js
module: {
rules: [{
// 정규표현식 : js, jsx 파일에 룰 적용
test: /\.jsx?$/, loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
// 한국에서 점유율 5% 이상인 브라우저 전부 지원
browsers: [ '> 5% in KR'],
},
debug: true, // 개발 시 디버그설정
}],
'@babel/preset-react'],
plugins: [],
},
}],
},
@babel/preset-env
설정 후 webpack
실행 결과...
@babel/preset-env: `DEBUG` option
Using targets:
{
"chrome": "97",
"edge": "98",
"ios": "15.2",
"samsung": "16"
}
...
webpack.Loader~
대신 npm loader 모듈 직접 불러와서 사용const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
...
plugins : [
// 모든 loader.options에 debug: true 코드 삽입
new LoaderOptionsPlugin ({ debug : true })
],
output: { // app.js
path: path.join(__dirname, 'dist'),
filename: 'app.js',
},