<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>C-log</title>
    <link>https://hi-code.tistory.com/</link>
    <description>vlog는 video, 영상으로 남기는 일상을 의미한다. 
C-log는 내가 만들어낸 언어로 Code를 통해 나의 일상을 남기는 기록이란 뜻이다.
 &amp;zwj; </description>
    <language>ko</language>
    <pubDate>Thu, 20 Aug 2026 15:51:31 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>4:Bee</managingEditor>
    <image>
      <title>C-log</title>
      <url>https://tistory1.daumcdn.net/tistory/4455772/attach/6bc8038ff9f14b0997db6645c2438f3d</url>
      <link>https://hi-code.tistory.com</link>
    </image>
    <item>
      <title> Webpack : 자주 사용되는 Babel Plugin(Preset)</title>
      <link>https://hi-code.tistory.com/425</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이번 포스팅에서는 지난 시간에 이어서 자주 사용되는 Preset을 설치해보고 실습해볼 것이다. Babel은 보통 실무에서 Preset을 잘 사용한다. 따라서 preset-env, preset-flow, preset-react, preset-typescript 이렇게 네가지를 중점으로 살펴 볼 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;preset-env&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치는 다음과 같이 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1725004740859&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:: CMD

yarn add @babel/preset-env&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 babel.config파일에서 기존에 사용하고 있던 커스텀 babel은 주석처리하고 다음과 같이 추가를 해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1725004842503&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//babel.confing.js

const myBabelPreset = require('./my-babel-preset');
module.exports = {
  presets: [
    '@babel/preset-env'
  ]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리과 다음과 같이 명령어를 실행하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1725005040419&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

yarn babel src/app.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1725005068408&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

&quot;use strict&quot;;

function _typeof(o) { &quot;@babel/helpers - typeof&quot;; return _typeof = &quot;function&quot; == typeof Symbol &amp;amp;&amp;amp; &quot;symbol&quot; == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o &amp;amp;&amp;amp; &quot;function&quot; == typeof Symbol &amp;amp;&amp;amp; o.constructor === Symbol &amp;amp;&amp;amp; o !== Symbol.prototype ? &quot;symbol&quot; : typeof o; }, _typeof(o); }
var math = _interopRequireWildcard(require(&quot;./math.js&quot;));
require(&quot;./app.css&quot;);
function _getRequireWildcardCache(e) { if (&quot;function&quot; != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r &amp;amp;&amp;amp; e &amp;amp;&amp;amp; e.__esModule) return e; if (null === e || &quot;object&quot; != _typeof(e) &amp;amp;&amp;amp; &quot;function&quot; != typeof e) return { &quot;default&quot;: e }; var t = _getRequireWildcardCache(r); if (t &amp;amp;&amp;amp; t.has(e)) return t.get(e); var n = 
{ __proto__: null }, a = Object.defineProperty &amp;amp;&amp;amp; Object.getOwnPropertyDescriptor; for (var u in e) if (&quot;default&quot; !== u &amp;amp;&amp;amp; {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i &amp;amp;&amp;amp; (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n[&quot;default&quot;] = e, t &amp;amp;&amp;amp; t.set(e, n), n; }
var alert = function alert(msg) {
  return window.alert(msg);
};
// import npmIcon from './npm-icon.png';
// import { sum } from './math.js';
console.log(math.sum(1, 2));
// console.log(sum(1,2));

// document.addEventListener('DOMContentLoaded', () =&amp;gt; {
//   document.body.innerHTML = `&amp;lt;img src=&quot;${npmIcon}&quot;/&amp;gt;`
// });

console.log(process.env.NODE_ENV);
console.log(api.domain)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 확인해본 결과 이전과 매우 유사한 결과가 나온다는 것을 알 수가 있다. 이에 이전에 커스텀했던 방식인 'use Strict'모드와 '일반 함수로 변환'과 'let을 var로 변환'해주는 것 등을 위의 플러그인 하나로 모든 것이 해결 된다는 것을 우리는 알 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;preset-env는 무엇인가&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;타겟 브라우져(TargeBrowser)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 우리 코드가 크롬 최신 버전만 지원한다는 가정에서 다른 익스플로러와 같은 변환은 불필요하기에 설정된 target만을 위한 최적의 코드들을 출력, 설정해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1725005517908&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const myBabelPreset = require('./my-babel-preset');

module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: {
        chrome: '79'
      }
    }]
  ]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 또한 잘 출력된다.('더보기 클릭')&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;:: yarn babel src/app.js &lt;br /&gt;&quot;use&amp;nbsp;strict&quot;; &lt;br /&gt;&lt;br /&gt;var&amp;nbsp;math&amp;nbsp;=&amp;nbsp;_interopRequireWildcard(require(&quot;./math.js&quot;)); &lt;br /&gt;require(&quot;./app.css&quot;); &lt;br /&gt;function&amp;nbsp;_getRequireWildcardCache(e)&amp;nbsp;{&amp;nbsp;if&amp;nbsp;(&quot;function&quot;&amp;nbsp;!=&amp;nbsp;typeof&amp;nbsp;WeakMap)&amp;nbsp;return&amp;nbsp;null;&amp;nbsp;var&amp;nbsp;r&amp;nbsp;=&amp;nbsp;new&amp;nbsp;WeakMap(),&amp;nbsp;t&amp;nbsp;=&amp;nbsp;new&amp;nbsp;WeakMap();&amp;nbsp;return&amp;nbsp;(_getRequireWildcardCache&amp;nbsp;=&amp;nbsp;function&amp;nbsp;(e)&amp;nbsp;{&amp;nbsp;return&amp;nbsp;e&amp;nbsp;?&amp;nbsp;t&amp;nbsp;:&amp;nbsp;r;&amp;nbsp;})(e);&amp;nbsp;} &lt;br /&gt;function&amp;nbsp;_interopRequireWildcard(e,&amp;nbsp;r)&amp;nbsp;{&amp;nbsp;if&amp;nbsp;(!r&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;e&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;e.__esModule)&amp;nbsp;return&amp;nbsp;e;&amp;nbsp;if&amp;nbsp;(null&amp;nbsp;===&amp;nbsp;e&amp;nbsp;||&amp;nbsp;&quot;object&quot;&amp;nbsp;!=&amp;nbsp;typeof&amp;nbsp;e&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&quot;function&quot;&amp;nbsp;!=&amp;nbsp;typeof&amp;nbsp;e)&amp;nbsp;return&amp;nbsp;{&amp;nbsp;default:&amp;nbsp;e&amp;nbsp;};&amp;nbsp;var&amp;nbsp;t&amp;nbsp;=&amp;nbsp;_getRequireWildcardCache(r);&amp;nbsp;if&amp;nbsp;(t&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;t.has(e))&amp;nbsp;return&amp;nbsp;t.get(e);&amp;nbsp;var&amp;nbsp;n&amp;nbsp;=&amp;nbsp;{&amp;nbsp;__proto__:&amp;nbsp;null&amp;nbsp;},&amp;nbsp;a&amp;nbsp;=&amp;nbsp;Object.defineProperty&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;Object.getOwnPropertyDescriptor;&amp;nbsp;for&amp;nbsp;(var&amp;nbsp;u&amp;nbsp;in&amp;nbsp;e)&amp;nbsp;if&amp;nbsp;(&quot;default&quot;&amp;nbsp;!==&amp;nbsp;u&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;{}.hasOwnProperty.call(e,&amp;nbsp;u))&amp;nbsp;{&amp;nbsp;var&amp;nbsp;i&amp;nbsp;=&amp;nbsp;a&amp;nbsp;?&amp;nbsp;Object.getOwnPropertyDescriptor(e,&amp;nbsp;u)&amp;nbsp;:&amp;nbsp;null;&amp;nbsp;i&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(i.get&amp;nbsp;||&amp;nbsp;i.set)&amp;nbsp;?&amp;nbsp;Object.defineProperty(n,&amp;nbsp;u,&amp;nbsp;i)&amp;nbsp;:&amp;nbsp;n[u]&amp;nbsp;=&amp;nbsp;e[u];&amp;nbsp;}&amp;nbsp;return&amp;nbsp;n.default&amp;nbsp;=&amp;nbsp;e,&amp;nbsp;t&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;t.set(e,&amp;nbsp;n),&amp;nbsp;n;&amp;nbsp;} &lt;br /&gt;const&amp;nbsp;alert&amp;nbsp;=&amp;nbsp;msg&amp;nbsp;=&amp;gt;&amp;nbsp;window.alert(msg); &lt;br /&gt;//&amp;nbsp;import&amp;nbsp;npmIcon&amp;nbsp;from&amp;nbsp;'./npm-icon.png'; &lt;br /&gt;//&amp;nbsp;import&amp;nbsp;{&amp;nbsp;sum&amp;nbsp;}&amp;nbsp;from&amp;nbsp;'./math.js'; &lt;br /&gt;console.log(math.sum(1,&amp;nbsp;2)); &lt;br /&gt;//&amp;nbsp;console.log(sum(1,2)); &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;document.addEventListener('DOMContentLoaded',&amp;nbsp;()&amp;nbsp;=&amp;gt;&amp;nbsp;{ &lt;br /&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body.innerHTML&amp;nbsp;=&amp;nbsp;`&amp;lt;img&amp;nbsp;src=&quot;${npmIcon}&quot;/&amp;gt;` &lt;br /&gt;//&amp;nbsp;}); &lt;br /&gt;&lt;br /&gt;console.log(process.env.NODE_ENV); &lt;br /&gt;console.log(api.domain);&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 여기서 우리가 주시해야할 것은 const이다. 그 이유는 크롬 79ver은 const를 이해하고 있기 때문에 이전과 달리 var로 변환될 필요가 없는 것이다. 만약 chrome 뿐만아니라 익스플로러까지 지원 해야 한다면 다음과 같이 추가하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1725005978226&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*--이하 생략--*/
presets: [
    ['@babel/preset-env', {
      targets: {
        chrome: '79',
        ie: '11'
      }
    }]
  ]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 관련 정보는 다음 아래 링크를 통해서 확인 할 수 있다.(검색 예시 ex. arrow)&lt;/p&gt;
&lt;figure id=&quot;og_1725005648985&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Can I use... Support tables for HTML5, CSS3, etc&quot; data-og-description=&quot;&quot; data-og-host=&quot;caniuse.com&quot; data-og-source-url=&quot;https://caniuse.com/&quot; data-og-url=&quot;https://caniuse.com/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://caniuse.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://caniuse.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Can I use... Support tables for HTML5, CSS3, etc&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;caniuse.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;폴리필(Polyfill)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Promise를 app.js에 추가를 하고 babael을 실행하면 변환된 결과물 확인이 가능한 것을 기대했지만 명령어를 실행하고 확인을 해보면 그렇지 못한 것을 학인 할 수 있었다. 이에 우리에게 필요한 플러그인을 설치해야 한다는 것을 알 수 있다. (만약 변환되지 않은 Promise를 웹에서 확인하면 SCRIPT5009와 같은 error를 발생시킨다.)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;폴리필(Polyfill) 은 무엇인가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 우리가 앞서 언급했지만 플러그인이 Promise를 ECMAScript5로 변환할 것으로 기대 했지만 그렇지 못했다. 이유는 &lt;b&gt;babel은 ECMAScript2015+를 ECMAScript5 버전으로 변환&lt;/b&gt; 할 수 있는 것만 변환하기 때문이다. 폴리필이라는 플러그인은 위에서 변환하지 못한 코드 조각들을 추가적으로 해결 하는 역할을 하는 것이다. 다만 Promise는 ECMAScript5 버전으로 &lt;b&gt;대체&lt;/b&gt;할 수 없다. 따라 ECMAScript5 버전으로 &lt;b&gt;구현&lt;/b&gt;은 할 수 있다. (core-js promise 참고)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;env 프리셋은 폴리필을 지정할 수 있는 옵션을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라 아래와 같이 패키지를 설치해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1725007345805&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

