[리액트] 프로젝트에 웹팩을 적용해보자 #2 (feat.타입스크립트)
이전 포스트에 이어서 계속 진행해보겠다.
일단 로그를 보자 webpack mode에 대한 WARNING과 React에 대한 ERROR 있다.
첫번째 WARNING은 webpack.config.js 안에 mode: "development" 값을 넣어서 처리하면 된다.
mode를 통해서 development 또는 production 으로 셋팅할 수 있다. 이 값을 통해 API 서버나 테스트 UI 또는 빌드된 파일을 변경하여 구성할 수 있다. 우리는 개발환경이니 developmenet로 설정한다.
두번째 React Error 는 어떤 것이 문제일지 생각해보자.
웹팩이 React를 읽어가면서 발생한 문제일 것이다. 하지만 생각해보니 우리의 웹팩 설정에는 리액트, 타입스크립트에 관련된 로더 설정이 없다. 우리가 리액트와 타입스크립트를 배우기로 자바스크립트로 변환하는 트랜스파일러가 필요하다고 배웠다.
그렇다면 공식문서를 좀 더 보기로 한다. 뒤쪽에 https://webpack.kr/guides/typescript/#root 타입스크립트 편이 있다.
문서를 읽어보니 tsx, ts파일을 읽기 위해서 ts-loader라는 것을 사용한다고 한다. 생각해보건데 ts-loader는 tsx, ts 파일을 자바스크립트로 변환하는 로더라고 생각하면 될 듯하다. 그래서 ts-loader를 쓰면 된다고 생각할 수 있다. (물론 써도 동작한다)
하지만 나는 babel-loader를 사용하기로 한다. babel-loader를 쓰는 이유는 여러 버전의 브라우저를 지원하기 위해서다.
우리는 다양한 브라우저를 지원하기 위해 babel를 통해 자바스크립트 버전을 낮춰야 한다. 이것을 위해 babel를 통해 변환을 하는데 별도의 babel를 설정하기보다 babel-loader 통해 webpack 빌드 과정에서 바로 변환하도록 한다.
// 설치
yarn add babel-loader -D
// or
npm install babel-loader --save-dev
설치를 하고 webpack.config.js의 rules에 추가한다.
그리고 babel 설정 파일인 .babelrc를 webpack.config.js와 같은 레벨의 폴더에 생성해준다.
그리고 다시 빌드해본다.
npx webpack
실패는 했지만 에러로그가 달라졌다.
ERROR in ./src/index.tsx 8:0-24
Module not found: Error: Can't resolve './App' in 'C:\Users\tmax-dev-kang\Documents\project\dividend\src'
우리는 기존의 entry 포인트로 index.tsx로 설정했다. 그래서 webpack이 명령 그대로 읽어가며 코드를 변환하고 있는데
src 폴더에서 App 파일을 못찾겠다고 한다. 이때 원인은 웹팩이 멍청해서라고 볼 수 있다.
우리는 vsc를 통해 import를 한다. 그리고 코드는 아래와 같이 되어있다.(일반적으로)
코드를 짠 우리는 import App from "./App" 이 App.tsx를 가리키고 있다는 것을 아는데 웹팩은 모른다. 그래서 저런 경우에 webpack에 확장자로 가능한 리스트를 건네주어서 없는 경우 찾아서 써봐~~라고 말해줄 필요가 있다.
그걸 webpack 설정에서 resolve라는 값으로 설정할 수 있으며 코드는 다음과 같다.
이제 다시 npx webpack
또 다시 에러로그가 달라졌다.
기존에 App를 못찾겠다는 에러는 사라졌고 webpack이 App.tsx를 타고 더 깊게 들어간 듯하다.
하지만 이번에는 34 errors가 생겼고 모든 로그들을 살펴보니 코드들이 절대 경로로 표시된 경우에서 발생했다.
src/component....
해당 에러가 발생하는 원인은 웹팩기준으로 특정 파일의 상대경로는 파악은 쉽지만 절대경로는 파악하기 어렵기 때문이다. 절대경로는 파일의 시작 지점을 알아야 한다.
우리는 시작지점을 src로 판단하고 개발했지만 웹팩은 모른다. 그래서 이것도 알려줘야 한다.
이제 다시 npx webpack
다행스럽게도 드디어 빌드가 완료되었다.
이제 output 포인트로 설정한 dist 폴더로 가서 파일을 살펴보자.
코드들이 묶인 bundle.js와 폰트 파일들 그리고 png파일이 몇 개 보인다.
dist 안에 있는 파일들을 확인하려면 html이 있어야 하니 dist 폴더 안에 index.html를 만들어 확인해보자
<!--dist/index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Dividend(Dev)</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>
이제 vsc 익스텐션 통해 열어보자.
내 프로젝트 기준으로 정상 동작을 확인했다.
근데 지금 상황을 보면 불편함이 있다. webpack 공식문서를 자세히 본 사람은 알겠지만
일반적으로 webpack 플러그인을 통해 기존의 dist 파일을 삭제하고 매번 빌드할 때마다 dist파일을 만들기를 권고하고 있다. 이렇게 하는 이유는 사라진 파일과 새롭게 만들어진 파일의 충돌을 피하기 위해서라고 한다.
그러면 dist 안에 있는 파일은 전부다 삭제될 것이고 우리는 매번 index.html 파일을 만들어서 확인해야 하는 귀찮음이 생긴다. 이런 귀찮음을 없애기 위해 webpack은 html-webpack-plugin를 제공한다.
해당 플러그인의 template 기능을 통해 기존에 미리 만들어놓은 index.html를 가져다가 사용할 수 있게 한다. 또한 해당 플러그인을 통해서 빌드된 파일의 title, favicon 등을 설정할 수도 있다.
template는 src/public 에 위치해 있다고 설정했고 기본적으로 CRA로 프로젝트를 만들면 처음 보이는 React 마크가 빙빙 돌고 있는 화면이다. (해당 폴더 or 코드를 삭제했다면 새롭게 만들어서 설정해도 상관없다)
<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="root"></div>
</body>
</html>
아주 기본적인 것만 세팅했다. 여기에서 title, favicon 등을 설정해도 되고 플러그인을 통해 설정해도 된다. 다만 테스트해보지 않았지만 둘 중에 하나는 씹힐 것이다.
아무튼 body안에서 react가 처음으로 접근하는 root div만 만들어주면 된다. 스크립트 코드는 웹팩이 만들어서 넣어줄 것이다.
이전과 달리 index.html이 기본적으로 생성된 것을 확인할 수 있고
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>title</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script defer src="main.bundle.js"></script></head>
<body>
<div id="root"></div>
</body>
</html>
코드를 보면 script가 생성된 것을 볼 수 있다. ( 추가로 볼 것은 title 태그에 title이 입력된 점이다. 플러그인보다 template가 후에 동작한 듯하다 )
이로써 webpack으로 빌드하기가 완성되었다.
다음 포스트에서는 리액트를 개발하기 위한 webpack-dev-server의 새로운 모습인 webpack serve를 적용하고 핫로딩을 적용해보도록 하자