๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ

2000๋…„๋Œ€ ์ดˆ๋ฐ˜์˜ ์›นํŽ˜์ด์ง€๋Š” ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ์ƒˆ๋กœ์šด html์„ ์š”์ฒญํ•ด์„œ ํ™”๋ฉด์„ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” DOM์„ ์กฐ์ž‘ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์—ญํ• ๋งŒ ํ–ˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— html์˜ scriptํƒœ๊ทธ์— ๋„ฃ๋Š” ๊ฒƒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ–ˆ๋‹ค. ajax๊ฐ€ ์œ ํ–‰ํ–ˆ์„ ๋•Œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋น„์ค‘์ด ์กฐ๊ธˆ ๋” ์ปค์กŒ์ง€๋งŒ ๊ทธ๋ž˜ ๋ด์•ผ ํŽ˜์ด์ง€๋‹น ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ๋ช‡ ๊ฐœ๋ฉด ์ถฉ๋ถ„ํ–ˆ๋‹ค. SPA(single page app)๋Š” ํ•˜๋‚˜์˜ html์— ์ˆ˜์‹ญ, ์ˆ˜๋ฐฑ ๊ฐœ์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ์ด์ƒ ๊ธฐ์กด ๋ฐฉ์‹์ด ํ†ตํ• ๋ฆฌ ์—†์—ˆ๋‹ค.

 

<html>
<head>
<link rel="stylesheet" type="text/css" href="javascript_file_1.js">
<link rel="stylesheet" type="text/css" href="javascript_file_2.js">
...
<link rel="stylesheet" type="text/css" href="javascript_file_999.js">
</head>
...
</html>

์œ„์˜ ๋ฐฉ์‹์œผ๋กœ๋Š” ๊ณ„์† ๋Š˜์–ด๋‚˜๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ํž˜๋“ค๋‹ค. ๋˜ํ•œ ์„ ์–ธ๋˜๋Š” ์ˆœ์„œ๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•˜๊ณ , ๊ธฐ์กด์— ์ƒ์„ฑ๋œ ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ๋ฎ์–ด์“ฐ๋Š” ์œ„ํ—˜๋„ ์กด์žฌํ•œ๋‹ค.

๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด ํ•„์š”ํ•˜๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํƒœ์ƒ์ด ๋ธŒ๋ผ์šฐ์ €์— ์ข…์†์ ์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž์ฒด์ ์ธ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด ์—†์—ˆ๋‹ค. ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์€ C++์ด๋‚˜ ์ž๋ฐ”์—์„œ include๋‚˜ import ํ‚ค์›Œ๋“œ๋ฅผ ๋– ์˜ฌ๋ฆฌ๋ฉด ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ตœ์‹  ํ‘œ์ค€์ธ ES6๋ถ€ํ„ฐ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์ด ํฌํ•จ๋์ง€๋งŒ ์•„์ง ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ง€์›ํ•˜์ง€ ์•Š๊ณ  ์žˆ๋‹ค. ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ง€์›ํ•œ๋‹ค ํ•˜๋”๋ผ๋„ ๋‹ค์ˆ˜์˜ ์œ ๋ช…ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ES6 ํ‘œ์ค€์œผ๋กœ ์ž‘์„ฑ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒŒ ํฐ ๊ฑธ๋ฆผ๋Œ์ด๋‹ค.

๋ธŒ๋ผ์šฐ์ €์— ์–ฝ๋งค์ด์ง€ ๋ง์ž.

์˜ˆ์ „๋ถ€ํ„ฐ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ธŒ๋ผ์šฐ์ € ๋ฐ–์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ ค๋Š” ๋…ธ๋ ฅ์ด ์žˆ์—ˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ํ‘œ์ค€ ์œ„์›ํšŒ๋Š” CommonJS, AMD๊ฐ€ ์žˆ๋‹ค. ์ด๋“ค์ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ฒ”์šฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ผ์€ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์„ ์ •์˜ํ•˜๋Š” ์ผ์ด์—ˆ๋‹ค. ๊ทธ๋ฆฌํ•˜์—ฌ nodejs ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋“ฑ์žฅํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์„œ๋ฒ„์—์„œ ๋Œ์•„๊ฐ€๋Š” ์„ธ์ƒ์ด ๋˜์—ˆ๋‹ค.

