웹팩 튜토리얼II

Eugenius1st·2022년 9월 26일
0

JavaScript

목록 보기
49/62
post-thumbnail

웹팩 튜토리얼II

튜토리얼을 이어서 진행하겠다. 이번 튜토리얼에서는 CSS까지 함께 작업해보겠다. 이전에 제작한 튜토리얼 앱은 CLI로만 작동했는데, 이제는 브라우저에서도 작동하도록 제작하려고 합니다. src/index.html 파일을 아래와 같이 간단하게 제작한다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Shout Lorem Ipsum</title>
</head>
<body>
  <div id="app"></div>
  <script src="index.js"></script>
</body>
</html>

src/index.js를 실행해보면 에러가 난다.

이는 매우 자연스러운 현상인데, require 문법은 Node.js 문법으로 브라우저에서 지원하지 않기 때문이다. create-react-app으로 이미 이런저런 프론트엔드 개발을 해오던 개발자는 당황할 수 있다. 더 최신 문법인 import, export도 지금까지 잘 써왔는데, require가 되지 않는게 모순적으로 느껴질 수 있다.

하지만 사실 create-react-appwebpack을 사용한다.

https://github.com/facebook/create-react-app#philosophy

Node.js에서만 작동할 법한 코드를 모든 브라우저에서 잘 작동할 수 있도록 번들링을 해주었기 때문에 잘 작동했던 것이다. index.html 파일을 dist 디렉터리로 옮겨서 번들 파일과 연결시키겠다.

<!-- dist/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Shout Lorem Ipsum Once</title>
</head>
<body>
  <div id="app"></div>
  <script src="app.bundle.js"></script>
</body>
</html>

src/index.js 도 단순히 console.log만 찍기 보다는, DOM 관련 코드를 조금 더 추가해서 브라우저에서 볼 수 있게 수정한다.

const _ = require("./underbar.js");

const shout = (...sentences) => console.log(...sentences);
const shoutToHTML = (...sentences) => {
  const app = document.querySelector("#app");
  app.append(
    ...sentences.map((sentence) => {
      const shoutHere = document.createElement("div");
      shoutHere.className = "shout";
      shoutHere.textContent = sentence;
      return shoutHere;
    })
  );
  return;
};

const loremIpsum =
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis egestas feugiat elit, ac tincidunt neque vestibulum at. Mauris a eros sit amet urna efficitur tempus.";

const shoutOnce = _.once(shout);
const shoutToHTMLOnce = _.once(shoutToHTML);

shoutOnce(loremIpsum);
shoutOnce(loremIpsum);
shoutOnce(loremIpsum);
shoutOnce(loremIpsum);

shoutToHTMLOnce(loremIpsum);
shoutToHTMLOnce(loremIpsum);
shoutToHTMLOnce(loremIpsum);
shoutToHTMLOnce(loremIpsum);

이렇게 src/index.js 에서 새롭게 작성한 코드는 dist의 app.bundle.js에 적용되지 않았기 때문에, 다시 npm run build 명령어로 번들링을 진행하고 나서 dist/index.html 을 열면 아래와 비슷한 화면을 확인할 수 있다.

웹페이지가 다소 밋밋해서, H1 요소를 추가하고 CSS를 적용해보겠다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>Shout Lorem Ipsum Once</title>
</head>
<body>
  <main>
    <h1>Shout Lorem Ipsum Once</h1>
    <div id="app"></div>
  </main>
  <script src="app.bundle.js"></script>
</body>
</html>
/* dist/style.css */
* {
  box-sizing: border-box;
  border: 0;
  padding: 0;
  margin: 0;
}