yarn add core-js@3&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1725012049758&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { version } = require('webpack');
const myBabelPreset = require('./my-babel-preset');
module.exports = {
  presets: [
    [
      '@babel/preset-env', {
        targets: {
          chrome: '79',  //79, 60
          // ie: '11'
        },
        useBuiltIns: &quot;usage&quot;, // 폴리필 사용 방식 지정 기본값은 false
        corejs: {
          // 폴리필 버전 지정
          version: 3,
        },
        /**
         * useBuiltIns: &quot;usage&quot;, // 폴리필 사용 방식 지정 기본값은 false
        corejs: 3, // 폴리필 버전 지정
         */
      }
    ]
  ]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 위와 같이 설정을 잘 해주고 babel을 실행시키면 정상적으로 동작을 하지 않는다. 원인을 찾는데 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;정말 많은 시간을&lt;span&gt; 사용했다. html에 import를 하는 방법과 babel을 webpack에서 통합적으로 관리할 수 있게 코드를 작성햅보고 최대한 구글링에서도 최신 글들만 찾아보며 말이다. 결과적으로 원인을 찾은 경로는 'Can I use'에서 확인 할수 있었다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp; chrome의 79버전을 지정하고 ie를 11버전으로 지정을 했다. 여기서 작성자는 ie를 사용하지 않을 것이니 해당 targets를 삭제를 했다. 그리고선 promise가 변환되길 바라고 있었다. 즉, chrome 79에서는 정상적으로 promise 사용할 수 있기 때문에 굳이 변환을 하지 않은 것이다. 그래서 ie를 11버전을 추가 했더니 정상적으로 require로 변환되는 것을 확인 했다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725012132472&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*--이하 생략--*/
    targets: {
      chrome: '79',  //79, 60
      ie: '11'
    },&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1725012242327&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::yarn babel src/app.js

&quot;use strict&quot;;

require(&quot;core-js/modules/es.object.to-string.js&quot;);
require(&quot;core-js/modules/es.promise.js&quot;);
var alert = function alert(msg) {
  return window.alert(msg);
};
new Promise(function (resolve) {
  return resolve('test');
}).then(console.log);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp; (여기서 의문 &lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;왜 chrome '60'으로 설정을 하면 require문으로 트렌제이션을 할까?&lt;/i&gt;&lt;/span&gt; 'Can I Use'에선 '60' 버전도 promise를 충분히 지원을 한다고 했는데 말이다. 이유는 생각보다 복잡하다. 폴리필은 버전마다 안전하게 코드가 동작할 수 있게 도움을 주는 역할이다. 즉, 'Can I Use'에서 promise를 완전히 지원 한다해도 일부 안정적인 개발환경을 지원하기 위해서 폴리필의 판단하게 트렌제이션을 할지 말지를 결정하기 때문인 것이다. 따라서 폴리필을 잘 설정하기만 하면 문제 없이 동작을 할 것이다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;웹팩으로 통합하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무 환경에서는 바벨을 직접 사용하는 것보다는 웹팩으로 통합해서 사용하는 것이 일반적이다. 웹팩으로 통합하기 위해서는 babel-loader를 사용해야한다. 아래 명령어를 통해서 설치하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1725015511402&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

yarn add babel-loader&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래와 같이 webpack.config를 수정하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1725016480186&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/*--이하 생략--*/
  module: {
    rules: [
      {
        test: /\.js$/,
        // use: [
        //   path.resolve('./my-webpack-loader.js')
        // ],
        exclude: /node_modules/,  // node_modules는 제외
        loader: 'babel-loader', //바벨 로더 추가
      },
      {
        test: /\.css$/,
        use: [
          process.env.NODE_ENV === 'production'
            ? MiniCssExtractPlugin.loader
            : 'style-loader', 'css-loader'
        ],
      },
/*--이하 생략--*/&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1725016943935&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

yarn add core-js@3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정하고 yanr build를 하면 정상적으로 build가 되는 것을 확인 할수 있다. 원래라면 corejs가 설치가 되어 있으면 안되는 상태에서 build를 하게되면 문제가 발생하지만 작성자는 이전에 corejs를 설치했기 때문에 정상적으로 build가 되는 것을 확인 할 수 있다. 정리하자면 바벨 코어는 파싱과 출력만 담당한다. 변환 작업(트레스젝션)을 담당하는 역할은 바벨 플러그인 처리를 한다. 이러한 여러 플러그인을 모아 놓은 세트를 프리셋이라고 한다. 이후 바벨이 변환하지 못하는 코드는 폴리필이 잔여 코드 조작들을 결과물에 로딩해서 우리가 렌더링된 결과물을 받아 볼 수 있는 것이다. 따라서 babel-loader로 웹팩과 함께 사용해서 훨 단순한 자동화된 프론트엔드 개발환경을 갖출 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SUMMARY&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전반적으로 중요한 모든 설정들을 학습했다. 환경을 설정하고 커스텀 하면서 느낀점은 dist폴더의 설정과 build된 결과물과 out, entry설정이 무엇보다 중요하다는 것을 느꼈다. 여기서 잘못된 부분이 많으면 어떠한 플러그인을 설정해도 정상적으로 동작하지 않을 것이다. 어쩌면 이 모든 강의 중 가장 중요한 강의는 초반 세팅 환경 구성의 대한 수업이지 않을까 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REFERNCE&lt;/p&gt;
&lt;figure id=&quot;og_1725007570187&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;똑똑하게 브라우저 Polyfill 관리하기&quot; data-og-description=&quot;현대적인 JavaScript를 쓰면서도 넓은 범위의 기기를 지원하기 위한 Polyfill을 어떻게 똑똑하게 설정할 수 있는지 소개합니다.&quot; data-og-host=&quot;toss.tech&quot; data-og-source-url=&quot;https://toss.tech/article/smart-polyfills&quot; data-og-url=&quot;https://toss.tech/article/smart-polyfills&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5QMMS/hyWV1HC1Wi/HUV6wNAXEtE839KAlVnK51/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/JufOR/hyWVXSJ45R/upEOSOdTwuyojhVaOlMTmK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/brlPFh/hyWV63ieID/QOUWSTcWfYVH3kIHmhSSuK/img.png?width=417&amp;amp;height=417&amp;amp;face=0_0_417_417&quot;&gt;&lt;a href=&quot;https://toss.tech/article/smart-polyfills&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://toss.tech/article/smart-polyfills&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5QMMS/hyWV1HC1Wi/HUV6wNAXEtE839KAlVnK51/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/JufOR/hyWVXSJ45R/upEOSOdTwuyojhVaOlMTmK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/brlPFh/hyWV63ieID/QOUWSTcWfYVH3kIHmhSSuK/img.png?width=417&amp;amp;height=417&amp;amp;face=0_0_417_417');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;똑똑하게 브라우저 Polyfill 관리하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;현대적인 JavaScript를 쓰면서도 넓은 범위의 기기를 지원하기 위한 Polyfill을 어떻게 똑똑하게 설정할 수 있는지 소개합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;toss.tech&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1725007797759&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;CRA 환경에서 폴리필 설정하기 (feat. core-js 라이브러리)&quot; data-og-description=&quot;Create React App(CRA)은 React 애플리케이션을 빠르게 구성할 수 있는 도구입니다. CRA를 사용하면 자동으로 바벨(Babel) 설정이 적용되며, 최신 자바스크립트 문법(ES6+)을 사용할 수 있습니다. 하지만 모&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@ss20141232/CRA-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%ED%8F%B4%EB%A6%AC%ED%95%84-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot; data-og-url=&quot;https://velog.io/@ss20141232/CRA-환경에서-폴리필-설정하기&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bEWPdr/hyWV0IILKX/ohWGwx2is2mTuk5Uu0DP7k/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/AGLtA/hyWVUhpj3I/4GxM2sYzpzaYpjdcrMQ4hK/img.jpg?width=930&amp;amp;height=558&amp;amp;face=0_0_930_558&quot;&gt;&lt;a href=&quot;https://velog.io/@ss20141232/CRA-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%ED%8F%B4%EB%A6%AC%ED%95%84-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@ss20141232/CRA-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%ED%8F%B4%EB%A6%AC%ED%95%84-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bEWPdr/hyWV0IILKX/ohWGwx2is2mTuk5Uu0DP7k/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/AGLtA/hyWVUhpj3I/4GxM2sYzpzaYpjdcrMQ4hK/img.jpg?width=930&amp;amp;height=558&amp;amp;face=0_0_930_558');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CRA 환경에서 폴리필 설정하기 (feat. core-js 라이브러리)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Create React App(CRA)은 React 애플리케이션을 빠르게 구성할 수 있는 도구입니다. CRA를 사용하면 자동으로 바벨(Babel) 설정이 적용되며, 최신 자바스크립트 문법(ES6+)을 사용할 수 있습니다. 하지만 모&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1725008498021&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;webpack에서 polyfill 설정하기&quot; data-og-description=&quot;들어가며 이 포스팅 에 이어서 이번 포스팅에서는 webpack에서 polyfill을 설정하는 방법에 대해 알아보도록 하자. webpack 에 대한 설명 여기 에서 확인할 수 있&amp;hellip;&quot; data-og-host=&quot;chamdom.blog&quot; data-og-source-url=&quot;https://chamdom.blog/webpack-polyfill-setting/&quot; data-og-url=&quot;https://chamdom.blog/webpack-polyfill-setting/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dbK1qe/hyWVSYdsMR/vLE8RPie7JD20SR8ATsKFK/img.png?width=800&amp;amp;height=400&amp;amp;face=0_0_800_400&quot;&gt;&lt;a href=&quot;https://chamdom.blog/webpack-polyfill-setting/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chamdom.blog/webpack-polyfill-setting/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dbK1qe/hyWVSYdsMR/vLE8RPie7JD20SR8ATsKFK/img.png?width=800&amp;amp;height=400&amp;amp;face=0_0_800_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;webpack에서 polyfill 설정하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;들어가며 이 포스팅 에 이어서 이번 포스팅에서는 webpack에서 polyfill을 설정하는 방법에 대해 알아보도록 하자. webpack 에 대한 설명 여기 에서 확인할 수 있&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chamdom.blog&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1725008719386&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;개발을 하다보니 이런 에러가 생겨서 원인을 찾다가 폴리필 문제라는걸 깨닫고 정리합니다.&quot; data-og-description=&quot;Core.js&quot; data-og-host=&quot;simsimjae.medium.com&quot; data-og-source-url=&quot;https://simsimjae.medium.com/%EA%B0%9C%EB%B0%9C%EC%9D%84-%ED%95%98%EB%8B%A4%EB%B3%B4%EB%8B%88-%EC%9D%B4%EB%9F%B0-%EC%97%90%EB%9F%AC%EA%B0%80-%EC%83%9D%EA%B2%A8%EC%84%9C-%EC%9B%90%EC%9D%B8%EC%9D%84-%EC%B0%BE%EB%8B%A4%EA%B0%80-%ED%8F%B4%EB%A6%AC%ED%95%84-%EB%AC%B8%EC%A0%9C%EB%9D%BC%EB%8A%94%EA%B1%B8-%EA%B9%A8%EB%8B%AB%EA%B3%A0-%EC%A0%95%EB%A6%AC%ED%95%A9%EB%8B%88%EB%8B%A4-217a207f8181&quot; data-og-url=&quot;https://simsimjae.medium.com/%EA%B0%9C%EB%B0%9C%EC%9D%84-%ED%95%98%EB%8B%A4%EB%B3%B4%EB%8B%88-%EC%9D%B4%EB%9F%B0-%EC%97%90%EB%9F%AC%EA%B0%80-%EC%83%9D%EA%B2%A8%EC%84%9C-%EC%9B%90%EC%9D%B8%EC%9D%84-%EC%B0%BE%EB%8B%A4%EA%B0%80-%ED%8F%B4%EB%A6%AC%ED%95%84-%EB%AC%B8%EC%A0%9C%EB%9D%BC%EB%8A%94%EA%B1%B8-%EA%B9%A8%EB%8B%AB%EA%B3%A0-%EC%A0%95%EB%A6%AC%ED%95%A9%EB%8B%88%EB%8B%A4-217a207f8181&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iVUX3/hyWV3FqZBX/bt4T9IktxmYnik92jzK0jk/img.jpg?width=1358&amp;amp;height=905&amp;amp;face=0_0_1358_905,https://scrap.kakaocdn.net/dn/b1tbxx/hyWVVtR79z/LlFgy9veeNXJPvnbS7hZNk/img.png?width=1072&amp;amp;height=594&amp;amp;face=0_0_1072_594,https://scrap.kakaocdn.net/dn/brlAPA/hyWVW0DepG/O84mIBixF81tggBbi9E36k/img.png?width=915&amp;amp;height=407&amp;amp;face=0_0_915_407&quot;&gt;&lt;a href=&quot;https://simsimjae.medium.com/%EA%B0%9C%EB%B0%9C%EC%9D%84-%ED%95%98%EB%8B%A4%EB%B3%B4%EB%8B%88-%EC%9D%B4%EB%9F%B0-%EC%97%90%EB%9F%AC%EA%B0%80-%EC%83%9D%EA%B2%A8%EC%84%9C-%EC%9B%90%EC%9D%B8%EC%9D%84-%EC%B0%BE%EB%8B%A4%EA%B0%80-%ED%8F%B4%EB%A6%AC%ED%95%84-%EB%AC%B8%EC%A0%9C%EB%9D%BC%EB%8A%94%EA%B1%B8-%EA%B9%A8%EB%8B%AB%EA%B3%A0-%EC%A0%95%EB%A6%AC%ED%95%A9%EB%8B%88%EB%8B%A4-217a207f8181&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://simsimjae.medium.com/%EA%B0%9C%EB%B0%9C%EC%9D%84-%ED%95%98%EB%8B%A4%EB%B3%B4%EB%8B%88-%EC%9D%B4%EB%9F%B0-%EC%97%90%EB%9F%AC%EA%B0%80-%EC%83%9D%EA%B2%A8%EC%84%9C-%EC%9B%90%EC%9D%B8%EC%9D%84-%EC%B0%BE%EB%8B%A4%EA%B0%80-%ED%8F%B4%EB%A6%AC%ED%95%84-%EB%AC%B8%EC%A0%9C%EB%9D%BC%EB%8A%94%EA%B1%B8-%EA%B9%A8%EB%8B%AB%EA%B3%A0-%EC%A0%95%EB%A6%AC%ED%95%A9%EB%8B%88%EB%8B%A4-217a207f8181&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iVUX3/hyWV3FqZBX/bt4T9IktxmYnik92jzK0jk/img.jpg?width=1358&amp;amp;height=905&amp;amp;face=0_0_1358_905,https://scrap.kakaocdn.net/dn/b1tbxx/hyWVVtR79z/LlFgy9veeNXJPvnbS7hZNk/img.png?width=1072&amp;amp;height=594&amp;amp;face=0_0_1072_594,https://scrap.kakaocdn.net/dn/brlAPA/hyWVW0DepG/O84mIBixF81tggBbi9E36k/img.png?width=915&amp;amp;height=407&amp;amp;face=0_0_915_407');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;개발을 하다보니 이런 에러가 생겨서 원인을 찾다가 폴리필 문제라는걸 깨닫고 정리합니다.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Core.js&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;simsimjae.medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/425</guid>
      <comments>https://hi-code.tistory.com/425#entry425comment</comments>
      <pubDate>Fri, 30 Aug 2024 19:12:58 +0900</pubDate>
    </item>
    <item>
      <title> Webpack : Babel</title>
      <link>https://hi-code.tistory.com/423</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이번 포스팅에서는 Babel에 관해서 다루어 볼 것이다. Babel은 무엇이고 Babel이 어떻게 탄생이 되었는지 알아 볼 것이다. 우선 Babel이라는 어원은 고대 히브리 신화에서 다루고 있는 Babel탑 이야기의 Babel로 부터 가지고 온 것이다. 이야기의 간단한 내용을 이렇다. &lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;사람들이 하늘 높이 올라가기 위한 탑을 쌓아 올렸는데 신이 이것을 막기위해 인간들의 언어를 모두 바꿔 놓게 되는 이야기다.&lt;/i&gt;&lt;/span&gt; 지금 소프트웨어, 브라우저의 생태계를 보면 윈도우, 리눅스, 맥, 크롬, 엣지, 사파리, 웨일 등 다양한 소프트웨어가 존재하고 이것들이 사용되는 프로그래밍의 언어가 각기 다르다. 과거 사파리에서는 Promise.prototype.finaly 메소드는 사용할 수 없었다. 그야 말로 혼돈의 시대이다. 참고로 히브리어로 Babel은 혼돈을 뜻한다. 이런 다양한 생태계로 발생하게 되는 현상을 소프트웨에선 '크로스 브라우징'이라고 하고 이것을 해결해주는 것이 바로 Babel이 되겠다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;크로스 브라우징과 Babel&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Babel이 ECMAScript2015+(ES6)로 작성한 코드 모두를 브라우저로 동학 할 수 있게 호환 시키는 역할을 한다. 즉, 현 생태계의 번역가와 같은 역할을 하면서 크로스 브라우징을 해소시켜 준다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Babel&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 바벨을 설치하기 위해서는 아래와 같이 설치를 진행하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724506170342&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD
npm install @babel/core @babel/cli&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치된 babel을 실행시키는 방법은 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724506505876&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::npm
npx babel src/app.js

::yarn
yarn babel src/app.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바벨은 세 단계로 빌드를 진행한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 파싱(Parsing)&lt;br /&gt;2. 변환(Transforming)&lt;br /&gt;3. 출력(Printing)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;플러그인(Plugin)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플러그인은 Babel 빌드 세가지 단계 중 두 번째 변환(Transforming)을 담당한다. 따라서 우리가 loader, plugin을 webpack.config에서 커스텀했듯이 Babel도 커스텀이 가능하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;커스텀 플러그인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Babel 플러그인을 커스텀한 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724507408126&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// my-babel-plugin.js

module.exports = function myBabelPlugin() {
  return {
    visitor: {
      Identifier(path) {
        const name = path.node.name;
        //  바벨이 만든 AST 노드를 출력한다.
        console.log('Identifier() name: ', name)

        //  변환작업: 코드 문자열을 역순으로 변환한다.
        path.node.name = name
          .split(&quot;&quot;)
          .reverse()
          .join(&quot;&quot;)
      }
    },
  };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 bable을 동작시키게 하기 위해서는 아래와 같이 명령을 해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724507736749&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::npm
npm babel src/app.js --plugins './src/my-babel-plugin.js'

:yarn
yarn babel src/app.js --plugins './src/my-babel-plugin.js'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 강의와 다르게 아래와 같은 오류가 나온다.&lt;/p&gt;
&lt;pre id=&quot;code_1724507771788&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:: 이하 생략
at loadPlugin (D:\myclass\0_Programming-content\Frontend-Development-Environment\.yarn\cache\@babel-core-npm-7.25.2-341930f809-a425fa40e7.zip\node_modules\@babel\core\lib\config\files\plugins.js:52:20)
    at loadPlugin.next (&amp;lt;anonymous&amp;gt;) {
  code: 'ERR_MODULE_NOT_FOUND'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 바벨 플러그인을 찾지 못하는 것이다. 현재 강의와 달리 작성자는 디렉토리 구조가 다르다. 'my-babel-plugin.js' 파일이 src 디렉토리 안에 있다. 강의에선 상위 폴더에서 실행하고 실습하고 있다. 이 에러를 해결하기 위해서 gpt와 해결하게 되었다. 해결방법은 'babel.config.js'파일을 생성해서 plugin을 관리하는 것이다. 작성 방법은 간단했다. 아래 코드를 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1724507934708&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//babel.config.js

module.exports = {
  plugins: [&quot;./src/my-babel-plugin.js&quot;]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 작성하고 아래와 같이 명령어를 직성하면 정상적으로 build 되는 것을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1724507994480&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

yarn babel src/app.js

Identifier() name:  alert
Identifier() name:  msg
Identifier() name:  window
Identifier() name:  alert
:: 이하 생략
Identifier() name:  api
Identifier() name:  domain
const trela = gsm =&amp;gt; wodniw.trela(gsm);
import * as htam from './math.js';
import './app.css';
// import npmIcon from './npm-icon.png';
// import { sum } from './math.js';
elosnoc.gol(htam.mus(1, 2));
// console.log(sum(1,2));

// document.addEventListener('DOMContentLoaded', () =&amp;gt; {
//   document.body.innerHTML = `&amp;lt;img src=&quot;${npmIcon}&quot;/&amp;gt;`
// });

elosnoc.gol(ssecorp.vne.VNE_EDON);
elosnoc.gol(ipa.niamod);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면 이상한 점이 있다. `elosnoc.gol(htam.mus(1, 2));` 이렇게 괴상하게 찍히는 것을 확인 할수 있는데 이유는 우리가 my-babel-plugin.js에서 `//변환 작업~`이라고 주석친 아래 코드에서 path로 부터 접근된 name들을 모두 reverse하고 split하면서 join으로 합치면서 발생된 결과물인것이다. 그렇다면 이번에는 const 타입을 전부 var로 변경하는 커스텀 plugin을 작성해 보겠다.&lt;/p&gt;
&lt;pre id=&quot;code_1724583767121&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// my-babel-plugin

module.exports = function myBabelPlugin() {
  return {
    visitor: {
      VariableDeclaration(path) {
      //번수에 어떤 자료형으로 선언이 되어 있는지 확인하는 log
        console.log('VariableDeclaration() kind', path.node.kind);

        //const를 var로 변환하는 조건문
        if (path.node.kind === 'const') {
          path.node.kind = 'var'
        }
      }
    },
  };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정을 하고 해당 js파일을 babel.config.js에 require를 사용해서 정확하게 삽입해서 실행 시켜보자.&lt;/p&gt;
&lt;pre id=&quot;code_1724583878062&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// babel.config.js

const myBabelPlugin = require('./src/my-babel-plugin.js');

module.exports = {
  plugins: [myBabelPlugin]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이렇게 작성이 완료되면 기존 방식과는 다른 CMD 명령을 해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1724584079265&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD
//npm
npm babel src/app.js

//yarn
yarn babel src/app.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실행을 하게 되면 아래와 같은 결과가 나온다.&lt;/p&gt;
&lt;pre id=&quot;code_1724584130689&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

VariableDeclaration() kind const
var alert = msg =&amp;gt; window.alert(msg);
import * as math from './math.js';
import './app.css';
// import npmIcon from './npm-icon.png';
// import { sum } from './math.js';
console.log(math.sum(1, 2));
// console.log(sum(1,2));

// document.addEventListener('DOMContentLoaded', () =&amp;gt; {
//   document.body.innerHTML = `&amp;lt;img src=&quot;${npmIcon}&quot;/&amp;gt;`
// });

console.log(process.env.NODE_ENV);
console.log(api.domain);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이런 방식의 플러그인이 이미 babel안에 제공을 해주고 있다. 그것이 바로 block-scoping이라는 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;block-scoping&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;block-scoping을 사용해서 구현해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1724584464973&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD
npm install @babel/plugin-transform-block-scoping

yarn add @babel/plugin-transform-block-scoping&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1724584794851&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// babel.config.js

const blockScoping = require('@babel/plugin-transform-block-scoping')
module.exports = {
  plugins: [blockScoping]
};&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1724584964773&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

::npm for build
npx babel src/app.js --out-file dist/app.js
::yarn for build
yarn babel src/app.js --out-file dist/app.js

::or

::npm for direct
npx babel src/app.js
::yarn for direct
yarn babel src/app.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724585181290&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

var alert = msg =&amp;gt; window.alert(msg);
import * as math from './math.js';
import './app.css';
// import npmIcon from './npm-icon.png';
// import { sum } from './math.js';
console.log(math.sum(1, 2));
// console.log(sum(1,2));

// document.addEventListener('DOMContentLoaded', () =&amp;gt; {
//   document.body.innerHTML = `&amp;lt;img src=&quot;${npmIcon}&quot;/&amp;gt;`
// });

console.log(process.env.NODE_ENV);
console.log(api.domain);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 화살표기 함수를 일반 함수로 변환하는 코드를 작성해 볼 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;arrow-functions&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 플러그인을 실행하기 위해서는 아래와 같이 패키지를 설치해주자&lt;/p&gt;
&lt;pre id=&quot;code_1724585375477&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

::npm
npm install @babel/plugin-transform-arrow-functions

::yarn
yarn add @babel/plugin-transform-arrow-functions&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1724585599455&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//babel.config.js

// const myBabelPlugin = require('./src/my-babel-plugin.js');
const blockScoping = require('@babel/plugin-transform-block-scoping');
const arrowFunction = require('@babel/plugin-transform-arrow-functions');
module.exports = {
  plugins: [blockScoping, arrowFunction]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실행을 시켜면 아래와 같은 결과가 나온다.&lt;/p&gt;
&lt;pre id=&quot;code_1724585674732&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

var alert = function (msg) {
  return window.alert(msg);
};
import * as math from './math.js';
import './app.css';
// import npmIcon from './npm-icon.png';
// import { sum } from './math.js';
console.log(math.sum(1, 2));
// console.log(sum(1,2));

// document.addEventListener('DOMContentLoaded', () =&amp;gt; {
//   document.body.innerHTML = `&amp;lt;img src=&quot;${npmIcon}&quot;/&amp;gt;`
// });

console.log(process.env.NODE_ENV);
console.log(api.domain);&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;strict-mode&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼭 설치해야하거나 꼭 사용해야하는 플러그인은 아니지만 엄격 모드를 사용하는 것이 코드의 안정성에 좋다. 이에 use strict 구문이 기본적으로 적용이 될 수 있게 코드를 작성하면 아래와 같다. 먼저 패키지 설치는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724585926927&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

::npm
npm install @babel/plugin-transform-strict-mode

::yarn
yarn add @babel/plugin-transform-strict-mode&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1724586123546&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// babel.config.js

const blockScoping = require('@babel/plugin-transform-block-scoping');
const arrowFunction = require('@babel/plugin-transform-arrow-functions');
const strictMode = require('@babel/plugin-transform-strict-mode');
module.exports = {
  plugins: [blockScoping, arrowFunction, strictMode]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실행을 하면 다음과 같은 결과가 나온다.&lt;/p&gt;
&lt;pre id=&quot;code_1724586187148&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

&quot;use strict&quot;;

var alert = function (msg) {
  return window.alert(msg);
};
import * as math from './math.js';
import './app.css';
// import npmIcon from './npm-icon.png';
// import { sum } from './math.js';
console.log(math.sum(1, 2));
// console.log(sum(1,2));

// document.addEventListener('DOMContentLoaded', () =&amp;gt; {
//   document.body.innerHTML = `&amp;lt;img src=&quot;${npmIcon}&quot;/&amp;gt;`
// });

console.log(process.env.NODE_ENV);
console.log(api.domain);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 실행되는 모습을 볼 수가 있었다. 마지막으로 우리가 하나하나 플러그인들을 설치하는 것은 작업에 있어서 매우 비현실적이다. 따라서 커스텀 프리셋을 이용해서 하나의 프리셋으로 만들어볼 수가 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;커스텀 프리셋&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 presets으로 관리할 js 파일을 하나 만든다. 그리고 우리가 필요한 플러그인을 담아내면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724586661525&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// my-babel-preset.js

const blockScoping = require('@babel/plugin-transform-block-scoping');
const arrowFunction = require('@babel/plugin-transform-arrow-functions');
const strictMode = require('@babel/plugin-transform-strict-mode');

module.exports = function myBabelPreset() {
  return {
    plugins: [blockScoping, arrowFunction, strictMode]
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 babel.config.js에 해당 presets을 연결해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724586732802&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//babel.config.js

const myBabelPreset = require('./my-babel-preset');
module.exports = {
  presets: [myBabelPreset]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 실행을 하면 아까와 변함없이 에러 없이 잘 실행되는 것을 확인할 수 있다. 마지막으로 build를 해보면 내가 babel에 설정한 플러그인들이 build된 파일에 잘 설정이 된 것을 확인 할 수 있다. 다음 포스팅에서는 실무에서 사용되는 프리셋을 설정할 것이다. 오늘의 포스팅은 babel을 어떻게 다루는지 알아보기 위한 플러그인들이다.&lt;/p&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/423</guid>
      <comments>https://hi-code.tistory.com/423#entry423comment</comments>
      <pubDate>Sat, 24 Aug 2024 14:06:05 +0900</pubDate>
    </item>
    <item>
      <title> Webpack : 자주 사용되는 Plugin</title>
      <link>https://hi-code.tistory.com/422</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 자주 사용되는 플러그인에 관해 살펴 볼 것이다. 자주 사용되는 대표적 플러그인 5가지를 살펴 볼 것이다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BannerPlugin&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 우리가 BannerPlugin을 모사했다. 이 플러그인은 webpack에서 기본적으로 제공을 해주는 플러그인이다. BannerPlugin은 결과물에 빌드 정보나 커밋 버전같은 것을 추가 할 수 있다. 이를 webpack.config에 적용하는 방법은 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724400039859&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

const path = require('path');
const MyWebpackPlugin = require('./my-webpack-plugin');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
 /* -- 중간 생략 -- */
  plugins: [
    new CleanWebpackPlugin(), // 빌드 전에 dist 폴더를 정리합니다.
    new webpack.BannerPlugin({
      banner: '이것은 Banner 입니다.'
    })
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 생성된 시간과 깃 커밋 log 번호 그리고 작성자 정보를 넣어 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1724400308338&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::cmd
git rev-parse --short HEAD

::a7cec5b

git config user.name

::4Bee&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;깃 커밋 log 번호는 git log와 같이 확인을 할 수도 있지만 너무길기 때문에 아래와같은 명령어를 실행해서 단축된 log번호를 가져올 수 있다. 이렇게 git을 통해서 하나하나 매번 정보를 우리가 입력해서 넣어 줄 수 없다. 그래서 이를 자동화 하는 방법이 있는데 그것은 node-modules에서 제공해주는 childProcess를 사용하는 것이다. 아래 코드를 참고하자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724400178074&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/* -- 중간 생략 -- */
const webpack = require('webpack');
const childProcess = require('child_process');  //from node_modules
/* -- 중간 생략 -- */
  plugins: [
    new CleanWebpackPlugin(), // 빌드 전에 dist 폴더를 정리합니다.
    new webpack.BannerPlugin({
      banner: `
      Build Date: ${new Date().toLocaleDateString()}
      Commit Version: ${childProcess.execSync('git rev-parse --short HEAD')}
      Author: ${childProcess.execSync('git config user.name')}
      `
    })
  ],
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 childProcess를 사용해서 git 명령어를 build가 되는 과정에 execSync로 실행시키게 만들면 된다. 이제 build된 결과를 보면 아래와 같이 배너에 추가가되는 것을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1724400795923&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*dist/main.js*/
/*!
 * 
 *       Build Date: 2024. 8. 23.
 *       Commit Version: a7cec5b
 *
 *       Author: 4Bee
 *
 *
 */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 우리가 브라우저에 console을 통한 log를 확인하는 용도와 유사하다. 잘 활요을 하면 매우 유용할 것 같다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DefinePlugin&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 프론트에서 프로젝트를 관리 할 때 개발환경과 배포환경으로 나누어서 운영을 한다. 그래서 서버 API 서버 주소나 변경이 될 정보들이 있을 수 있다. 이런 것들을 &lt;b&gt;`환경 의존 정보`&lt;/b&gt;라고 한다. 따라 배포를 할 때 마다 코드를 계속해서 변경하는 번거로움을 줄이고자 DefinePlugin을 사용해서 쉽게 해결 할수 있다.(dotenv와 같은 라이브러리가 있지만 해당 플러그인으로 대체할 수 있지 않을까 한다.) 해당 플러그인 역시 webpack에서 기본적으로 제공해주는 플러그인이다. 이를 활용하기 위해서는 process.env.NODE_ENV가 있다. 여기로 접근해서 webpack.config의 &lt;b&gt;`mode`&lt;/b&gt;값을 얻어와서 활용하면 된다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;process.env.NODE_ENV를 app.js에서 console로 확인이 가능하다. 따라 ` &lt;b&gt;development`&lt;/b&gt;라는 결과를 얻을 수 있다. 그럼 이제 직접 환경변수를 만들어보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724411097886&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/* -- 중간 생략 -- */
const webpack = require('webpack');
const childProcess = require('child_process');  //from node_modules
/* -- 중간 생략 -- */
  plugins: [
    new CleanWebpackPlugin(), // 빌드 전에 dist 폴더를 정리합니다.
    new webpack.BannerPlugin({
      banner: `
      Build Date: ${new Date().toLocaleDateString()}
      Commit Version: ${childProcess.execSync('git rev-parse --short HEAD')}
      Author: ${childProcess.execSync('git config user.name')}
      `
    }),
    new webpack.DefinePlugin({
      TWO: '1+1'
    })
  ],
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 app.js에 TWO라는 환경변수에 접근을 하려면 아래와 같이 작성하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724411151188&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//app.js

console.log(process.env.NODE_ENV);
console.log(TWO);  //2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 결과는 값으로 console이 찍힌다. 그렇다면 문자로 결과를 도출하고 싶다면 아래와 같이 수정하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724411359990&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//TWO: '1+1'
TWO: JSON.stringify('1+1')  //1+1
// 객체 방식
'api.domain': JSON.stringify('http://dev.api.domain.com')&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HtmlTemplatePlugin&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HtmlTemplatePlugin은 이전 플러그인과 달리 써드 파티 패키지이기에 따로 설치를 해줘야 한다. HtmlTemplatePlugin은 HTML 파일을 후처리하는 플러그인이며 빌드 타임의 값을 넣거나 코드를 압축하는 역할을 한다. HtmlTemplatePlugin은 html을 작업하는 플러그인이기 때문에 정상적으로 동작하게 하려면 src 디렉토리에 html이 있을 경우, webpack으로 작업을 해야하는 경우에만 사용하면 된다 볼 수 있다. 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724412284107&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/* -- 중간 생략 -- */
const webpack = require('webpack');
const childProcess = require('child_process');  //from node_modules
const HtmlWebpackPlugin = require('html-webpack-plugin');

/* -- 중간 생략 -- */ 
 plugins: [
    new CleanWebpackPlugin(), // 빌드 전에 dist 폴더를 정리합니다.
    new webpack.BannerPlugin({
      banner: `
      Build Date: ${new Date().toLocaleDateString()}
      Commit Version: ${childProcess.execSync('git rev-parse --short HEAD')}
      Author: ${childProcess.execSync('git config user.name')}
      `
    }),
    new webpack.DefinePlugin({
      TWO: JSON.stringify('1+1'),
      'api.domain': JSON.stringify('http://dev.api.domain.com')
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 build를 하게 되면 dist 디렉토리에 index.html 파일이 들어 있는 것을 확인 할수 있다. 만약 live-server로 접근을 하려면 주소가 `PortNumber/~/dist/index.html`로 해줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이번에는 이어서 html에서 사용할 수 있는 ejs 문법을 잠깐 다뤄 볼 것이다. 해당 문법은 HtmlTemplatePlugin에서 사용했던 template을 html에 직접 넣어 보는 것이다. 해당 문법은 envs라는 template를 넣을 수 있는 문법이다. 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724412755675&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- src/index.html --&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
  &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
  &amp;lt;title&amp;gt;Document&amp;lt;%= env %&amp;gt;&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;script type=&quot;module&quot; src=&quot;./dist/main.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 여기 env에 값을 넣어주려면 아래와 같이 webpack.config파일을 수정하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724412909282&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/* -- 중간 생략 -- */
const webpack = require('webpack');
const childProcess = require('child_process');  //from node_modules
const HtmlWebpackPlugin = require('html-webpack-plugin');
/* -- 중간 생략 -- */
    new HtmlWebpackPlugin({
      template: './src/index.html',
      templateParameters: {
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : ''
      }
    })
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 build를 하면된다. 단, NODE_ENV의 환경 변수를 설정하면 우리가 의도한 결과물이 나올 것이다. 따라서 일반적인 build가 아닌 아래와 같이 build명령으로 실행 해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1724413360569&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:: 개발용이 아닌 제품용일 경우 development 대신production을 넣으면 ejs의 env 문법을 무시하고 빌드가 된다.
:: npm(Window)
set NODE_ENV=development&amp;amp;&amp;amp; npm run build
:: npm(MacOS)
NODE_ENV=development yarn run build

:: yarn(Window)
set NODE_ENV=development&amp;amp;&amp;amp; yarn run build
::yarn(MacOS)
NODE_ENV=development&amp;amp;&amp;amp; yarn build&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이외에도 빌드되는 html에 여러 조건을 줄수가 있는데 우리는 빈줄 제거와 주석 제거를 해볼 것이다. 아래와 같이 코드를 추가하자&lt;/p&gt;
&lt;pre id=&quot;code_1724413634601&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/* -- 중간 생략 -- */
const webpack = require('webpack');
const childProcess = require('child_process');  //from node_modules
const HtmlWebpackPlugin = require('html-webpack-plugin');
/* -- 중간 생략 -- */
    new HtmlWebpackPlugin({
      template: './src/index.html',
      templateParameters: {
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : ''
      },
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      }
    })
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 build를 확인하면 아래 코드처럼 html파일은 한줄로 코드가 완성된걸 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1724413837274&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang=&quot;en&quot;&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;&amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot;&amp;gt;&amp;lt;title&amp;gt;Document(개발용)&amp;lt;/title&amp;gt;&amp;lt;script defer=&quot;defer&quot; src=&quot;main.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;script type=&quot;module&quot; src=&quot;./dist/main.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 한줄로 build하는 경우는 일반적으로 development 방식이 아니라 producion일 경우에만 적용한다. 따라 아래와 같이 조건을 추가해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1724414026288&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js

/* -- 중간 생략 -- */
const webpack = require('webpack');
const childProcess = require('child_process');  //from node_modules
const HtmlWebpackPlugin = require('html-webpack-plugin');
/* -- 중간 생략 -- */
    new HtmlWebpackPlugin({
      template: './src/index.html',
      templateParameters: {
        env: process.env.NODE_ENV === 'development' ? '(개발용)' : ''
      },
      minify: production.env.NODE_ENV === 'production' ? {
        collapseWhitespace: true,
        removeComments: true,
      } : false
    })
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장하지 않고 브라우저를 끄는 바람에 `clean-webpack-plugin`과 `mini-css-extract-plugin`을&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;nbsp;작성했던 코드들이 모두 사라졌다. 뒤에 자주 사용되는 플러그인 2개는 그리 어렵지 않았다. NODE_ENV를 잘 활용하는 방법들이였다. 오히려 주의 깊게 보아야 하는 부분은 mini-css-extract-plugin이였다. 추후에 다시 점검하면서 마무리 지을 것이다. 아래 Github에서 전체코드를 확인해 달라.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1724475446047&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* -- 중간 생략 -- */
new CleanWebpackPlugin(), // 빌드 전에 dist 폴더를 정리합니다.
    ...(process.env.NODE_ENV === 'production'
      ? [new MiniCssExtractPlugin({ filename: '[name].css' })]
      : [])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1724475542082&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Frontend-Development-Environment/webpack.config.js at main &amp;middot; Programming-Contents-List/Frontend-Development-Environment&quot; data-og-description=&quot;프론트엔드 개발 환경 세팅 수업. Contribute to Programming-Contents-List/Frontend-Development-Environment development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Programming-Contents-List/Frontend-Development-Environment/blob/main/webpack.config.js&quot; data-og-url=&quot;https://github.com/Programming-Contents-List/Frontend-Development-Environment/blob/main/webpack.config.js&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/OYEaM/hyWVWrwHEU/bKAWNnRKvPsgZc5B0k9d5k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Programming-Contents-List/Frontend-Development-Environment/blob/main/webpack.config.js&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Programming-Contents-List/Frontend-Development-Environment/blob/main/webpack.config.js&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/OYEaM/hyWVWrwHEU/bKAWNnRKvPsgZc5B0k9d5k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Frontend-Development-Environment/webpack.config.js at main &amp;middot; Programming-Contents-List/Frontend-Development-Environment&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;프론트엔드 개발 환경 세팅 수업. Contribute to Programming-Contents-List/Frontend-Development-Environment development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/422</guid>
      <comments>https://hi-code.tistory.com/422#entry422comment</comments>
      <pubDate>Tue, 20 Aug 2024 21:43:02 +0900</pubDate>
    </item>
    <item>
      <title> Webpack : Plugin</title>
      <link>https://hi-code.tistory.com/421</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;플러그인은 번들된 결과 하나만을 처리한다. 번들된 js를 난독화 한다거나 특정 텍스트를 추출하는 용도록 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;My-Webpack-Plugin&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1724152496117&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MyWebpackPlugin {
  apply(compiler) {
    compiler.hooks.done.tap('MyWebpackPlugin', stats =&amp;gt; {
      console.log('MyPlugin: done');
    })
  }
}

module.exports = MyWebpackPlugin;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 플러그인을 커스텀 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. class MyWebpackPlugin&lt;/b&gt; : Webpack 플러그인은 일반적으로 클래스 형태로 정의해야 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.&lt;/b&gt; &lt;b&gt;apply(compiler) { ... }&lt;/b&gt; : Webpack 플러그인은 apply 메서드를 가져야 한다. apply 메서드는 Webpack이 플러그인을 사용할 때 호출되며 이 메서드는 Webpack의 compiler 객체를 인수로 받아 컴파일러와 빌드 프로세스 중 발생하는 여러 이벤트에 접근할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3.&lt;/b&gt; &lt;b&gt;compiler.hooks.done.tap('MyWebpackPlugin', stats =&amp;gt; { ... })&lt;/b&gt; : 이 줄은 Webpack의 done 훅(hook)을 사용하여 빌드가 완료된 후 실행되는 작업을 정의한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;compiler.hooks.done&lt;/b&gt;: Webpack의 done 훅은 컴파일이 완료되었을 때 실행된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;tap('MyWebpackPlugin', stats =&amp;gt; { ... })&lt;/b&gt;: 이 메서드는 특정 훅에 함수를 등록(tap)한다. 첫 번째 인수는 플러그인의 이름이며 두 번째 인수는 빌드가 완료된 후 실행될 콜백 함수입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;'MyWebpackPlugin'&lt;/b&gt;: 등록된 함수의 이름으로, 디버깅 및 로깅 시 유용하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;stats =&amp;gt; { ... }&lt;/b&gt;: 콜백 함수로, stats 객체는 컴파일 결과에 대한 정보를 담고 있다. 이 함수는 빌드가 완료된 후 실행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Plugin이 번들 결과에 접근할 수 있는 이유는 웹팩 내장 플러그인인 BannerPlugin을 통해서 접근할 수 있는 것이다. 이를 참조해서 코드를 다시 커스텀 해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1724153254176&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MyWebpackPlugin {
  apply(compiler) {
    compiler.plugin('emit', (compilation, callback) =&amp;gt; {
      const source = compilation.assets['main.js'].source();
      console.log(source);
      // compilation.assets['main.js'].source = () =&amp;gt; {
      //   const banner = [
      //     '/**',
      //     ' * 이것은 BannerPlugin이 처리한 결과입니다.',
      //     ' * Build Date: 2019-10-10',
      //     ' */'
      //   ].join('\n');
      //   return banner + '\n\n' + source;
      // }

      callback();
    })
  }
}

module.exports = MyWebpackPlugin;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 코드를 작성하고 build를 하게 되면 error가 발생한다. 그 이유는 `compiler.plugin`이라는 명령어가 webpack5에서는 사용되지 않고 삭제가 되었기 때문이다. 그렇다면 webpack5를 기준으로 올바른 코드를 작성해보면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724153508573&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MyWebpackPlugin {
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) =&amp;gt; {
      const source = compilation.assets['main.js'].source();
      console.log(source);
      // compilation.assets['main.js'].source = () =&amp;gt; {
      //   const banner = [
      //     '/**',
      //     ' * 이것은 BannerPlugin이 처리한 결과입니다.',
      //     ' * Build Date: 2019-10-10',
      //     ' */'
      //   ].join('\n');
      //   return banner + '\n\n' + source;
      // }

      callback();
    })
  }
}

module.exports = MyWebpackPlugin;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;`compiler.plugin`&lt;/span&gt; 이라는 코드를 대신해서 이렇게 코드를 `compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback)`를 이용하면 정상적으로 build가 되는 것을 확인 할 수 있다. 이제 `console.log(source)`의 결과를 보면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724153619791&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
 * ATTENTION: The &quot;eval&quot; devtool has been used (maybe by default in mode: &quot;development&quot;).
 * This devtool is neither made for production nor for readable output files.
 * It uses &quot;eval()&quot; calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with &quot;devtool: false&quot;.
 * If you are looking for production-ready output files, see mode: &quot;production&quot; (https://webpack.js.org/configuration/mode/).
 */
/******/ (() =&amp;gt; { // webpackBootstrap
/******/        &quot;use strict&quot;;
/******/        var __webpack_modules__ = ({

/***/ &quot;./.yarn/__virtual__/css-loader-virtual-16d7c22a15/0/cache/css-loader-npm-6.11.0-d945f9f4c0-bb52434138.zip/node_modules/css-loader/dist/cjs.js!./src/app.css&quot;:
/*!*******************************************************************************************************************************************************************!*\
  !*** ./.yarn/__virtual__/css-loader-virtual-16d7c22a15/0/cache/css-loader-npm-6.11.0-d945f9f4c0-bb52434138.zip/node_modules/css-loader/dist/cjs.js!./src/app.css ***!
  \*******************************************************************************************************************************************************************/
/***/ ((module, __webpack_exports__, __webpack_require__) =&amp;gt; {

eval(&quot;__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, 
/* -- 이하생략 -- */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면 build된 main.js와 일치한다는 것을 알 수 있다. 이렇게 BannerPlugin과 유사하게 동작 할 수 있게 코드를 작성해 보았다. 이제 방금 작성한 코드에서 주석으로 처리가 되어 있는 코드를 활용해 build된 결과를 다시 살펴보자. 주석을 처리하고 build를 하면 정상적으로 build는 되지만 main.js에 우리가 작성한 주석이 적용되지 않은 것을 볼 수 있다. 이에 webpack 공식문서를 찾아가보며 gpt와 함께 이를 해결 했다. 수정된 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1724156192473&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MyWebpackPlugin {
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) =&amp;gt; {
      console.log('This is an example plugin!');
      const source = compilation.assets['main.js'].source();
      const banner = ['/* This is an example plugin! */'].join('\n');
      const updatedSource = banner + '\n\n' + source;
      // 수정된 소스를 assets에 다시 설정
      compilation.assets['main.js'] = {
        source: () =&amp;gt; updatedSource,
        size: () =&amp;gt; updatedSource.length
      };
      console.log('Banner added to main.js');
      callback();// 비동기 작업이 완료되었음을 알림
    })
  }
}

module.exports = MyWebpackPlugin;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 버전 방식인 return을 사용했던 방법과 달리 webpack5에서는 key, value처럼 객체화해서 값을 넘겨주니 정상적으로 동작하는 것을 확인 할 수 있었다. complication은 객체는 Webpack이 모듈을 분석하고 번들링하는 과정에서 사용되며 각 모듈과 파일이 어떻게 처리되고 연결되는지에 대한 정보를 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의 커뮤니티를 보니 많은 수강생들이 업데이트를 해달라고 하곤 있지만 그 시간을 기다릴 수 없어서 공식문서와 gpt를 사용해서 충분히 해결 할수 있었다. 아래 이미지는 webpack이 전반적으로 어떻게 동작하는지를 시각적으로 표기해본 이미지이다. 몇몇 정보들을 빼놓긴 했지만 어떤 느낌인지 알 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nvK8w/btsI9u4Xq0g/98LrnGSHVk43S1LL4FMykk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nvK8w/btsI9u4Xq0g/98LrnGSHVk43S1LL4FMykk/img.png&quot; data-alt=&quot;당연히 entry는 먼저 설정이 되어 있을 것이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nvK8w/btsI9u4Xq0g/98LrnGSHVk43S1LL4FMykk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnvK8w%2FbtsI9u4Xq0g%2F98LrnGSHVk43S1LL4FMykk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1088&quot; height=&quot;496&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;당연히 entry는 먼저 설정이 되어 있을 것이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;figure id=&quot;og_1724156873089&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Writing a Plugin | webpack&quot; data-og-description=&quot;webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.&quot; data-og-host=&quot;webpack.js.org&quot; data-og-source-url=&quot;https://webpack.js.org/contribute/writing-a-plugin/&quot; data-og-url=&quot;https://webpack.js.org/contribute/writing-a-plugin/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dWo96a/hyWShXqHYy/2kVbMb4nMEZ6jidngUR7Ik/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://webpack.js.org/contribute/writing-a-plugin/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://webpack.js.org/contribute/writing-a-plugin/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dWo96a/hyWShXqHYy/2kVbMb4nMEZ6jidngUR7Ik/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Writing a Plugin | webpack&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;webpack.js.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/421</guid>
      <comments>https://hi-code.tistory.com/421#entry421comment</comments>
      <pubDate>Tue, 20 Aug 2024 19:47:34 +0900</pubDate>
    </item>
    <item>
      <title>안녕하세요. 그리고 안녕하세요.</title>
      <link>https://hi-code.tistory.com/pages/%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요. 프론트 개발자 '포비'입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그 없이 천명이란 방문자들이 있었습니다. 너무나도 기쁘고 뿌듯한 숫자입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 수익을 위해서도 구독의 숫자를 위해서도 아닌, 개발을 공부하는 또는 개발을 하는 분들에게 보다 좋은 정보를 드리고자 노력했습니다. 저의 기록을 발판 삼아 좋은 개발 지식과 정보들이 각색되길 바랐고 희망했습니다.&lt;br /&gt;매일 같이 공부하며 글을 쓰며 많이 고민했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'어떻게 하면 보다 좋은 개발 일지를 작성할 수 있을까.'&lt;br /&gt;'어떻게 하면 보다 보기 좋은 블로그를 만들 수 있을까.'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 결정했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 블로그는 남겨두고 새로운 블로그로 Coding Log를 찍어 낼 수 있는 환경으로 이전을 해야겠다는 결정을 말입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라 아래와 같이 공지와 양해를 구합니다.&lt;br /&gt;현재 작성하고 있는 'Front-Dev-Environment' 카테고리의 글을 끝으로 이전을 시작할 것 같습니다.&lt;br /&gt;대략적인 마무리 일시는 2024년 10월쯤이 될 듯합니다. 개인적인 사정과 일정으로 기간을 넉넉하게 잡았습니다.&lt;br /&gt;보다 좋은 개발자가 되기 위해 이전을 하는 것이니 응원과 성원 부탁드리며 글을 마칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 현재는 GitHub에서 공부 기록을 남기고 있습니다. 이를 기반으로 개인 블로그가 탄생하지 않을까 스스로 기대하고 있습니다. 아래는 포비의 GitHub 링크입니다. 많은 관심과 팔로우, 스타 부탁드리겠습니다. fork도 환영입니다.&lt;/p&gt;
&lt;figure id=&quot;og_1723745614219&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;4BFC - Overview&quot; data-og-description=&quot; 기본에 충실한 프론트엔드 개발자 김동우입니다. &amp;zwj; . 4BFC has 16 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/4BFC&quot; data-og-url=&quot;https://github.com/4BFC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c2OMib/hyWOhRwfU3/jdqyRk45GiG9Z7jXAfX2hK/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/4BFC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/4BFC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c2OMib/hyWOhRwfU3/jdqyRk45GiG9Z7jXAfX2hK/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;4BFC - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt; 기본에 충실한 프론트엔드 개발자 김동우입니다. &amp;zwj; . 4BFC has 16 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/pages/%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94</guid>
      <pubDate>Fri, 16 Aug 2024 03:17:29 +0900</pubDate>
    </item>
    <item>
      <title> Webpack : url-loader</title>
      <link>https://hi-code.tistory.com/418</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; url-loader의 역할은 이미지를 base-64로 인코딩해서 문자열 형태로 이미지 소스에 넣는 역할을 한다. 이러한 처리를 url-loader가 자동으로 처리를 해준다. 사용하는 이미지가 많아질 때 네트워크에서 리소스를 사용하는 부담이 있고 서비스 성능에 영향을 줄 수 있기 떄문이다. 참고로 작은 이미지를 사용한다면 Data URI Scheme을 사용하는 것이 더 낫다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;file-loader : 2&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 현재 작성작의 webpack 환경은 알다시피 webpack 5이다. 이에 따라 file-loader나 url-loader는 이미 assets/resource에 내장이 되어 있어서 수업에서 처럼 따로 설정 할 필요는 없다. 다만 webpack.config에 지난번과 같은 형식과 형태를 유지하지만 png를 제외한 나머지 포멧도 설정해야 하기에 아래와 같이 코드를 수정해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1721319986117&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// webpack.config.js (5 버전 이상)

{
    test: /\.(png|jpg|gif|svg)$/,
    type: 'asset/resource',
    generator: {
      publicPath: './dist/',
      filename: 'assets/[name].[ext]?[hash]',
    },
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이전과 변경된게 있다면 우리가 hash값으로 변환이 된 파일을 확인하기 위해서 [name].[hash][ext] 이와 같이 작성을 했다. 하지만 이번엔 [name].[ext]?[hash]과 같이 작성을 했다. 이 둘의 차이는 아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;[name].[hash][ext]&lt;/b&gt; / 결과 파일 이름: example.1234567890abcdef.png&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[name].[ext]?[hash]&lt;/b&gt; / 결과 파일 이름: example.png&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;s&gt;?1234567890abcdef &lt;/s&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 요소들의 설명을 아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;[name]&lt;/b&gt;: 원본 파일의 이름을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[ext]&lt;/b&gt;: 원본 파일의 확장자를 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[hash]&lt;/b&gt;: 파일 내용 기반으로 생성된 해시 값을 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 그렇다면 '?'는 무슨 의미인가 우선 쿼리 파라미터 형식 기법이지만 webpack 5이상부터는 이를 지원 하지 않아서 '?'부터 일절 무시를 한다. 이에 따라서 원본 파일명으로 dist 폴더에 저장이되는 것이다. 가기 두 형식으롤 build한 결과를 보면 아래와 같다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[name].&lt;/b&gt;&lt;b&gt;[hash]&lt;/b&gt;&lt;b&gt;[ext]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1721322897973&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist
├── assets
│   ├── git-logo-icon.e6cb70b6c44cc2e8835a.png
│   └── npm-icon.1c616bc0f7d12cf5f824.png
│  
└── main.js&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[name].[ext]&lt;/b&gt;&lt;b&gt;[hash]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1721322719315&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist
├── assets
│   ├── git-logo-icon..pnge6cb70b6c44cc2e8835a
│   └── npm-icon..png1c616bc0f7d12cf5f824
│  
└── main.js&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[name].[ext]?&lt;/b&gt;&lt;b&gt;[hash]&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1721323107114&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist
├── assets
│   ├── git-logo-icon.png
│   └── npm-icon.png
│  
└── main.js&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간 점검으로 나의 pcakge.json 파일을 살펴보면 file-loader, url-loader는 현재 없다. 물론 yarn install도 해주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1721319924893&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// package.json

  &quot;devDependencies&quot;: {
    &quot;webpack&quot;: &quot;^5.75.0&quot;,
    &quot;webpack-cli&quot;: &quot;^4.10.0&quot;
  },
  &quot;dependencies&quot;: {
    &quot;css-loader&quot;: &quot;^6.7.1&quot;,
    &quot;style-loader&quot;: &quot;^3.3.1&quot;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 yarn run build를 해주면 잘 build 된 것을 볼 수가 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;url-loader&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;수업에서는 webpack 5 이하 버전이라서 limit을 사용 할 수 있지만 webpack 5이상 부터는 전혀 다르게 이미지 크기 파일을 제한 할 수 있다. 아래와 비교해보면서 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1721323598785&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// webpack.config.js (5 버전 이하)

 {
    test: /\.(png|jpg|gif|svg)$/,
    loader: 'url-loader',
    options: {
    	publicPath: './dist/',
        name: '[name].[ext]?[hash]',
        limit: 2000, // 2KB
    }
},&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1721323650315&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// webpack.config.js (5 버전 이상)

  {
    test: /\.(png|jpg|gif|svg)$/,
    type: 'asset/resource',
    generator: {
      publicPath: './dist/',
      filename: 'assets/[name].[ext]?[hash]',
    },
    dependency: { not: ['url'] },
    parser: {
      dataUrlCondition: {
        maxSize: 20000, // 2KB
      },
    },
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정하고 yarn run build를 하기 전 현재 나의 이미지 파일의 크기를 살펴보기 위해서 아래와 같이 명령어를 통해서 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1721323950736&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD : ls -l src

-rw-r--r-- 1 rxxxxxxxx 197121    88  -월 17 21:21 app.css
-rw-r--r-- 1 rxxxxxxxx 197121   305  -월 19 01:15 app.js
drwxr-xr-x 1 rxxxxxxxx 197121     0  -월 17 20:11 css
-rw-r--r-- 1 rxxxxxxxx 197121  7040  -월 12 23:35 git-logo-icon.png
-rw-r--r-- 1 rxxxxxxxx 197121    47  -월 17 22:49 math.js
-rw-r--r-- 1 rxxxxxxxx 197121 32816  -월 24 18:35 npm-icon.png&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 dist 폴더에 결과를 살펴보면 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1721329216214&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist
├── assets
│   └── npm-icon..png
│
├── e6cb70b6c44cc2e8835a.png
└── main.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 브라우저의 결과는 인라인(assets)에 포함 되지 않은 모든 이미지를 렌더링 한다. 따라서 이를 제한 할 수 있는 방법 별도로 파일을 제한 할 수 있는 js파일을 만들어서 path.resolve를 통해서 해당 이미지를 걸러 낼 수 있는 방법이 있다.&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;참고로 'dependency: { not: ['url'] }' 설정은 URL 호출로 인해 발생한 애셋에 대해 file-loader 규칙을 적용하지 않는다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;u&gt;즉, import '&lt;a href=&quot;https://example.com/image.png';와&quot;&gt;https://example.com/image.png';와&lt;/a&gt; 같이 URL에서 가져오는 이미지는 이 로더 규칙의 적용을 받지 않는다.&lt;/u&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(확인 중...) &lt;span style=&quot;color: #dddddd;&quot;&gt;file-loader와 url-loader를 사용 하는 방식이다. webpack 5에서 asset/resoucre를 사용해서 이전 버전과 달리 url-loader와 file-loader를 따로 설정하지 않아도 되는 편리성은 있지만 현재 수업처럼 limit을 사용하기 위해선 아래 코드와 같이 적용을 하면 된다. 하지만 생각한 것과 다르게 잘 동작하지 않는 것을 확인 할 수 있다. 아마 file-loader 방식과 url-loader 방식의 차이가 있다. import 방식과 css에서 url로 호출 하는 방식의 차이가 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1721328727070&quot; class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;  {
    test: /\.(png|jpg|gif|svg)$/i,
    type: 'asset/resource',
    generator: {
      publicPath: './dist/',
      filename: 'assets/[name].[ext]?[hash]',
    },
    dependency: { not: ['url'] },
    use: [
      {
        loader: 'url-loader',
        options: {
          limit: 8192,
        },
      },
    ],
  },&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;조금 더 분석해 볼 필요가 있다. url-loader와 file-loader의 차이를 좀 더 명확하게 살펴볼 필요가 있고 webpack 5에서 base-64로 인코딩 되는 것과 url로 처리할 수 있는 방법을 좀 더 찾아서 공부해볼 필요가 있다. 많이 아쉬운 부분 이지만 많은 시도로 대략적인 웹팩의 이미지처리 방식을 맛 볼 수 있었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REFERENCE&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://webpack.kr/guides/asset-modules/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://webpack.kr/guides/asset-modules/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@tkdals0978/Webpack5-loader&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@tkdals0978/Webpack5-loader&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/418</guid>
      <comments>https://hi-code.tistory.com/418#entry418comment</comments>
      <pubDate>Fri, 19 Jul 2024 04:00:41 +0900</pubDate>
    </item>
    <item>
      <title> Webpack : file-loader</title>
      <link>https://hi-code.tistory.com/417</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우선 이미지를 import하기 위해서 아래와 같이 css를 변경해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1721218877827&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;body {
  background-image: url(git-logo-icon.png);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 우선 yarn의 pnp로 동작을 설정한 나의 프로젝트 파일에선 오류가 실행되지 않고 정상적으로 빌드가 되었다고 나오고 있다. 거기다 브라우저에서는 내가 설정한 image가 제대로 동작하고 있다. 왜그런가 생각해보니 내가 이미 node_modules를 pnp로 전환해서 yarn-berry의 특징인 cache 폴더안에서 이미 file-loader가 존재해서 해결이 되고 있는 것이라고 짐작을 했다. 하지만 나의 추측과는 전혀 무관했다. file-loader를 무시하고 바로 webpack.config파일을 설정하니 그제서야 오류가 발생한 것이다. 따라서 다시 아래와 같이 file-loader를 설정했다.&lt;/p&gt;
&lt;pre id=&quot;code_1721219689654&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

npm install file-loader

yarn install file-loader&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 하지만 webpack.cofing 설정 과정에서 file-loader를 직접 다루려고 하니 file-loader없이 잘 동작하던 빌드가 이미지 처리가 되지 않고 있는 것이다. 확인을 해보니 webpack과 다른 패키지들의 버전 정보가 수업에서 하는 버전과 달라서 발생한 문제였다. webpack 5이상 부터는 file-loader를 포함시켰다는 것이다. 이에 따라 webpack과 나머지 패키지들을 모두 수업에서 다루는 버전으로 다시 맞추고 실행해 보려고 했으나 이전과 같이 style-loader를 찾지 못하는 불상사가 반복되었다. 그래서 수업과는 별개로 최신 버전에 맞춰서 webpack.config를 설정하기로 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1721223115809&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js (5 이상 버전)

  {
    test: /\.png$/,
    type: 'asset/resource'
  }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1721223221100&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js (5 이하 버전)

  {
    test: /\.png$/,
    use: [
      'file-loader'
    ],
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 추가적으로 설명하자면&amp;nbsp; 웹팩 5버전 이상에서는 몇 가지 중요한 변경 사항이 있다. file-loader, url-loader, 및 raw-loader와 같은 로더들은 웹팩 5부터는 자체적으로 포함된 기능으로 대체되었다. 그러나 특정한 경우에는 여전히 file-loader와 같은 로더를 직접 사용해야 하려면 위와 같이 type: 'asset/resource'방식으로 수행하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 웹팩 버전과 yarn-berry의 호환성 문제는 뒤로하고 dist폴더로 가보면 이미지 파일이 있는 것을 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1721224343246&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist
├── e6cb70b6c44cc2e8835a.png
└── main.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 우리가 지정해 놓은 이미지 파일의 파일명이 아닌 해시 값으로 이름이 변경 되어 있다. 웹팩은 빌드가 될 때 마다 이렇게 해시 값으로 파일명이 변경된다. 정적파일의 경우 캐싱 문제를 해결하기 위해서 해시값을 이용한다. 브라우전에서 캐싱을 하는 경우는 이미지 외에도 자바스크립트나 css, 이미지 폰트가 있다. 브라우저는 캐시를 사용하여 동일한 파일을 다시 다운로드하지 않도록 한다. 그러나 파일이 변경되었을 때 브라우저가 최신 버전을 로드하도록 파일 이름에 해시 값을 포함시키면 파일 내용이 변경될 때마다 새로운 파일 이름이 생성되므로 브라우저는 항상 최신 파일을 로드하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 이름을 설정할 수 있게 webpack.config에서 설정하면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1721225152674&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; //webpack.config.js (5 버전 이하)
 
 {
    test: /\.png$/,
    loader: 'file-loader',
    options: {
    	publicPath: './dist/',
        name: '[name].[ext]?[hash]'
    }
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1721225180725&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//webpack.config.js (5 버전 이상)

 {
    test: /\.png$/,
    type: 'asset/resource',
    generator: {
      filename: 'assets/[name].[hash][ext]',
      publicPath: './dist/',
    },
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 작성자는 assets폴더 아래에 본래 파일명과 함께 해시값을 부여했다. 그래서 결과적으로 아래와 같은 디렉토리 구조로 dist폴더에 파일들이 설정 된 것을 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1721225417201&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dist
├── assets
│   └── git-logo-icon.e6cb70b6c44cc2e8835a.png
│
├── e6cb70b6c44cc2e8835a.png
└── main.js&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.js에서는 아래와 같이 확인이 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1721225520532&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//main.js

/** 이하생략 */

...(&quot;module.exports = \&quot;./dist/assets/git-logo-icon.e6cb70b6c44cc2e8835a.png\&quot;;\n\n//#...

/** 이하생략 */&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 구버전으로 문제를 해결하지 못한 점이 매우 아쉽지만 최신 버전에 적응을 해야하는 것이 급선무라고 생각이 되어서 이렇게 최신버전으로 수행해 보았다. yarn-berry기반으로 프로젝트를 세팅해서 yarn-berry의 pnp 호환성 문제가 가장 클 것으로 추측이 된다. 아무래도 yarn-berry의 단점이 호환성 문제이기 때문에 최신 버전에 맞게 설정을 할 수 밖에 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REFERCNE&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://webpack.kr/guides/asset-modules&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://webpack.kr/guides/asset-modules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/417</guid>
      <comments>https://hi-code.tistory.com/417#entry417comment</comments>
      <pubDate>Wed, 17 Jul 2024 23:13:49 +0900</pubDate>
    </item>
    <item>
      <title> Webpack : css-loader, style-loader</title>
      <link>https://hi-code.tistory.com/416</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 자주 사용되는 loader에 관해서 다루어 볼 것이다. 먼저 css-loader와 style-loader를 다루어 볼것이다. 강의는 짧지만 다루고 있는 내용이 많아서 두번에 나누어서 포스팅을 할 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1721208478487&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//app.js

import * as math from './math.js'
import './app.css';
// import { sum } from './math.js';
console.log(math.sum(1, 2));
// console.log(sum(1,2));&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1721208497084&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//app.css

body {
  background-color: green;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 css파일을 추가하고 app.js에 import하고 build를 해보면 아래와 같은 결과를 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1721208414698&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;D:\myclass\0_Programming-content\Frontend-Development-Environment&amp;gt;yarn run build
Hash: b21c535998629576ab9e
Version: webpack 4.47.0
Time: 515ms
Built at: 2024. 07. 17. 오후 6:26:18
  Asset      Size  Chunks             Chunk Names
main.js  5.34 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/app.css] 272 bytes {main} [built] [failed] [1 error]
[./src/app.js] 142 bytes {main} [built]
[./src/math.js] 47 bytes {main} [built]

ERROR in ./src/app.css 1:5
Module parse failed: Unexpected token (1:5)
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
&amp;gt; body {
|   background-color: green;
| }
 @ ./src/app.js 2:0-19&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이러한 문제가 발생 했을까? 이는 자바스트립트로부터 css를 모듈로 처리함에 있어서 발생된 문제이다. 이를 css-loader인데 이번 시간에 우리는 이를 다루어 볼 것이다. 먼저 loader를 사용하기 위해선 아래와 같이 설정이 필요하다.&lt;/p&gt;
&lt;pre id=&quot;code_1721208839197&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

npm install css-loader

yarn add css-loader&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 css-loader를 설치하면 기존 package.json과 달리 dependcies에 css-loader가 생성된 것을 알 수 있다. 이는 &lt;b&gt;배포가 될 때&lt;/b&gt; 사용될 라이브러리라는 것을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1721208858448&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//(전)-package.json
{
  &quot;name&quot;: &quot;Frontend-Development-Environment&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;packageManager&quot;: &quot;yarn@4.3.0&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;amp;&amp;amp; exit 1&quot;,
    &quot;build&quot;: &quot;webpack&quot;,
    &quot;start&quot;: &quot;echo \&quot;여기에 스타트 스크립트를 추가합니다.\&quot;&quot;
  },
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;devDependencies&quot;: {
    &quot;webpack&quot;: &quot;^4.41.5&quot;,
    &quot;webpack-cli&quot;: &quot;^3.3.10&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1721208873268&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//(후)-package.json
{
  &quot;name&quot;: &quot;Frontend-Development-Environment&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;packageManager&quot;: &quot;yarn@4.3.0&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;amp;&amp;amp; exit 1&quot;,
    &quot;build&quot;: &quot;webpack&quot;,
    &quot;start&quot;: &quot;echo \&quot;여기에 스타트 스크립트를 추가합니다.\&quot;&quot;
  },
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;devDependencies&quot;: {
    &quot;webpack&quot;: &quot;^4.41.5&quot;,
    &quot;webpack-cli&quot;: &quot;^3.3.10&quot;
  },
  &quot;dependencies&quot;: {
    &quot;css-loader&quot;: &quot;^7.1.2&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 webpack.config 파일로 돌아가서 css를 처리할 수 있게 설정 할 것이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1721209135476&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          path.resolve('./my-webpack-loader.js')
        ]
      }
      {
        test: /\.css$/,
        use: [
          'css-loader'
        ]
      }
    ]
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 설정을 하면 Entry 포인터 부터 모든 파일들을 확인하면서 우리가 설정한 css 파일을 확인하고 이를 css-loader가 css 파일을 처리하게 될 것이다. 다시 yarn run build를 하게되면 성공적으로 빌드가 되고 dist 폴더 아래를 확인하면 main.js폴더 내부에 아래와 같이 css코드를 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1721209332082&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//main.js

/** 이하생략 */

{
  ...body {\\n|   background-color: green;\\n| }\&quot;);\n\n//# sourceURL=webpack:///./src/app.css?
}

/** 이하생략 */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 liver-server로 확인을 하면 아래와 같은 에러가 발생한다.&lt;/p&gt;
&lt;pre id=&quot;code_1721209676250&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Live reload enabled.
app.css:1 Uncaught Error: Module parse failed: Unexpected token (1:5)
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
&amp;gt; body {
|   background-color: green;
| }
    at eval (app.css:1:7)
    at ./src/app.css (main.js:96:1)
    at __webpack_require__ (main.js:20:30)
    at eval (app.js:3:66)
    at ./src/app.js (main.js:108:1)
    at __webpack_require__ (main.js:20:30)
    at main.js:84:18
    at main.js:87:10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 실행된 웹의 개발도구로 body를 탐색해보면 우리가 설정한 css가 적용되지 않은 것을 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clR5aD/btsIDGKQmtG/zsKrAKFdASOhM4CMrzPOE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clR5aD/btsIDGKQmtG/zsKrAKFdASOhM4CMrzPOE0/img.png&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;527&quot; data-is-animation=&quot;false&quot; width=&quot;573&quot; height=&quot;425&quot; style=&quot;width: 46.5438%; margin-right: 10px;&quot; data-widthpercent=&quot;47.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clR5aD/btsIDGKQmtG/zsKrAKFdASOhM4CMrzPOE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclR5aD%2FbtsIDGKQmtG%2FzsKrAKFdASOhM4CMrzPOE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;710&quot; height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R1yEr/btsID5DyMrF/GVkHbH2CY53bZqpYGZBuh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R1yEr/btsID5DyMrF/GVkHbH2CY53bZqpYGZBuh0/img.png&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;658&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.2934%;&quot; data-widthpercent=&quot;52.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R1yEr/btsID5DyMrF/GVkHbH2CY53bZqpYGZBuh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR1yEr%2FbtsID5DyMrF%2FGVkHbH2CY53bZqpYGZBuh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;996&quot; height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;body에 아무것도 설정된 것이 없다. 하지만 NetWork에서 JS의 preview를 확인해 보면 backgroud-color가 문자열로 잘 설정된 것을 확인 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 왜 이렇게 된 것일까? 그것은 우리가 DOM을 간과한 것이다. 그 말은 HTML코드가 DOM이라는 모습으로 변환이 되지 않아서 그렇다. 즉, JS가 Document 문서로 변환이 되어야 브라우저에서 문서로 확인이 될 수 있듯 css는 CSS-OM이라는 문서로 변환이 되어야 한다. 그렇게 하기 위해서는 HTML파일에서 css파일을 직접 불러오거나 inline-Style로 직접 넣어줘야 한다.(css가 css 파일보다 css-inline-Style을 먼저 읽는 이유가 여기에 포함된다.) 따라서 우리는 JS파일에서 모듈로 css를 불러오기 때문에 별도의 패키지를 설정해야한다. 아래와 같이 추가적이 패키지를 설치하자.&lt;/p&gt;
&lt;pre id=&quot;code_1721210499304&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;::CMD

yarn add style-loader

npm install style-loader&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Style-loader는 JS로 변환된 css를 HTML에 넣어주는 역할을 한다. 역시나 pacakge.json의 dependenies에 style-loader가 추가된 것을 확인 할 수 있었다. 이와 마찬가지로 webpack.config 파일에 아래와 같이 설정을 추가해준다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1721211504925&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/app.js'
  },
  output: {
    path: path.resolve('./dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          path.resolve('./my-webpack-loader.js')
        ]
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 설치가 되었으면 다시 run build를 수행하면 된다. 수행한 결과 아래와 같은 에러가 발생했다.&lt;/p&gt;
&lt;pre id=&quot;code_1721211429998&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;D:\myclass\0_Programming-content\Frontend-Development-Environment&amp;gt;yarn run build        
Hash: 538273a0ce3b6faa1797
Version: webpack 4.47.0
Time: 173ms
Built at: 2024. 07. 17. 오후 7:10:02
  Asset     Size  Chunks             Chunk Names
main.js  4.7 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/app.js] 142 bytes {main} [built]
[./src/math.js] 47 bytes {main} [built]

ERROR in ./src/app.js
Module not found: Error: Can't resolve 'style-loader' in 'D:\myclass\0_Programming-content\Frontend-Development-Environment'
 @ ./src/app.js 2:0-19&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 style-loader를 찾지 못하는 불상사가 벌어졌는데 이를 해결하기 위해서 아래와 같이 yarn의 cache파일을 삭제해 주었다. 이후 yarn install로 다시 yarn을 설치하고 다시 run build를 해주었지만 계속해서 같은 오류를 반복하며 webpack를 손실하게 되는 불상사가 일어났다. 이럴 때는 다시 webpack을 설치하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;webpack 덮어서 재설치&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;yarn add webpack --dev&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 왜 계속해서 이런 오류가 반복적일까? 확인해 보니 현재 나는 node_modules 기반이 아닌 pnp기반으로 동작하고 있다. 따라서 pnp가 일부 호환되지 않아서 일어난 불상사였던 것이다. pnpFallbackMode: all은 호환성 문제를 해결하는데 사용된다. 따라서 이를 해결하기 위해서는 yarnrc.yml파일에 아래와 같이 추가하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1721215776125&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//yarnrc.yml

pnpFallbackMode: all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 yarn cache clear를 실행하고 yarn install 후 yarn run build를 하니 정상적으로 동작을 했다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1721222759395&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;::CMD

yarn cache clear
yarn install
yarn run build&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시나 해서 package.json을 확인해보니 모든 패키지와 웹팩들 버전이 상위 버전으로 업그레이드 되어 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1721222717011&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//package.json

  &quot;devDependencies&quot;: {
    &quot;webpack&quot;: &quot;^5.75.0&quot;,
    &quot;webpack-cli&quot;: &quot;^4.10.0&quot;
  },
  &quot;dependencies&quot;: {
    &quot;css-loader&quot;: &quot;^6.7.1&quot;,
    &quot;style-loader&quot;: &quot;^3.3.1&quot;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수업에서 현재 진행하고 있는 버전과는 맞지 않지만 정상적으로 동작하고 있으니 우선은 이렇게 버전을 맞춰서 진행을 하면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REFERNCE&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/CSS_Object_Model&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/CSS_Object_Model&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>⚛️React/ Front-Dev-Environment</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/416</guid>
      <comments>https://hi-code.tistory.com/416#entry416comment</comments>
      <pubDate>Wed, 17 Jul 2024 21:17:38 +0900</pubDate>
    </item>
    <item>
      <title> Nodejs : section30~33 - form 그리고 response</title>
      <link>https://hi-code.tistory.com/413</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 form에서 부터 response까지 사용자가 입력한 값을 받아서 사용자에게 응답을 전달하는 모든 과정들을 살펴 볼 것이다. 비록 실제 data를 처리하는 sql이 아니지만 이를 통해서 대략적인 흐름과 맥락을 어느정도 가늠 해볼 수 있을 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;form&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 html을 작성해보고 실행을 해보고 URI의 결과를 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1719199123307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- form.html --&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;

&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
  &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
  &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
  &amp;lt;form action=&quot;http://localhost:3000/process_create&quot;&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;title&quot;&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;
      &amp;lt;textarea name=&quot;description&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
    &amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;
      &amp;lt;input type=&quot;submit&quot;&amp;gt;
    &amp;lt;/p&amp;gt;
  &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URI&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1719199337954&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://localhost:3000/process_create?title=test&amp;amp;description=test+des&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고로 위와 같은 결과를 얻기 위해서는 로컬 서버를 돌려야 한다. 본인은 live server를 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 살펴보면 form으로 전송된 input값으로 URI queryString을 만들어낸다는 것을 알 수 있다. 즉, input에 사용자가 입력한 값을 input type의 submit으로 전송을 하면 form태그의 action 속성으로 지정한 주소 URI에 queryString을 부여한 다는 것을 알 수 있다. 이 방법은 좋은 방법이 아니다. 불필요한 정보를 담아서 웹에 정보를 노출하는 것이다. 즉, 우리가 Get으로 id의 quryString 을 보여주는 방식은 괜찮지만 post와 같은 중요한 정보를 서버에 전달할 때는 위와 같은 방식을 하게 되면 사용자의 정보가 노출 되는 것이기 때문에 좋지 않다. 따라서 아래와 같이 데이터 전송 방식(method)을 지정해 주면 아까와 같이 URI의 queryString이 외부로 노출 되지 않는다.&lt;/p&gt;
&lt;pre id=&quot;code_1719199996794&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- form.html --&amp;gt;

&amp;lt;form action=&quot;http://localhost:3000/process_create&quot; method=&quot;POST&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URI&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1719200098680&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://localhost:3000/process_create&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Create&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글을 생성하는 페이지를 추가할 것이다. 그러기 위해서는 글을 생성하는 페이지로 넘어 갈 수 있는 링크가 필요하다. 아래와 같이 a태그를 추가 하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1719207211864&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */
/* 이하 생략 */

function templateHTML(title, list, body) {//list는 받아온 list를 return을 통해서 제작된다.
  return `
  &amp;lt;!doctype html&amp;gt;
  &amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;WEB1 - ${title}&amp;lt;/title&amp;gt;
    &amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;&amp;lt;a href=&quot;/&quot;&amp;gt;WEB&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
    ${list} 
    &amp;lt;a href=&quot;/create&quot;&amp;gt;create&amp;lt;/a&amp;gt;
    ${body}
  &amp;lt;/body&amp;gt;
  &amp;lt;/html&amp;gt;
  `;
}

/* 이하 생략 */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 시간에 우리는 코드의 효율을 높이기 위해서 렌더링 되어야하는 html부분을 함수로 따로 빼내서 template에 정의 했다. a태그를 위와 같은 곳에 추가 해서 '/create' 페이지로 넘겨 줄 수 있게 설정을 해준다. 이후 해당 path에 맞는 페이지를 createServer에 추가 해주면 된다. 추가 해야할 path는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1719207451646&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */
//var app = http.createServer(function (request, response) { ~

else if (pathname === '/create') { //pathname(url.parse(_url, true).pathname)이 create일 경우 아래 코드 실행
    fs.readdir('./data', function (error, filelist) {
      var title = 'WEB - create';
      // var description = 'Hello, Node.js';
      var list = templateList(filelist); //해당 매개변수로 받아온다. 여기서 이해가 안감.
      var template = templateHTML(title, list, `
      &amp;lt;form action=&quot;http://http://localhost:3000/create_process&quot; method=&quot;POST&quot;&amp;gt;
        &amp;lt;p&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;title&quot; placeholder=&quot;title&quot;&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;textarea name=&quot;description&quot; placeholder=&quot;description&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
        &amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;
          &amp;lt;input type=&quot;submit&quot;&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/form&amp;gt;`);//html 구문을 생성하는 코드
      response.writeHead(200); //200이란 web브라우저의 승인으로 생성
      response.end(template);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 작성하면 이제 '/create' pathName을 가진 URI주소로 넘어가 글을 생성 할 수 있는 페이지가 완성이 된다. 여기서 주의해서 봐야 하는 부분은 위에서 다루었던 form태그이다. 역시나 글을 생성하는 페이지기 때문에 form태그의 데이터 전송 방식(method)는 post여야한다. 이를 통해 form 태그로 부터 전송된 데이터들을 은닉하게 되며 외부로 부터 노출되지 않게 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;create_process(doCreate)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 &lt;b&gt;글을 생성&lt;/b&gt;하는 페이지를 만들었다면 작성된 글을 서버로 보내는 페이지가 필요하다. 앞전의 코드에서 form태그의 action의 URI는 '/create_process'로 되어 있다. 우리가 create페이지를 만들었던 것 처럼 이번에도 같게 작성하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1719208049396&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */
var qs = require('querystring'); //모듈

//var app = http.createServer(function (request, response) { ~

else if (pathname === '/create_process') { //create에서 POST한 데이터 가져오기
    let body = ''
    request.on('data', function (data) {
      body = body + data
    })
    request.on('end', function () {
      let post = qs.parse(body) //querystring 모듈을 통해서 create에서 post로 전송받은 값을 가져올 수 있다.
      var title = post.title;
      var description = post.description;
      console.log(post)
    })
    response.writeHead(200); //200이란 web브라우저의 승인으로 생성
    response.end('success');
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위코드를 유심히 보면 body라는 변수가 있다. 위 변수는 내가 서버에 전송할 data를 담아내는 역할 이라고 보면 된다. 실제 API와 통신에서 Post를 할 때 백엔드에서 body에 어떤 값을 넣어야 하는지 &lt;b&gt;규칙과 요소들을 설정하는데&lt;/b&gt; 위의 코드가 이와 같은 역할을 하는 것이다. 아래 코드를 통해서 자세한 사항들을 살펴 볼 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; create_process(doCreate) 코드의 분석&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;경로 확인&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1719208435115&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */

else if (pathname === '/create_process') { ~&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 조건문은 URL의 경로명이 /create_process일 때만 실행되도록 한다. 이 경로는 폼 데이터(formData)가 서버로post되는 &lt;b&gt;엔드포인트&lt;/b&gt;로 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;데이터 수신&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1719208442310&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */

let body = '';
request.on('data', function (data) {
  body += data;
});&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;body 변수를 초기화하여 사용자로부터 수신된 데이터를 저장한다.&lt;/li&gt;
&lt;li&gt;request.on('data', callback) 리스너는 사용자로부터 데이터가 &lt;b&gt;스트림 형태&lt;/b&gt;로 도착할 때마다 호출된다. 이 때 수신된 data를 body에 삽입한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;데이터 처리 완료&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1719208451693&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */

request.on('end', function () {
  let post = qs.parse(body);
  var title = post.title;
  var description = post.description;
  console.log(post);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;request.on('end', callback) 이벤트는 데이터 수신이 완료되었을 때 호출된다. 이 시점에서 모든 데이터가 body 변수에 저장되어 있다.&lt;/li&gt;
&lt;li&gt;qs.parse(body)를 사용하여&lt;b&gt; URL 인코딩된 문자열&lt;/b&gt; body를 JavaScript 객체로 파싱한다. qs는 querystring 모듈의 일반적인 별칭이며 이 객체에서 title과 description 필드를 추출한다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참고로 아래와 같이 console로 확인을 해보면 이와 같은 결과를 얻어 낼 수 있다.&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1719210070726&quot; class=&quot;stata&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;/* main.js */

request.on('end', function () {
      console.log(&quot;body: &quot;, body);
      console.log(&quot;queryString: &quot;, qs);
      let post = qs.parse(body);
      var title = post.title;
      var description = post.description;
      console.log(&quot;post: &quot;, post);
    })&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1719210097814&quot; class=&quot;perl&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;body:  title=%ED%85%8C%EC%8A%A4%ED%8A%B8+%EC%9E%85%EB%8B%88%EB%8B%A4.&amp;amp;description=%ED%85%8C%EC%8A%A4%ED%8A%B8+%EC%84%A4%EB%AA%85+%EC%9E%85%EB%8B%88%EB%8B%A4.
queryString:  {
  unescapeBuffer: [Function: unescapeBuffer],
  unescape: [Function: qsUnescape],
  escape: [Function: qsEscape],
  stringify: [Function: stringify],
  encode: [Function: stringify],
  parse: [Function: parse],
  decode: [Function: parse]
}
post:  [Object: null prototype] {
  title: '테스트 입니다.',
  description: '테스트 설명 입니다.'
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;응답&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1719208458823&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */

response.writeHead(200); //200이란 web브라우저의 승인으로 생성
response.end('success');&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;response.writeHead(200)로 HTTP 상태 코드 200을 클라이언트에 전송합니다. 200은 요청이 성공적으로 처리되었다는 의미입니다.&lt;/li&gt;
&lt;li&gt;response.end('success')로 응답을 종료하고 클라이언트에게 'success'라는 메시지를 보냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;post로 받은 데이터로 파일 생성하기 fs.writeFile&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 create_process를 통해서 사용자로 부터 post로 받은 데이터 값들을 받아 올 수 있는 코드를 작성 했다. 이제 남은건 해당 데이터들을 가지고 data폴더에 post로 받아온 데이터 값들로 파일을 생성하는 코드를 추가적으로 작성할 것이다. 추가된 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1719210844441&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* main.js */
// request.on('end', function () { ~
// ...이하 생략...
var description = post.description;
      // console.log(post)
      fs.writeFile(`data/${title}`, description, 'utf8', (err) =&amp;gt; {
        response.writeHead(302, { Location: `/?id=${title}` }); //200이란 web브라우저의 승인으로 생성
        response.end();
      })
 // ...이하 생략...&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;파일 쓰기()&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fs.writeFile 함수는 &lt;b&gt;첫 번째 인자&lt;/b&gt;로 파일의 경로와 이름을 받는다. 여기서는 data/${title}을 사용하여 data 디렉토리 내에 title 변수의 값에 해당하는 이름으로 파일을 생성하거나 덮어쓰기 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;두 번째 인자&lt;/b&gt;인 description은 파일 안에 쓸 내용이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세 번째 인자&lt;/b&gt; 'utf8'은 파일을 쓸 때 사용할 인코딩 방식을 지정한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네 번째 인자&lt;/b&gt;는 콜백 함수로 파일 쓰기 작업이 완료되었을 때 실행된다. 에러가 발생하면 err 파라미터에 에러 객체가 전달됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;응답 처리&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;콜백 함수 내부에서 response.writeHead(302, { Location: /?id=${title} });를 호출하여 HTTP 상태 코드 302(리다이렉션-코드의 리소스의 위치가 바뀌었다.는 뜻)와 함께 Location 헤더를 설정한다. &lt;u&gt;&lt;i&gt;Location은&amp;nbsp;&lt;b&gt;사용자가 리다이렉션 될 새로운 URL을 지정한다.&lt;/b&gt; 여기서는 쿼리 스트링으로 id 파라미터에 &lt;b&gt;title의 값을 주어 파일이 성공적으로 생성되었을 때&lt;/b&gt; 사용자를 &lt;b&gt;해당 파일의 페이지로 리다이렉트 시킵니다.&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;response.end()는 HTTP 응답을 종료하고 설정된 헤더와 본문을 사용자에게 전송한다. 이 경우 별도의 본문 내용을 전송하지 않으므로 단순히 응답을 마무리 짓는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;시도 해볼 수 있는 response&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;post가 성공적으로 이루어 지면 사용자에게 response로 title과 description을 전달해보자면 아래와 같이 작성하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1719211553839&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//json 파일 형시으로 응답
fs.writeFile(`data/${title}`, description, 'utf8', (err) =&amp;gt; {
    if (err) {
        response.writeHead(500, { 'Content-Type': 'application/json' });
        response.end(JSON.stringify({ error: 'Failed to write file' }));
    } else {
        response.writeHead(200, { 'Content-Type': 'application/json' });
        response.end(JSON.stringify({ title: title, description: description }));
    }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 유의해야 할 점은 포멧 설정이다. 포멧에 따라서 Content-Type을 잘 설정해야 한다. 현재는 JSON 응답으로 주는 경우이기 때문에 application/json으로 설정했다. 만약 html로 응답을 할 경우 text/html로 설정하면 된다.&lt;/p&gt;</description>
      <category> Nodejs/⚡ver.0</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/413</guid>
      <comments>https://hi-code.tistory.com/413#entry413comment</comments>
      <pubDate>Mon, 24 Jun 2024 12:38:46 +0900</pubDate>
    </item>
    <item>
      <title> Nodejs : section28(1~3) - 동기와 비동기</title>
      <link>https://hi-code.tistory.com/412</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 Nodejs를 잘 이해하기 위해서는 동기와 비동기를 알아야 한다. 지금까지 내가 알고 있는 동기와 비동기는 이와 같다. 동기는 순차적으로 일을 처리한다. 비동기는 각 개인들이 일을 시작 할 수 있는 시간 개념을 가지고 있어서 동시 다발적으로 일을 처리한다. 그래서 우리는 비동기를 await과 같은 명령어로 제어한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의를 토대로 첨삭을 한다면 &lt;br /&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&quot;동기는 직렬로 구성이 되어 있어서 일을 처리함에 있어서 시간 소요가 많이 든다. 하지만 비동기는 병렬로 구성이 되어 있어서 일을 처리함에 있어서 효율 적이다. Nodejs는 비동기적 처리를 하기 위한 좋은 기능을 가지고 있다.&quot; &lt;br /&gt;&lt;/span&gt;&lt;/i&gt;이 수업을 통해서 우리는 조금 더 진보적이고 Nodejs의 근간이되는 Nodejs를 공부 해 볼 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;readFileSync( path, [option] ) : 동기적 방식&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1719154403359&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* 
* sync.js
* readFileSync( path, [option] )
*/

let fs = require('fs');

console.log('A');
let result = fs.readFileSync('syntax/sample.txt', 'utf8');//동기적 방식
console.log('C');&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1719154427916&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A
B
C&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;readFile( path, [option], callback ) : 비동기적 방식&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;readFile을 보면서 Promise, then을 사용해보고 싶었다. 찾아보니 readFilePromise 함수(또는 require('fs').promsies; 사용)가 있지만 생각해보면 &lt;b&gt;callback 함수&lt;/b&gt;가 존재하는 &lt;b&gt;비동기 처리 함수&lt;/b&gt; readFile을 지금 굳이 Promise 방식을 사용하면서 비동기로 만들 필요가 없다 느꼈다.&lt;/p&gt;
&lt;pre id=&quot;code_1719154388519&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* 
* sync.js
* readFile( path, [option], callback )
*/

let fs = require('fs');

console.log('A');
//비동기적 방식
fs.readFile('sample.txt', 'utf8', function (err, result) {
  console.log(result);
});
console.log('C');&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1719154439753&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A
C
B&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Callback&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백함수는 내부적으로 동작한다. 먼저 선언 되어 있는 외부 함수가 실행이 되고 난 다음 결과를 받아 에 내부 함수(callback)에 전달 후 함수(callback)가 동작하라고 하는 것과 같다. 예시를 들어보면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1719155356938&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* callback.js */
let a = function () {
  console.log('A');
}
function slowfunc(callback) {//매개변수로 함수를 가져올 때 ()없이 사용해야한다.
  callback()
}
slowfunc(a);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고로 위의 코드는 비동기가 아닌 동기적 함수이다. callback을 이해하기 위한 예시일 뿐 비동기적 함수가 아니다. 굳이 비동기적으로 구현을 하고 싶다면 setTimeout함수를 사용해야하는데 이는 결국 비동기 함수인 setTimeout을 사용하는 것이기에 내가 직접 비동기 함수 없이 코드를 작성하는 것엔 한계가 있는 것 같다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로서 우리는 비동기와 callback을 알게 되었다. 다음 포스팅에서 이를 토대로 비동기를 nodejs로 직접 제어하는 포스팅을 작성 할 것이다.&lt;/p&gt;</description>
      <category> Nodejs/⚡ver.0</category>
      <author>4:Bee</author>
      <guid isPermaLink="true">https://hi-code.tistory.com/412</guid>
      <comments>https://hi-code.tistory.com/412#entry412comment</comments>
      <pubDate>Mon, 24 Jun 2024 00:13:15 +0900</pubDate>
    </item>
  </channel>
</rss>