1. Github+ Jenkins+Docker+React.js
0. 시작
기존에 개발하였던 React.js 포트폴리오 웹사이트의 빌드 자동화를 위해 Jenkins와 도커를 사용해보는 작업을 진행해보았다.
진행 순서는 다음과 같다.
React.js+Webpack 번들링 → Jenkins + VPS → Jenkins+Github 연동 → Webhook으로 자동 빌드 배포
Docker는 전체적인 세팅이 끝나면 차차 추가할 예정이다. 최종적으로는 도커까지 모두 연결되어 자동 빌드 배포를 할 수 있게 하는 것이다.
1. 사전 준비
React.js 와 같은 경우, 웹팩을 통해 번들링을 수행해주어야 하기 때문에 Webpack 번들링 가능 여부를 먼저 확인할 필요가 있다.
또한 Jenkins와 도커를 사용하게 될 경우 서버에서 사용하는 램이 1기가를 넘기 때문에 기존의 Hostinger VPS 사양으로는 이용할 수 없었다. 때문에 2기가로 업그레이드를 진행하였다.(메모리를 swap하는 방법도 있지만, Hostinger에서는 별도의 스왑 기능을 허용하지 않는다. AWS 는 가능한 것으로 보인다.)
2. React.js + Webpack
처음부터 Webpack이 설정되어있는 프로젝트로 시작하여 개발했으면 좋았겠지만, 이렇게 확장하게 될 줄은 미처 고려하지 못했다. 때문에 이제라도 급하게 Webpack을 적용해두기로 했다.
Loader
웹팩에서는 자바스크립트 모듈 뿐만 아니라 웹 앱을 구성하는 모든 자원을 모듈이라고 부른다. HTML,CSS, JS, 이미지, 폰트 등등등 모두 모듈로 보기 때문에 import 구문을 사용하면 자바스크립트 코드 안으로 가져올 수 있다.
이를 가능하게 하는 것이 Loader의 역할이다.
현재 사용하고 있는 모듈 중에는 GLB나 GLTF와 같은 3D 오브젝트도 포함이 되어 있다. 해당 오브젝트들 또한 빌드 시에 함꼐 포함되도록 해야 한다.
React에 Webpack 추가하기
-
Webpack 설치
npm install react react-dom # 설지 안되면 --force 붙이기 npm install --save-dev webpack webpack-cli
-
추가 loader 설치
"devDependencies": { "copy-webpack-plugin": "^11.0.0", "html-webpack-plugin": "^5.5.3", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" } //여기에 babel-loader도 추가로 설치를 진행하였다.
-
루트 경로에 webpack.config.js 파일 생성
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { mode: "development", entry: "./src/index.js", //루트 index.js 위치 output: { path: path.resolve("./dist"), //빌드 결과 생성 폴더 경로 filename: "[name].js", }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env", "@babel/preset-react"], }, }, }, { test: /\.css$/, use: ["style-loader", "css-loader"], }, { test: /\.s[ac]ss$/, use: ["style-loader", "css-loader", "sass-loader"], // 로더는 한 파일에 여러개가 실행될 때 뒤에서 부터 앞으로 실행된다. }, { test: /\.(woff(2)?|ttf|eot|svg|jpg|jpeg|png|glb|gltf)(\?v=\d+\.\d+\.\d+)?$/, use: [ { loader: "file-loader", options: { name: "[name].[ext]", outputPath: "assets/", }, }, ], }, { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: "babel-loader", options: { presets: [ "@babel/preset-env", ["@babel/preset-react", { runtime: "automatic" }], ], }, }, }, { test: /\.json$/, loader: "file-loader", type: "javascript/auto", options: { name: "[name].[ext]", }, }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "./public/index.html", favicon: "./public/favicon.ico", }), ], resolve: { extensions: [".js", ".jsx"], }, devServer: { static: path.join(__dirname, "dist"), port: 9000, }, };
-
gltf와 glb 파일들을 포함시키기 위해 glb gltf와 같이 추가하였다. - menifest 에러 발생을 해결하기 위해 마지막 test: /.json$/,을 추가해보았지만, 해결 방법은 아니었다.
- favicon이 빌드 뒤에 dist에 포함되지 않아 plugins에 다음과 같이 추가했다.
-
-
package.json 수정
"start": "webpack-dev-server --mode development --config ./webpack.config.js", "build": "webpack --mode production --config ./webpack.config.js",
위와 같이 추후 젠킨스에서 build를 수행할 때 webpack.config.js를 기반으로 빌드할 수 있도록 변경한다. 해당 빌드 결과가 제대로 빌드되었는지 확인하기 위해 start 또한 다음과 같이 변경해두면 dist 파일 하위에 빌드된 파일을 실행시킬 수 있다.
하는 동안 생겼던 여러 이슈사항들 정리
# console Error
Manifest: Line: 1, column: 1, Syntax error.
# 해결방법
public 폴더의 <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />를
<link rel="/manifest" href="%PUBLIC_URL%/manifest.json" />로 변경해준다.
## glb 포함이 안되는 현상
위와 같이 glb, gltf 파일 형식을 지정해주어도 포함되지 않을 경우, 이는 import 형식이 아닌 코드에
직접 경로를 작성하여 발생된 문제일 수 있다.
예) useGLTF(/scroll.glb)
##해결방법
import를 통해 가져오는 방식으로 변경해준다.
import ScrollOBJ from "../assets/scroll.glb"
useGLTF(/ScrollOBJ)
### favicon이 함께 빌드되지 않는 문제
### 해결방법plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
favicon: './public/favicon.ico'
}),
],
위와 같이 favicon 옵션 추가해주기