main {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

div.shout {
  padding: 12px;
  margin: 4px;
  border-radius: 8px;
  border: 0.5px solid gray;
}

webpack은 이렇게 JavaScript와 CSS를 함께 배포해야 할 때, 좀 더 쉽게 배포할 수 있게 로더(loader)를 제공한다. create-react-app에서 자유롭게 CSS를 import할 수 있었던 이유도 webpack에서 CSS를 불러올 수 있는 툴을 사용했기 때문이다.

dist/style.css 파일의 위치를 src/style.css 로 옮기고, 파일을 index.js 에서 불러와보자. 잘 불러왔는지 node src/index.js 명령으로 확인한다. Node.js는 그 자체만으로는 CSS를 읽을 수 없어 문법 에러가 발생한다.

// src/index.js
const _ = require('./underbar.js');
require('./style.css');

const shout = (...sentences) => console.log(...sentences);
const shoutToHTML = (...sentences) => {
  const app = document.querySelector('#app');
  app.append(...sentences.map(sentence => {
    const shoutHere = document.createElement('div');
    shoutHere.className = 'shout';
    shoutHere.textContent = sentence;
    return shoutHere;
  }))
  return;
};

const loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis egestas feugiat elit, ac tincidunt neque vestibulum at. Mauris a eros sit amet urna efficitur tempus."

const shoutOnce = _.once(shout);
const shoutToHTMLOnce = _.once(shoutToHTML);

shoutOnce(loremIpsum);
shoutOnce(loremIpsum);
shoutOnce(loremIpsum);
shoutOnce(loremIpsum);

shoutToHTMLOnce(loremIpsum);
shoutToHTMLOnce(loremIpsum);
shoutToHTMLOnce(loremIpsum);
shoutToHTMLOnce(loremIpsum);

webpack도 마찬가지입니다. 친절하게도 아래와 같은 에러 메시지를 출력한다.

You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See
https://webpack.js.org/concepts/#loaders

이 파일을 다루기 위해서는 적절한 로더가 필요하다. 현재 이파일을 처기하기 위한 로더가 설정되어 있지 않다.

에러에서 제공한 공식문서 링크에서 아래 로더 목록을 찾았다. 이번 튜토리얼에서 필요한 로더는 style-loader, css-loader이다. css-loader 는 CSS를 JS파일 내에서 불러올 수 있고, style-loader 는 불러온 CSS를 style 요소 내에 담아준다.

npm으로 두 로더를 설치하고, webpack.config.js 를 조정한다.

npm i -D css-loader style-loader
// webpack.config.js
const path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "app.bundle.js",
  },
  module: {
    rules: [
      {
				// 파일명이 .css로 끝나는 모든 파일에 적용
        test: /\.css$/,
				// 배열 마지막 요소부터 오른쪽에서 왼쪽 순으로 적용
				// 먼저 css-loader가 적용되고, styled-loader가 적용되어야 한다.
				// 순서 주의!
        use: ["style-loader", "css-loader"],
				// loader가 node_modules 안의 있는 내용도 처리하기 때문에
				// node_modules는 제외해야 합니다
        exclude: /node_modules/,
      },
    ],
  },
};

이후 npm run build 명령을 통해 번들링이 잘 되었는지 확인한다. 번들링이 성공한 모습을 확인하실 수 있습니다. 경고가 있어도 에러가 없으면 성공이다.

app.bundle.js 파일을 열어서 유심히 살펴보면 두 로더가 한 일을 얼추 파악할 수 있다. style 요소를 자동 생성하고 지금까지 작성한 CSS를 넣는 방식이다. (아래 화면을 보고 싶으면, VS Code의 Format Document 기능(alt + shift + F)를 사용하면 된다.)

dist/index.html 파일을 열어보니 style 요소가 생성되고 작성한 CSS가 담겨있는 모습을 확인하실 수 있습니다. 이젠 <link rel="stylesheet" href="style.css"> 코드는 필요없다.

webpack의 주요 컨셉 #2

로더에 대해서 정리하겠습니다.

loader는 JavaScript, JSON이 아닌 파일을 불러오는 역할을 한다.

profile
최강 프론트엔드 개발자가 되고싶은 안유진 입니다

0개의 댓글