SPA๊ฐœ๋ฐœ์€ webpack๊ณผ ํ•จ๊ป˜

webpack์€ CommonJS์™€ AMD ์ŠคํŽ™ ๋ชจ๋‘๋ฅผ ์ง€์›ํ•œ๋‹ค. webpack์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ(์›ํ•œ๋‹ค๋ฉด ์—ฌ๋Ÿฌ ๊ฐœ)๋กœ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌํ•˜์—ฌ SPA๊ฐœ๋ฐœ ์‹œ html์—๋Š” ์ปดํŒŒ์ผ๋œ ํ•˜๋‚˜์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ๋งŒ ํฌํ•จ์‹œํ‚ค๋ฉด ๋œ๋‹ค. ๊ณ ๋งˆ์šด ์ ์€ ES6 ํ‘œ์ค€์œผ๋กœ ์ž‘์„ฑ๋˜์ง€ ์•Š์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์•Œ์•„์„œ ์ž˜ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค๋Š” ์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ npm์œผ๋กœ ์„ค์น˜ ํ›„ ํ•„์š”ํ•œ ๋ถ€๋ถ„์— import๋งŒ ํ•˜๋ฉด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

webpack์˜ ์žฅ์  1: ํŒŒ์ผ ๋ถ„ํ•  ๊ธฐ๋Šฅ

์ˆ˜๋ฐฑ ๊ฐœ์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฑด ์ข‹์€ ์ƒ๊ฐ์ด ์•„๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ฒซ ํŽ˜์ด์ง€๋ฅผ ๋ณด๊ธฐ ์œ„ํ•ด ๋ช‡ ์ดˆ๋ฅผ ๊ธฐ๋‹ค๋ ค์•ผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. webpack์—๋Š” ๋‹ค์–‘ํ•œ ํŒŒ์ผ ๋ถ„ํ•  ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค.

  • vendor์ฝ”๋“œ๋งŒ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. vendor์ฝ”๋“œ๋Š” ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์— ์บ์‹ฑ ํ›„ ์˜ค๋žซ๋™์•ˆ ์žฌ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•๋งŒ ์‚ฌ์šฉํ•ด๋„ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ƒ๋‹น ๋ถ€๋ถ„ ๋Œ์–ด์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฒซ ๋ฐฉ๋ฌธ์ž์˜ ๊ฒฝ์šฐ์—๋Š” ์˜๋ฏธ๊ฐ€ ์—†๋‹ค.
  • require.ensure ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ ํŒŒ์ผ ๋ถ„ํ• ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ require.ensure ๊ตฌ๋ฌธ์„ ์‹คํ–‰ํ•  ๋•Œ ํ•„์š”ํ•œ ํŒŒ์ผ์„ on-demand๋กœ ๋‹ค์šด๋กœ๋“œํ•œ๋‹ค(webpack์ด ์•Œ์•„์„œ ํ•ด์ค€๋‹ค-_-b). ๋”ฐ๋ผ์„œ ์ฒซ ๋ฐฉ๋ฌธ์ž์˜ ๊ฒฝ์šฐ์—๋„ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜์‘ ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค. ์ฒซ ํŽ˜์ด์ง€ ๋กœ๋”ฉ์€ ๋น ๋ฅด์ง€๋งŒ ์ดํ›„ ํ•„์š”ํ•œ ๋ถ€๋ถ„์˜ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถ„ํ• ๋œ ์ฝ”๋“œ์˜ ํฌ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ํฌ์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. react์—์„œ๋Š” route๋ณ„๋กœ ํŒŒ์ผ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ด ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค.

