Load JavaScript and CSS
Deep dive loading methods for resources about JavaScript and CSS
1. Load CSS ๐ฉโ
1. Including CSS
CSS ๋ฅผ ์ฒ์๋ถํฐ HTML ์ ๋ด์ฅํ๋ ๋ฐฉ์์ด๋ค. HTML ํ๊ทธ ๋ด๋ถ์ style
ํ๊ทธ๋ฅผ ์ฌ์ฉํด ์ง์ ๋ด์ฅํ๊ฑฐ๋, HTML ์๋ฆฌ๋จผํธ์ ์ธ๋ผ์ธ์ผ๋ก
์์ฑํ๋ฉด ๋ณ๋์ ์ธ๋ถ ํ์ผ ์์ด ์๋์ด ๊ฐ๋ฅํ๋ค. ๋ฐ๋ผ์ CSS ์คํ์ผ์ ์ป๊ธฐ ์ํ ๋ณ๋์ ๋คํธ์ํฌ ํต์ ์ด ํ์ํ์ง ์๋ค.
2. link
์ผ๋ฐ์ ์ผ๋ก head ํ๊ทธ ๋ด์ link
ํ๊ทธ๋ฅผ ์ฌ์ฉํด HTTP Request ๋ฅผ ๋ณด๋ด๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
<head>
<link rel="stylesheet" href="/css//main.css" />
</head>
๋ธ๋ผ์ฐ์ ์ ๋คํธ์ํฌ ํญ์ ๋ณด๋ฉด ๋ฆฌ์์ค ํ์ ์ด stylesheet ์์ ํ์ธํ ์ ์๋ค. ๋ฌผ๋ก , DOM ์ด ์ด๋ฏธ ๊ทธ๋ ค์ก๋๋ฐ CSS ๊ฐ ๋๋ฌด ๋ฆ๊ฒ ๋ก๋ฉ๋๋ค๋ฉด ํ๋ฉด์ ํํ์ ๋ฌธ์ ๊ฐ ์๊ธฐ์ง๋ง CSS ๋ JavaScript ์ ๋ฌ๋ฆฌ DOM ํ์ฑ๊ณผ ๊ด๋ จํด ์๋ ์์ฒด๋ ์์์ ์ํฅ์ ๋ฐ์ง ์๊ธฐ ๋๋ฌธ์ ์์ฒญ๋ง ์ ํ๋ฉด ํฌ๊ฒ ์ ๊ฒฝ ์ธ ๋ถ๋ถ์ด ์์ง๋ ์๋ค.
3. @import
@import url("fineprint.css") print;
@import url("bluish.css") speech;
@import "custom.css";
@import url("chrome://communicator/skin/");
@import "common.css" screen;
@import url("landscape.css") screen and (orientation: landscape);
CSS Declarations ์์๋ ์ค๋ช ํ์ง๋ง CSS ํ์ผ์ ์ข ๋ ํจ์จ์ ์ผ๋ก ๋ถ๋ฆฌ์ํฌ ์ ์๋ ์ฅ์ ์ ์์ง๋ง ์ง๋ ฌ๋ก ์์ฒญํ๋ ๋ฌธ์ ๊ฐ ์๋ค. ์ฒ์๋ถํฐ including ๋๋ ๋ฐฉ์์ด ์๋๊ณ ๋จผ์ ๋ฐ์์จ CSS ํ์ผ์ ํด์ํ๊ณ ์ถ๊ฐ๋ก ๋ถ๋ฌ์ค๊ธฐ ๋๋ฌธ์ ์๊ฐ์ด ์ง์ฐ๋๊ณ , CSS ์ฐ์ ์์๊ฐ ๋ค๋ฐ๋์ด ์๋ชป๋ ์คํ์ผ์ด ์ ์ฉ๋๊ฑฐ๋, DOM ์ด ์ด๋ฏธ ๋ก๋ฉ ๋์๋๋ฐ ์ ๋ ์คํ์ผ์ด ์ ์ฉ๋์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ฐ๋ผ์ CSS ๋ฅผ ์ฌ์ฉํ ๋๋ Link ๋ฐฉ์์ ์ฌ์ฉํด ๋ณ๋ ฌ๋ก ์์ฒญํ๊ฑฐ๋, SCSS ๋ฑ์ ์ฌ์ฉํด ์ ์ฒ๋ฆฌ ๊ณผ์ ์ ๊ฑฐ์ณ์ผํ๋ค.
4. Webpack & JavaScript
Webpack ์ ์๋ก ๋ค์์ง๋ง, ๋ค๋ฅธ ๋ฒ๋ค๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํด๋ ๋น์ทํ๋ค. ์ฐ์ ๋ฒ๋ค๋ง ์ต์ ์ ์ ํํ ์ค์ ํ๋ ๊ฒ์ด ์ฝ์ง๋ ์์ง๋ง, ๋ฒ๋ค๋ง์ ์ ์ฉํ๋ฉด, CSS ํ์ผ์ ์ต์ ํ ํ๋ ๊ฒ์ ๋ฌผ๋ก ์ด๊ณ , JavaScript ๋ฅผ ์ฌ์ฉํด CSS ๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๊ฒ ํด์ค๋ค.
import "../css/main.css"
๋ํ ์ด ๋ฐฉ์์ ์ฅ์ ์ SCSS ๋ฅผ ๋ถ๋ฌ์ค๋ ๊ฒ ์ญ์ ์์ฝ๊ฒ ์ฒ๋ฆฌํด์ค๋ค๋ ๊ฒ์ด๋ค.
import "../css/main.scss"
React CLI ๋๋ Vue CLI, Vite CLI ๋ฑ์ ์ฌ์ฉํด ์์ฑํ ์ฑ์์ ์์ ๊ฐ์ import ์ฌ์ฉ์ด ๊ฐ๋ฅํ ์ด์ ๋ค.
5. JavaScript with assert
import style from '../css/main.css' assert { type: 'css' };
document.adoptedStyleSheets = [style];
import
๋ช
๋ น์ ์ง๊ธ ์์ฒญํ๋ ์ด ๋ฆฌ์์ค๋ ์ฌ์ค CSS
๋ผ๋ ๊ฒ์ ๋ช
์ํจ์ผ๋ก์จ JavaScript ๊ฐ ์ด๊ฒ์ Stylesheet ๋ก ๋ค๋ฃฐ ์ ์๋๋ก
ํ๋ ์์ฑ์ ์ฌ์ฉํ ์ ์๋ค. ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด JavaScript ๊ฐ ์คํ๋๋ ์์ ์ ๋ฆฌ์์ค๋ฅผ ๋ถ๋ฌ์ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ ์์ฝ๊ฒ Dynamic import
๋ฅผ ์ ์ฉํ ์ ์๋ค๋ ์ฅ์ ์ ๊ฐ๋๋ค.
๋จ, ์ด ๋ฐฉ๋ฒ์ JavaScript ๊ฐ ๋ค๋ฅธ JavaScript Module ์ ๋ถ๋ฌ์ค๊ธฐ ์ํ ๋ช
๋ น์ด์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋์ ๋ชจ๋๋ก ๋ค๋ค์ผ ํ๋ฏ๋ก
<script type="module"></script>
๋ก ์ ์ธ์ด ํ์ํ๋ฉฐ, ์์ฒญ๋๋ CSS ๋ ๋ธ๋ผ์ฐ์ ์ ๋คํธ์ํฌ ํญ์
๋ฆฌ์์ค ํ์
์ด script ๋ก ํ์ธ๋๋ค.
๋ค๋ง ์ด ๋ฐฉ๋ฒ์ ํ์ฌ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ด๋ค. Browser compatibility ๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด assert
๋
ํฌ๋ก๋ฏธ์ ๊ธฐ๋ฐ์์๋ง ์๋ํ๊ณ , ํ์ด์ดํญ์ค๋ ์ฌํ๋ฆฌ์์๋
์๋ํ์ง ์๋๋ค. ํ์ค์ ์ผ๋ก VanillaJS ๋ก ๊ฐ๋ฐ์ ํ๋๋ผ๋ ํฌ๋ก์ค ๋ธ๋ผ์ฐ์ง ๋ฌธ์ ๋ก ์์ง์ ์ฌ์ฉํ ์ ์๋ค. ํ์ง๋ง ์ฐ๋ฆฌ์๊ฒ๋
Webpack, Vite ์ ๊ฐ์ ํ๋ฅญํ ๋์์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋์ง๋ ์๋๋ค.
6. Dynamic import
export const loadStyle = (href) => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = href;
document.head.appendChild(link);
};
CSS ์ญ์ Dynamic import ๋ฅผ ์ฌ์ฉํ ์ ์๋ค. UI ์ ๊ด๋ จ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ JavaScript ์ CSS ๋ฅผ ํจ๊ป ๋ฐฐํฌํ๋ ๋ฐ,
์ผ๋ฐ์ ์ผ๋ก Webpack, Vite ๋ฑ์ด ์์์ import
๋ฅผ ์ฒ๋ฆฌํด ์ฃผ๊ฒ ์ง๋ง, VanillaJS ๋ก ๊ฐ๋ฐํ๊ฑฐ๋ CDN ์์ ๊ฐ์ ธ์ฌ ๊ฒฝ์ฐ
์์ ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉํด head ํ๊ทธ์ ์คํ์ผ์ ๋ถ๋ฌ์ค๋๋ก ์์ฒญํ ์ ์๋ค. ์ ๋ฐฉ๋ฒ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ธฐ๋ณธ์ ์ธ
๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ JavaScript with assert ์ ๊ฐ์ด ํฌ๋ก์ค ๋ธ๋ผ์ฐ์ง ๋ฌธ์ ๊ฐ
๋ฐ์ํ์ง ์๋๋ค๋ ๊ฒ์ด ๊ฐ์ฅ ํฐ ์ฅ์ ์ด๋ค.
2. Load JavaScript ๐ฉโ
1. Including JavaScript
CSS ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฒ์๋ถํฐ HTML ์ ๋ด์ฅํ๋ ๋ฐฉ์์ด๋ค. HTML ํ๊ทธ ๋ด๋ถ์ script
ํ๊ทธ๋ฅผ ์ฌ์ฉํด ์ง์ ๋ด์ฅํ ์ ์๋ค.
<!DOCTYPE html>
<html lang="ko">
<head></head>
<body>
<button type="button" onclick="changeColor('#AEA')">Click!!</button>
<script>
function changeColor(color) {
event.target.style.backgroundColor = color;
}
</script>
</body>
</html>
์ด๋ head ๋ถ๋ถ์ script ๋ฅผ ์์น์์ผ๋ ์๊ด ์์ง๋ง, script ๋ด JavaScript ์ฝ๋์ DOM ์ด ํ์ํ ์ฝ๋๊ฐ ์์ ๊ฒฝ์ฐ ์์ง ๊ทธ๋ ค์ง์ง ์์ DOM ์ ์ฐพ์ง ๋ชปํด ์๋ฌ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ฃผ๋ก body ํ๊ทธ๊ฐ ๋ซํ ๋ค์ ๋๋ body ํ๊ทธ๊ฐ ๋ซํ๊ธฐ ์ง์ ์ script ๋ฅผ ๋ฃ๊ณค ํ๋ค.
๋จ, ์์ ๊ฐ์ด ์์ฑํ ๊ฒฝ์ฐ
onclick="changeColor('#AEA')"
์ ์ฌ์ฉ๋ ํจ์changeColor
๋ ๋ฐ๋์ DOM ์ ๋ด์ฅ๋์ด ์์ด์ผ ํ๋ค. script ๋ฅผ ์ธ๋ถ ๋ฆฌ์์ค๋ก ๋ถ๋ฆฌํด ๋ก๋ํ๋ script ๋ฐฉ์์ผ๋ก๋ ํจ์๋ฅผ ์ฐพ์ง ๋ชปํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ ์ฝ๋๊ฐ ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ a
ํ๊ทธ์ href
์์ฑ์ด๋ ๋ง์ ์๋ฆฌ๋จผํธ์์ ์ฌ์ฉ ๊ฐ๋ฅํ onclick
, onmouseover
, onkeyup
๊ณผ ๊ฐ์
์์ฑ์๋ JavaScript ์์ฑ๋ ํ
์คํธ๋ฅผ ๋ธ๋ผ์ฐ์ ๊ฐ JavaScript ์ฝ๋๋ก ์ธ์ํ๊ณ ์ํํ ์ ์๋ค๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด CSS ์ ๊ฐ์ด
์๋ฆฌ๋จผํธ์ ์ง์ ์ธ๋ผ์ธ์ผ๋ก ์์ฑํ๋ ๊ฒ ์ญ์ ๊ฐ๋ฅํ๋ค.
<button
type="button"
onclick="this.style.backgroundColor = '#AEA'"
>
Click!!
</button>
CSS ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฒ์๋ถํฐ DOM ์ ๋ด์ฅ๋์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ๋คํธ์ํฌ ํต์ ์ด ํ์ํ์ง ์๋ค.
CSS ๋ฅผ ์ฒ์๋ถํฐ HTML ์ ๋ด์ฅํ๋ ๋ฐฉ์์ด๋ค. HTML ํ๊ทธ ๋ด๋ถ์ style
ํ๊ทธ๋ฅผ ์ฌ์ฉํด ์ง์ ๋ด์ฅํ๊ฑฐ๋, HTML ์๋ฆฌ๋จผํธ์ ์ธ๋ผ์ธ์ผ๋ก
์์ฑํ๋ฉด ๋ณ๋์ ์ธ๋ถ ํ์ผ ์์ด ์๋์ด ๊ฐ๋ฅํ๋ค. ๋ฐ๋ผ์ CSS ์คํ์ผ์ ์ป๊ธฐ ์ํ ๋ณ๋์ ๋คํธ์ํฌ ํต์ ์ด ํ์ํ์ง ์๋ค.
2. script
์ผ๋ฐ์ ์ผ๋ก head ํ๊ทธ ๋ด์ script
ํ๊ทธ์ src
์์ฑ์ ์ฌ์ฉํด HTTP Request ๋ฅผ ๋ณด๋ด๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
<head>
<script type="text/javascript" src="js/main.js"></script>
</head>
๋ธ๋ผ์ฐ์ ์ ๋คํธ์ํฌ ํญ์ ๋ณด๋ฉด ๋ฆฌ์์ค ํ์ ์ด script ์์ ํ์ธํ ์ ์๋ค.
Including JavaScript ์์ ํ์ธํ๋ฏ์ด, DOM ์ด ๋จผ์ ๊ทธ๋ ค์ ธ์ผ ํ๋ ์ฝ๋๊ฐ ์กด์ฌํ๋ ๋ฌธ์ ๋ ์ฌ์ ํ ์ ํจํ๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ MutationObserver ๋ฅผ ์ฌ์ฉํ๋ ์ผ๋ฐ์ ์ด์ง ์์ ๋ฐฉ๋ฒ์ ์ ์ธํ๋ฉด 3๊ฐ์ง๋ก ์ ๋ฆฌํ ์ ์๋ค.
1 ) window.onload
<button type="button" id="foo">Click!!</button>
window.onload = () => {
document
.getElementById('foo')
.addEventListener('click', () => changeColor('#AEA'));
};
2 ) addEventListener
window.onload ๋ HTML ๋ฌธ์์ ํ ๋ฒ๋ง ์ฌ์ฉ ๊ฐ๋ฅํด ์ค๋ณต์ ๋ง์ง๋ง์ ์ ์ธ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ด์ ์ ํธ๋ค๋ฌ๋ฅผ ๋ชจ๋ ๋ฎ์ด์ด๋ค. ๋ฌผ๋ก ,
์ฝ๋๋ฅผ ์ ์์ฑํ๋ฉด ๋์ง๋ง ๋จ์ผ ๋ฌธ์๊ฐ ์๋ ๊ฒฝ์ฐ ์์ํ๊ธฐ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธธ ์ ์๋ค.
์ฌ์ ํ ๋ง์ ์๋ฒ๋ SSR ์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, Next.JS ์ ๊ฐ์ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ JSP, Thymeleaf, EJS, Pug(=Jade) ์
๊ฐ์ ํ
ํ๋ฆฟ ์์ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์๋ํ์ง ์์ ์ค๋ณต์ผ๋ก ํน์ script ์ onload ์ฝ๋๊ฐ ๋ฌด์๋๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
๋ฐ๋ผ์ window ์ load
์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ๊ฐ์ ์ด๋ฒคํธ๋ฅผ ๋ฑ๋กํ ์ ์์ด ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
window.addEventListener('load', () => {
document
.getElementById('foo')
.addEventListener('click', () => changeColor('#AEA'));
});
์ค๋ณต ๋ฑ๋ก์ ๋ํ ๋ฌธ์ ๋ ํด๊ฒฐํ ์ ์์ง๋ง window ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ ๋์ผํ๊ธฐ ๋๋ฌธ์ DOM ์ด ์ด๋ฏธ ์กด์ฌํจ์๋ ๋ค๋ฅธ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฏ๋ก
๋ถํ์ํ ์ง์ฐ์ด ๋ฐ์ํ ์ ์๋ค. load
๋์ DOMContentLoaded
์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ๋ฉด, โ HTML ๋ฌธ์์ ํ์ฑ์ด ์๋ฃ๋๊ณ , โก ๋ชจ๋
์ง์ฐ๋ ์คํฌ๋ฆฝํธ(<script defer src="...">
์ <script type="module">
)๊ฐ ๋ค์ด๋ก๋๋๊ณ ์คํ๋ ๋ ํธ๋ฆฌ๋๋ฏ๋ก ๋ชจ๋ ๋ฌธ์ ๋ฅผ
ํด๊ฒฐํ ์ ์๋ค.
window.addEventListener('DOMContentLoaded', () => {
document
.getElementById('foo')
.addEventListener('click', () => changeColor('#AEA'));
});
์ข ๋ ์์ธํ ์ค๋ช ํ๋ฉด, ์๋์ ์ค๋ช ํ
defer
์์ฑ์ดDOMContentLoaded
๊ฐ ํธ๋ฆฌ๊ฑฐ ๋๋ ๊ฒ์ ๋ง๋๋ค. ๊ทธ๋ฆฌ๊ณJavaScript Module
์ ๊ธฐ๋ณธ์ ์ผ๋กdefer
์ฒ๋ฆฌ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ โ HTML ๋ฌธ์์ ํ์ฑ์ด ์๋ฃ๋๊ณ , โก ๋ชจ๋ ์ง์ฐ๋ ์คํฌ๋ฆฝํธ๊ฐ ๋ค์ด๋ก๋๋๊ณ ์คํ๋๋ ๊ฒ์ด๋ค.
3 ) defer
ํ์ง๋ง, DOMContentLoaded
์ญ์ ์ฝ๋๋ฅผ ์์ฑํ ๋ ํญ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ๋ฑ๋กํด์ผํ๋ฏ๋ก ์ฝ๋ ์์ฑ์ ํ๋ฆ์ด๋ ๊ฐ๋
์ฑ์ ์ํฅ์ ์ค๋ค.
๋ํ, ํด๋น ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ ์ต์ด ๋ก๋ฉ ํ ๋์ด์ ํธ๋ฆฌ๊ฑฐ ๋ ์ผ์ ์์ง๋ง, ์ข ๋ ์ต์ ํ๋ฅผ ํ๊ณ ์ ํ๋ค๋ฉด ์ด๋ฒคํธ๋ฅผ ์ ๊ฑฐํ๋ ์์
๊น์ง ํฌํจ๋์ด์ผ
ํ๋ค. ๊ฒฐ๋ก ์ ์ผ๋ก, ์ฝ๋๋ฅผ ๋ถ๋ฆฌํด ๊ด๋ฆฌ ํ ์ ์๋ ์ฅ์ ์ ์กด์ฌํ์ง๋ง, ์ต์ ํ์ ์ถ๊ฐ์ ์ธ ๋
ธ๋ ฅ ํ์, ์ฝ๋๋ ์ฆ๊ฐ, ๊ฐ๋
์ฑ ํ๋ฝ ๋ฑ์ ๋ฌธ์ ๊ฐ ์์ด
body ํ๊ทธ๊ฐ ๋ซํ ๋ค์ ๋๋ body ํ๊ทธ๊ฐ ๋ซํ๊ธฐ ์ง์ ์ script ๋ฅผ ๋ฃ๋ ๊ฒ์ด ์คํ๋ ค ๊ฐ์ฅ ์ต์ ํ๋ ๊ฐ์ฅ ์ข์ ์ฝ๋๊ฐ ๋๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด script
ํ๊ทธ์ defer
๋ผ๋ ์์ฑ์ด ์ถ๊ฐ๋์๋ค. ๋จ์ง defer
์์ฑ์ ๋ช
์ํ๋ ๊ฒ ๋ง์ผ๋ก ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ
HTTP Request ๋ฅผ ๋ณด๋ด ์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ์ง๋ง, HTML ๋ฌธ์์ ํ์ฑ ์๋ฃ ๋ฐ ๋ชจ๋ ์ง์ฐ๋ ์คํฌ๋ฆฝํธ๊ฐ
๋ค์ด๋ก๋๋๊ณ execute ํ๋ค.
default | async | defer | module | module async | |
---|---|---|---|---|---|
fetch ๋ก ์ธํ ํ์ฑ ์ค๋จ | O | X | X | X | X |
execute ๋ก ์ธํ ํ์ฑ ์ค๋จ | O | O | X | X | O |
script ์์ ๋ณด์ฅ | O | X | O | O | X |
modulation | X | X | X | O | O |
๋ฌผ๋ก , ๋ค๋ฅธ ์คํฌ๋ฆฝํธ๋ DOM ์ ์ํฅ์ ๋ฐ์ง ์๋ ๊ฒฝ์ฐ async ๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ ์ผ๋ฐ์ ์ผ๋ก, fetch, execute ๋ก ์ธํ HTML ์ ํ์ฑ์ ์ค๋จ๋์ง ์๋ ๊ฒ์ด ์ข๊ณ , ์คํฌ๋ฆฝํธ์ ์์๋ ํ์์ ๋ณด์ฅ๋์ด์ผํ๋ฉฐ, ๋ชจ๋ ํ์ ์ผ๋ก ๋ค๋ฃจ๋ ๊ฒ์ด ์ข๋ค.
๋ฐ๋ผ์ ์ค๋๋ ๊ฐ์ฅ ์ ํฉํ ๋ฐฉ์์ defer ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, module ํ์ ์ ์ฌ์ฉํ๊ณ ํ์์ async ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข๋ค๊ณ ํ ์ ์๋ค.
module
๋ก ์ค์ ํ๊ฒ๋๋ฉด, ์ด๊ฒ์ script ๊ฐ JavaScript Module ๋ก ์ฒ๋ฆฌํ๋๋ก ๊ฐ์ฃผ๋๋ฉฐ, ์ฝ๋์ ์คํ์ด deferred ๋๋ค. ๋ฐ๋ผ์ ๋์ด์charset
๊ณผdefer
์์ฑ์ ์๋ฏธ๊ฐ ์์ด ์์ฑํ ํ์๊ฐ ์์ผ๋ฉฐ, ํด๋์ํ ๋ฐฉ์์text/javascript
์ ๋ฌ๋ฆฌ Cross-Origin Fetching ์ CORS ํ๋กํ ์ฝ์ ์ฌ์ฉํด์ผ ํ๋ค.
3. import
๋ชจ๋๋ก ๋ค๋ฃฐ ๊ฒฝ์ฐ ์ง์ ํธ์คํ
์ค์ธ ์๋ฒ์ ์คํฌ๋ฆฝํธ ๋ฟ ์๋๋ผ ์ผ๋ถ CDN ์ ๊ฒฝ์ฐ ๋ฆฌ์์ค๋ฅผ ๋ชจ๋๋ก ์ ๊ณตํด import
๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋ค.
import Swiper from "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.mjs"
const swiper = new Swiper(...)
๋จ, ์ง์ ํธ์คํ
ํ๋ ์๋ฒ์์ ์ ๊ณตํ๋ ์คํฌ๋ฆฝํธ๊ฐ ์๋ ๊ฒฝ์ฐ, ์์ ๊ฐ์ import
๋ฅผ ์ฌ์ฉํ ์์ฒญ์ด ๋ชจ๋ CDN ์ ์ ์ฉ ๊ฐ๋ฅํ ๊ฒ์ ์๋๋ค.
์ฐธ๊ณ ๋ก ์์ ๊ฐ์ด import
๋ก ์์ฒญํ ๋ชจ๋ ์คํฌ๋ฆฝํธ๊น์ง ๋ค์ด๋ก๋๊ฐ ์๋ฃ๋๊ธฐ ์ ๊น์ง ๋ชจ๋ ๋ชจ๋ ์คํฌ๋ฆฝํธ ์ฝ๋์ ์คํ์ด ์ง์ฐ๋๋ค. ๋ฐ๋ผ์
ํด๋น ์คํฌ๋ฆฝํธ ๋ด import
๋ณด๋ค ์์ ์์ฑ๋ ์ฝ๋๋ผ ํ๋๋ผ๋ ๋ชจ๋ ์คํฌ๋ฆฝํธ์ ์ฝ๋๊ฐ ๋ค์ด๋ก๋ ์๋ฃ๋๊ธฐ ์ ๊น์ง execute ๋์ง ์์
์ฝ๋์ ์คํ์ด ์ง์ฐ๋๋ฏ๋ก ๋ณ๋์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ์์ด const swiper = new Swiper(...)
์ ๊ฐ์ด ๋๊ธฐ์ ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
4. Webpack & JavaScript
์์ฆ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ๋๋ถ๋ถ ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค. ๋ชจ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด import
๋ก ํ์ํ ๋ชจ๋ ์ ์ฒด ๋๋ ๋ฉ์๋๋ง ๊ฐ์ ธ์ค๊ณ , Webpack ์ด
Tree Shaking ๋ฑ์ ํตํด ์ต์ ํ ํ๋ค.
// Import Swiper React components
import { Swiper, SwiperSlide } from 'swiper/react';
// Import Swiper styles
import 'swiper/css';
5. Dynamic import
์์ฆ ํ๋ก ํธ์๋๋ ์ฝ๋๋ฅผ chunk ๋จ์๋ก ๋๋๊ณ dynamic import ๋ฅผ ์ฌ์ฉํด ํ ๋ฒ์ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ์ง ์๋๋ก ํด ํ์ด์ง์ ์ด๊ธฐ
๋ก๋ฉ ์๋๋ฅผ ๋น ๋ฅด๊ฒ ๊ฐ์ ํ๊ณ , ํ์ํ ์์ ์ ํ์ํ ๋ฆฌ์์ค๋ง ์์ฒญํ๋๋ก ์ต์ ํ๋ฅผ ํ๊ณ ์๋ค. import
๋ ์ฝ๋ ์ค๊ฐ์์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ฉฐ, ๋ค์๊ณผ
๊ฐ์ด ํจ์๋ก ๋ง๋ค๋ฉด ์ฝ๊ฒ dynamic import ๊ฐ ๊ฐ๋ฅํ๋ค.
export const loadScript = async (src) => import(src);
const Swiper = await loadScript(
'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.mjs'
);
const swiper = new Swiper(...)
ํ์ง๋ง Webpack ์ ์ฌ์ฉํ์ง ์๊ฑฐ๋ CDN ๊ฐ์ ๊ณณ์ ์์ฒญํด์ผ ํ ๊ฒฝ์ฐ, import
์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ ํ๊ฒฝ๋ ๊ณ ๋ ค์ ํํ๋ค.
CSS Dynamic import ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ๋จํ๊ฒ HTML ์ script ๋ฅผ ์ถ๊ฐํ๋ ํจ์๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
export const loadScript = (src) => {
const script = document.createElement('script');
script.src = src;
script.type = 'module';
script.async = false;
document.head.appendChild(script);
};
๋จ, CSS ์ ๋ฌ๋ฆฌ JavaScript ๋ ์คํฌ๋ฆฝํธ์ ๋ค์ด๋ก๋๊ฐ ์๋ฃ๋ ์์ ์ ํ์ธํด์ผ ํ ํ์๊ฐ ์๋ค.
๋ฐ๋ผ์, ๋ค์ด๋ก๋ ์๋ฃ ์ฌ๋ถ๋ฅผ ํ์ธ ํ ๋น์ฆ๋์ค ๋ก์ง์ ์คํํ๋๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ํ์๊ฐ ์๋๋ฐ, Promise
์ Event Listener
๋ฅผ ์ ์ ํ
์ฌ์ฉํด ์ ํจ์๋ฅผ ๊ฐ์ ์ํฌ ์ ์๋ค.
๋ค์์ ์์ ์ ํ ์ด ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์ ์ธ๋ถ ์คํฌ๋ฆฝํธ๋ฅผ ํน์ ํ์ด์ง ๋ฐฉ๋ฌธ์ Dynamic import ๋ฅผ ์ ์ฉํ๋, ์คํฌ๋ฆฝํธ ์ค๋ณต ์์ฒญ์ ๋ฐฉ์งํ๊ณ , ์คํฌ๋ฆฝํธ์ ๋ก๋ ์๋ฃ ์ฌ๋ถ๋ฅผ ํ์ธ ํ ๋ค์ ์ฝ๋๋ฅผ ์๋์ํค๊ธฐ ์ํด ๋ง๋ค์๋ ์ฝ๋๋ฅผ ์ผ๋ถ๋ค.
export const loadScript = ({ src, mode = "none" }) =>
new Promise((resolve, reject) => {
try {
const previous = document.querySelector(`script[src="${src}"]`);
if (previous === null) {
const script = document.createElement("script");
script.src = src;
setScriptMode(mode)(script);
script.addEventListener("load", () =>
resolve({
load: true,
removeScript: () => document.head.removeChild(script),
})
);
script.addEventListener("error", () =>
reject({
load: false,
message: `Fail to load external script from ${src}`,
})
);
document.head.appendChild(script);
} else {
resolve({
load: true,
removeScript: () => document.head.removeChild(previous),
});
}
} catch (e) {
throw new Error(`Fail to load external script`);
}
});
const setScriptMode = (mode) => {
switch (mode) {
case "async":
return (script) => (script.async = true);
case "defer":
return (script) => (script.defer = true);
default:
return () => undefined;
}
};
const kakaoMapApiBaseUrl =
"//dapi.kakao.com/v2/maps/sdk.js?autoload=false&appkey=";
const kakaoMapApiScriptSrc = kakaoMapApiBaseUrl + kakaoMapApiKey;
const [loadKakaoMapScript, setLoadKakaoMapScript] = useState(null);
useEffect(() => {
let removeScript;
const loadKakaoMapApi = async () => {
try {
const result = await loadScript({
src: kakaoMapApiScriptSrc,
});
setLoadKakaoMapScript(result.load);
if (result.load) {
removeScript = result.removeScript;
}
} catch (e) {
console.error(`You cannot use kakao map, error: ${e}`);
}
};
loadKakaoMapApi();
// return () => removeScript && removeScript();
}, []);
removeScript
๋ HTML ๋ด์ ํด๋น ์คํฌ๋ฆฝํธ๋ฅผ ์ ๊ฑฐํ๊ณ ์ถ์ ๋๋ง ์ฌ์ฉํ๋ค. ์ ๊ฑฐ์ ๋ค์ ํ์ํ๋ฉด ๋ค์ ๋ก๋ฉํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก
์ฌ์ฉํ ์ผ์ ๋ง์ง ์์ ๊ฒ์ด๋ค.
Reference
- โimport.โ MDN Web Docs. Feb. 20, 2024, MDN - import.