webpack์—์„œ๋Š” ์ปดํŒŒ์ผ๋œ ํŒŒ์ผ์˜ ์ด๋ฆ„์— hash๊ฐ’์„ ๋ถ™์ด๋Š” ๊ธฐ๋Šฅ์ด ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค. ํ•ด๋‹น ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์—๋งŒ hash๊ฐ’์ด ๋ณ€๊ฒฝ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ ํŒŒ์ผ์€ ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์— ์บ์‹ฑ๋œ ํŒŒ์ผ์ด ์žฌํ™œ์šฉ๋œ๋‹ค.

webpack์˜ ์žฅ์  2: ๋‹ค์–‘ํ•œ loader๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ loader๋Š” ํŒŒ์ผ์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ถœ๋ ฅํ•ด์ค€๋‹ค. loader๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด webpack์ด ์ปดํŒŒ์ผ์„ ํ•˜๊ธฐ ์ „์— ์›ํ•˜๋Š” ํŒŒ์ผ์— ๋Œ€ํ•ด์„œ ์ „์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. jsx๋ผ๋Š” react ๊ณ ์œ ์˜ ๋ฌธ๋ฒ•์œผ๋กœ ์ž‘์„ฑ๋œ ํŒŒ์ผ์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ๋งŽ์ด ์“ฐ์ธ๋‹ค. ๊ทธ ์™ธ์—๋„ babel-loader๋ฅผ ์ด์šฉํ•ด์„œ ES6, ES7๊ณผ ๊ฐ™์€ ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์—ฌ๋Ÿฌ ๊ฐœ์˜ loader๋ฅผ ์ฒด์ธ ํ˜•์‹์œผ๋กœ ๋ฌถ์„ ์ˆ˜๋„ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด babel-loader์™€ eslint-loader๋ฅผ ๋ฌถ์–ด์„œ ๋จผ์ € eslint๋กœ ์ •์  ๋ถ„์„์„ ํ•˜๊ณ  ์„ฑ๊ณตํ•˜๋ฉด babel-loader๊ฐ€ jsxํŒŒ์ผ์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋Š” style-loader์™€ css-loader๋ฅผ ๊ฐ™์ด ์“ฐ๋Š” ๊ฒฝ์šฐ์ด๋‹ค. css๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์–ด๋ ค์šด ์  ์ค‘์˜ ํ•˜๋‚˜๊ฐ€ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. css-loader๋Š” import ํ•˜๋Š” ๋ชจ๋“ˆ์˜ id๊ฐ’์„ ํด๋ž˜์Šค ์ด๋ฆ„์— ์ž๋™์œผ๋กœ ๋ถ™์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹จ์ˆœํžˆ ํด๋ž˜์Šค ์ด๋ฆ„์„ ‘button’์œผ๋กœ ์ •์˜ํ•˜๋”๋ผ๋„ ์ด๋ฆ„์ด ๊ฒน์น ๊นŒ ๋ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค. style-loader๋Š” css-loader๊ฐ€ ์ถœ๋ ฅํ•˜๋Š” css์ •๋ณด๋ฅผ ๋ฐ›์•„์„œ styleํƒœ๊ทธ๋กœ ๋งŒ๋“ค๊ณ  ๊ทธ๊ฒƒ์„ DOM์— ๋ถ™์—ฌ์ค€๋‹ค.

// a.css
:local .button {
background-color: red;
}
// b.css
:local .button {
background-color: blue;
}
// app1.jsx
import styles from 'a.css'
...
<button className=styles.button>click me</button>
...
// app2.jsx
import styles from 'b.css'
...
<button className=styles.button>click me</button>
...

app1์˜ ๋ฒ„ํŠผ์€ ๋นจ๊ฐ„์ƒ‰์ด ๋˜๊ณ , app2์˜ ๋ฒ„ํŠผ์€ ํŒŒ๋ž€์ƒ‰์ด ๋œ๋‹ค.

 

์ถœ์ฒ˜: https://ljs0705.medium.com/spa-single-page-app-%EC%97%90%EC%84%9C-webpack%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-ce7d3f82fe9

๋ฐ˜์‘ํ˜•