ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ์น ์ปดํฌ๋ํธ ์ฑ๋ฅ ์ต์ ํ ์ข ํฉ ๊ฐ์ด๋. ๊ธ๋ก๋ฒ ์น ๊ฐ๋ฐ์ ์ํ ์ ๋ต, ๊ธฐ์ , ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ค๋ฃน๋๋ค.
์น ์ปดํฌ๋ํธ ์ฑ๋ฅ ํ๋ ์์ํฌ: ์ต์ ํ ์ ๋ต ๊ตฌํ ๊ฐ์ด๋
์น ์ปดํฌ๋ํธ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด UI ์์๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋๋ค. ๊ธฐ๋ฅ๊ณผ ์คํ์ผ์ ์บก์ํํ์ฌ ๋ณต์กํ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ฐ ๋์์ธ ์์คํ ์ ์ด์์ ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ๊ธฐ์ ์ด ๊ทธ๋ ๋ฏ, ์น ์ปดํฌ๋ํธ๋ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌํํ์ง ์์ผ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด ๊ฐ์ด๋๋ ๋ค์ํ ํ๋ ์์ํฌ์ ์ ๋ต์ ์ฌ์ฉํ์ฌ ์น ์ปดํฌ๋ํธ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ํฌ๊ด์ ์ธ ๊ฐ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
์น ์ปดํฌ๋ํธ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์ ์ดํดํ๊ธฐ
์ต์ ํ ๊ธฐ์ ์ ์ดํด๋ณด๊ธฐ ์ ์, ์น ์ปดํฌ๋ํธ์ ๊ด๋ จ๋ ์ ์ฌ์ ์ธ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ด๋ ์ฌ๋ฌ ์์ญ์์ ๋ฐ์ํ ์ ์์ต๋๋ค:
- ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ: ๋๊ท๋ชจ ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ ํฌ๊ฒ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค.
- ๋ ๋๋ง ์ฑ๋ฅ: ๋ณต์กํ ์ปดํฌ๋ํธ ๊ตฌ์กฐ์ ๋น๋ฒํ ์ ๋ฐ์ดํธ๋ ๋ธ๋ผ์ฐ์ ์ ๋ ๋๋ง ์์ง์ ๋ถ๋ด์ ์ค ์ ์์ต๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์๋น: ๊ณผ๋ํ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ฑ๋ฅ ์ ํ ๋ฐ ๋ธ๋ผ์ฐ์ ์ถฉ๋๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
- ์ด๋ฒคํธ ์ฒ๋ฆฌ: ๋นํจ์จ์ ์ธ ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ํธ๋ค๋ฌ๋ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ๋๋ฆฌ๊ฒ ํ ์ ์์ต๋๋ค.
- ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ: ๋นํจ์จ์ ์ธ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๋ฉ์ปค๋์ฆ์ ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ์ ๋ฐํ ์ ์์ต๋๋ค.
์ฌ๋ฐ๋ฅธ ํ๋ ์์ํฌ ์ ํํ๊ธฐ
๋ช๋ช ํ๋ ์์ํฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์น ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ถํ๊ณ ์ต์ ํํ๋ ๋ฐ ๋์์ ์ค ์ ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ๊ฒ์ ์ ํํ๋ ๊ฒ์ ํน์ ์๊ตฌ์ฌํญ๊ณผ ํ๋ก์ ํธ ๋ฒ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ๋ค์์ ๋ช ๊ฐ์ง ์ธ๊ธฐ ์๋ ์ต์ ์ ๋๋ค:
- LitElement: ๊ตฌ๊ธ์ LitElement(ํ์ฌ Lit)๋ ๋น ๋ฅด๊ณ ๊ฐ๋ฒผ์ด ์น ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๊ฒฝ๋ ๊ธฐ๋ณธ ํด๋์ค์ ๋๋ค. ๋ฐ์ํ ์์ฑ, ํจ์จ์ ์ธ ๋ ๋๋ง, ์ฌ์ด ํ ํ๋ฆฟ ๊ตฌ๋ฌธ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์์ ํฌ๊ธฐ ๋๋ถ์ ์ฑ๋ฅ์ ๋ฏผ๊ฐํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์์ ์ ๋๋ค.
- Stencil: Ionic์์ ๊ฐ๋ฐํ Stencil์ ์น ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋ ์ปดํ์ผ๋ฌ์ ๋๋ค. ์ฑ๋ฅ์ ์ค์ ์ ๋๋ฉฐ TypeScript์ JSX๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. Stencil์ ๋ํ ์ง์ฐ ๋ก๋ฉ ๋ฐ ์ฌ์ ๋ ๋๋ง๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค.
- FAST: ๋ง์ดํฌ๋ก์ํํธ์ FAST(์ด์ FAST Element)๋ ์๋, ์ฌ์ฉ ์ฉ์ด์ฑ, ์ํธ ์ด์ฉ์ฑ์ ์ค์ ์ ๋ ์น ์ปดํฌ๋ํธ ๊ธฐ๋ฐ UI ํ๋ ์์ํฌ ๋ฐ ๊ธฐ์ ๋ชจ์์ ๋๋ค. ์ปดํฌ๋ํธ์ ํ ๋ง ๋ฐ ์คํ์ผ๋ง์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค.
- Polymer: Polymer๋ ์ด๊ธฐ์ ์น ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค ํ๋์์ง๋ง, ๊ฐ์ ๋ ์ฑ๋ฅ๊ณผ ๋ ์์ ํฌ๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก ์๋ก์ด ํ๋ก์ ํธ์๋ ํ์ ์ ํ์ธ Lit์ด ๊ถ์ฅ๋ฉ๋๋ค.
- Vanilla JavaScript: ํ๋ ์์ํฌ ์์ด ์์ JavaScript๋ฅผ ์ฌ์ฉํ์ฌ ์น ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์๋ ์์ต๋๋ค. ์ด๋ ๊ตฌํ์ ๋ํ ์์ ํ ์ ์ด๋ฅผ ์ ๊ณตํ์ง๋ง ๋ ๋ง์ ์์์ ์ด ํ์ํฉ๋๋ค.
์์ : LitElement
๋ค์์ LitElement๋ก ๊ตฌ์ถ๋ ๊ฐ๋จํ ์น ์ปดํฌ๋ํธ ์์ ์ ๋๋ค:
import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';
@customElement('my-element')
export class MyElement extends LitElement {
static styles = css`
p {
color: blue;
}
`;
@property({ type: String })
name = 'World';
render() {
return html`Hello, ${this.name}!
`;
}
}
์ด ์์ ๋ ์คํ์ผ๋ง๊ณผ ๋ฐ์ํ ์์ฑ์ ํฌํจํ LitElement ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
์ต์ ํ ์ ๋ต ๋ฐ ๊ธฐ์
ํ๋ ์์ํฌ๋ฅผ ์ ํํ๋ค๋ฉด, ์น ์ปดํฌ๋ํธ ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด ๋ค์ํ ์ต์ ํ ์ ๋ต์ ๊ตฌํํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ ๋ต์ ํฌ๊ฒ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฅํ ์ ์์ต๋๋ค:
1. ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ ๋จ์ถ
- ์ฝ๋ ๋ถํ : ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ํ ๋ ๋ก๋ํ ์ ์๋ ๋ ์์ ์ฒญํฌ๋ก ๋๋๋๋ค. ์ด๋ ์ด๊ธฐ ํ์ด๋ก๋๋ฅผ ์ค์ด๊ณ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. Stencil๊ณผ ๊ฐ์ ํ๋ ์์ํฌ๋ ์ฝ๋ ๋ถํ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํฉ๋๋ค.
- ์ง์ฐ ๋ก๋ฉ: ์ปดํฌ๋ํธ๊ฐ ๋ทฐํฌํธ์ ๋ณด์ผ ๋๋ง ๋ก๋ํฉ๋๋ค. ์ด๋ ์ฆ์ ํ์ํ์ง ์์ ์ปดํฌ๋ํธ์ ๋ถํ์ํ ๋ก๋ฉ์ ๋ฐฉ์งํฉ๋๋ค. ์ ์ ํ ๊ฒฝ์ฐ ์ปดํฌ๋ํธ ๋ด์ ์ด๋ฏธ์ง ๋ฐ iframe์
loading="lazy"์์ฑ์ ์ฌ์ฉํ์ธ์. Intersection Observer๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ ์ ์ง์ฐ ๋ก๋ฉ ๋ฉ์ปค๋์ฆ์ ๊ตฌํํ ์๋ ์์ต๋๋ค. - ํธ๋ฆฌ ์์ดํน: ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ฌ์ฉํ์ง ์๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค. Webpack ๋ฐ Rollup๊ณผ ๊ฐ์ ์ต์ ๋ฒ๋ค๋ฌ๋ ๋น๋ ๊ณผ์ ์์ ์๋์ผ๋ก ์ฃฝ์ ์ฝ๋๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
- ์ต์ํ ๋ฐ ์์ถ: ๊ณต๋ฐฑ, ์ฃผ์, ๋ถํ์ํ ๋ฌธ์๋ฅผ ์ ๊ฑฐํ์ฌ JavaScript, CSS, HTML ํ์ผ์ ํฌ๊ธฐ๋ฅผ ์ค์ ๋๋ค. Terser ๋ฐ Gzip๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ์ต์ํํ๊ณ ์์ถํ์ธ์.
- ์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ(CDN): CDN์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ๋ฌ ์๋ฒ์ ๋ถ์ฐ์ํต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ์์ ์ ์์น์ ๊ฐ๊น์ด ์๋ฒ์์ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ด๋ก๋ํ์ฌ ์ง์ฐ ์๊ฐ์ ์ค์ผ ์ ์์ต๋๋ค. Cloudflare ๋ฐ Akamai์ ๊ฐ์ ํ์ฌ๊ฐ CDN ์๋น์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ฌ์ ๋ ๋๋ง: ์๋ฒ์์ ์ปดํฌ๋ํธ์ ์ด๊ธฐ HTML์ ๋ ๋๋งํฉ๋๋ค. ์ด๋ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ๊ณผ SEO ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. Stencil์ ์ฌ์ ๋ ๋๋ง์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํฉ๋๋ค.
์์ : Intersection Observer๋ฅผ ์ด์ฉํ ์ง์ฐ ๋ก๋ฉ
class LazyLoadElement extends HTMLElement {
constructor() {
super();
this.observer = new IntersectionObserver(this.onIntersection.bind(this), { threshold: 0.2 });
}
connectedCallback() {
this.observer.observe(this);
}
disconnectedCallback() {
this.observer.unobserve(this);
}
onIntersection(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadContent();
this.observer.unobserve(this);
}
});
}
loadContent() {
// ์ฌ๊ธฐ์ ์ปดํฌ๋ํธ ์ฝํ
์ธ ๋ฅผ ๋ก๋ํฉ๋๋ค
this.innerHTML = '์ฝํ
์ธ ๊ฐ ๋ก๋๋์์ต๋๋ค!
'; // ์ค์ ์ปดํฌ๋ํธ ๋ก๋ฉ ๋ก์ง์ผ๋ก ๋์ฒดํ์ธ์
}
}
customElements.define('lazy-load-element', LazyLoadElement);
์ด ์์ ๋ Intersection Observer๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๊ฐ ๋ทฐํฌํธ์ ๋ณด์ผ ๋๋ง ํด๋น ์ฝํ ์ธ ๋ฅผ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
2. ๋ ๋๋ง ์ฑ๋ฅ ์ต์ ํ
- ๊ฐ์ DOM: ๊ฐ์ DOM์ ์ฌ์ฉํ์ฌ ์ค์ DOM ์ ๋ฐ์ดํธ ํ์๋ฅผ ์ต์ํํฉ๋๋ค. LitElement์ ๊ฐ์ ํ๋ ์์ํฌ๋ ๊ฐ์ DOM์ ์ฌ์ฉํ์ฌ UI๋ฅผ ํจ์จ์ ์ผ๋ก ์ ๋ฐ์ดํธํฉ๋๋ค.
- ๋๋ฐ์ด์ฑ ๋ฐ ์ค๋กํ๋ง: ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋๋ฐ์ด์ฑํ๊ฑฐ๋ ์ค๋กํ๋งํ์ฌ ์ ๋ฐ์ดํธ ๋น๋๋ฅผ ์ ํํฉ๋๋ค. ์ด๋ ์ด๋ฒคํธ๊ฐ ๋น ๋ฅด๊ฒ ํธ๋ฆฌ๊ฑฐ๋ ๋ ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํฉ๋๋ค.
- Should Update ์๋ช
์ฃผ๊ธฐ ํ
: ์ปดํฌ๋ํธ ์์ฑ์ด ๋ณ๊ฒฝ๋์ง ์์์ ๋ ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํ๊ธฐ ์ํด
shouldUpdate์๋ช ์ฃผ๊ธฐ ํ ์ ๊ตฌํํฉ๋๋ค. ์ด ํ ์ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ ์์ฑ์ ํ์ฌ ๊ฐ๊ณผ ์ด์ ๊ฐ์ ๋น๊ตํ๊ณ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋งtrue๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค. - ๋ถ๋ณ ๋ฐ์ดํฐ: ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ๊ฒฝ ๊ฐ์ง๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ๋ง๋ญ๋๋ค. ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ์ ํ์ฌ ์ํ์ ์ด์ ์ํ๋ฅผ ์ฝ๊ฒ ๋น๊ตํ๊ณ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
- ์น ์์ปค: ๊ณ์ฐ ์ง์ฝ์ ์ธ ์์ ์ ์น ์์ปค์ ์คํ๋ก๋ํ์ฌ ๋ฉ์ธ ์ค๋ ๋๊ฐ ์ฐจ๋จ๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์์ฑ์ ํฅ์์ํต๋๋ค.
- RequestAnimationFrame:
requestAnimationFrame์ ์ฌ์ฉํ์ฌ UI ์ ๋ฐ์ดํธ๋ฅผ ์์ฝํฉ๋๋ค. ์ด๋ ๋ธ๋ผ์ฐ์ ์ ๋ฆฌํ์ธํธ ์ฃผ๊ธฐ์ ๋ง์ถฐ ์ ๋ฐ์ดํธ๊ฐ ์ํ๋๋๋ก ๋ณด์ฅํ์ฌ ๋ฒ๋ฒ ์(jank)์ ๋ฐฉ์งํฉ๋๋ค. - ํจ์จ์ ์ธ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด: ๋ ๋๋ง์ ์ํด ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด์ ์ฌ์ฉํ ๋, ๊ฐ ์ ๋ฐ์ดํธ ์ ํ ํ๋ฆฟ์ ๋์ ์ธ ๋ถ๋ถ๋ง ์ฌํ๊ฐ๋๋๋ก ํฉ๋๋ค. ํ ํ๋ฆฟ์์ ๋ถํ์ํ ๋ฌธ์์ด ์ฐ๊ฒฐ์ด๋ ๋ณต์กํ ํํ์์ ํผํ์ธ์.
์์ : LitElement์ Should Update ์๋ช ์ฃผ๊ธฐ ํ
import { LitElement, html, css } from 'lit';
import { customElement, property } from 'lit/decorators.js';
@customElement('my-element')
export class MyElement extends LitElement {
static styles = css`
p {
color: blue;
}
`;
@property({ type: String })
name = 'World';
@property({ type: Number })
count = 0;
shouldUpdate(changedProperties) {
// 'name' ์์ฑ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ์
๋ฐ์ดํธํฉ๋๋ค
return changedProperties.has('name');
}
render() {
return html`Hello, ${this.name}! Count: ${this.count}
`;
}
updated(changedProperties) {
console.log('์
๋ฐ์ดํธ๋ ์์ฑ:', changedProperties);
}
}
์ด ์์ ์์๋ count ์์ฑ์ด ์
๋ฐ์ดํธ๋๋๋ผ๋ name ์์ฑ์ด ๋ณ๊ฒฝ๋ ๋๋ง ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋ ๋๋ง๋ฉ๋๋ค.
3. ๋ฉ๋ชจ๋ฆฌ ์๋น ์ค์ด๊ธฐ
- ๊ฐ๋น์ง ์ปฌ๋ ์ : ๋ถํ์ํ ๊ฐ์ฒด์ ๋ณ์๋ฅผ ์์ฑํ์ง ๋ง์ธ์. ๋ ์ด์ ํ์ํ์ง ์์ ๊ฐ์ฒด๋ ์ ๋๋ก ๊ฐ๋น์ง ์ปฌ๋ ์ ๋๋๋ก ํ์ธ์.
- ์ฝํ ์ฐธ์กฐ: DOM ์์์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์ฅํ ๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฝํ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ์ธ์. ์ฝํ ์ฐธ์กฐ๋ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๊ฐ ์ฌ์ ํ ์๋๋ผ๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ํ ์ ์๊ฒ ํฉ๋๋ค.
- ๊ฐ์ฒด ํ๋ง: ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฌ์ฉํ์ธ์. ์ด๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ค๋ฒํค๋๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
- DOM ์กฐ์ ์ต์ํ: ๋น๋ฒํ DOM ์กฐ์์ ๋ฉ๋ชจ๋ฆฌ์ ์ฑ๋ฅ ์ธก๋ฉด์์ ๋น์ฉ์ด ๋ง์ด ๋ค ์ ์์ผ๋ฏ๋ก ํผํ์ธ์. ๊ฐ๋ฅํ๋ฉด DOM ์ ๋ฐ์ดํธ๋ฅผ ์ผ๊ด ์ฒ๋ฆฌํ์ธ์.
- ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๊ด๋ฆฌ: ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ ์คํ๊ฒ ๊ด๋ฆฌํ์ธ์. ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ ์ด์ ํ์ํ์ง ์์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ ์ ๊ฑฐํ์ธ์.
4. ์ด๋ฒคํธ ์ฒ๋ฆฌ ์ต์ ํ
- ์ด๋ฒคํธ ์์: ๊ฐ๋ณ ์์ ์์ ๋์ ๋ถ๋ชจ ์์์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ฐ๊ฒฐํ๊ธฐ ์ํด ์ด๋ฒคํธ ์์์ ์ฌ์ฉํ์ธ์. ์ด๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ์๋ฅผ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ํจ์๋ธ ์ด๋ฒคํธ ๋ฆฌ์ค๋: ์คํฌ๋กค ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด ํจ์๋ธ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ฌ์ฉํ์ธ์. ํจ์๋ธ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ด๋ฒคํธ์ ๊ธฐ๋ณธ ๋์์ ๋ง์ง ์์ ๊ฒ์์ ๋ธ๋ผ์ฐ์ ์ ์๋ ค์ฃผ์ด ๋ธ๋ผ์ฐ์ ๊ฐ ์คํฌ๋กค์ ์ต์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ๋๋ฐ์ด์ฑ ๋ฐ ์ค๋กํ๋ง: ์์ ์ธ๊ธํ๋ฏ์ด, ๋๋ฐ์ด์ฑ ๋ฐ ์ค๋กํ๋ง์ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์คํ ๋น๋๋ฅผ ์ ํํ์ฌ ์ด๋ฒคํธ ์ฒ๋ฆฌ๋ฅผ ์ต์ ํํ๋ ๋ฐ์๋ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
์์ : ์ด๋ฒคํธ ์์
<ul id="my-list">
<li>ํญ๋ชฉ 1</li>
<li>ํญ๋ชฉ 2</li>
<li>ํญ๋ชฉ 3</li>
</ul>
<script>
const list = document.getElementById('my-list');
list.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log('ํด๋ฆญ๋ ํญ๋ชฉ:', event.target.textContent);
}
});
</script>
์ด ์์ ์์๋ ๋จ์ผ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ul ์์์ ์ฐ๊ฒฐ๋๊ณ , ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ํด๋ฆญ๋ ์์๊ฐ li ์์์ธ์ง ํ์ธํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ li ์์์ ๊ฐ๋ณ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ์ ํผํ ์ ์์ต๋๋ค.
5. ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ์ต์ ํ
- ํจ์จ์ ์ธ ์๋ฃ ๊ตฌ์กฐ: ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํด ํจ์จ์ ์ธ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ธ์. ์์ ์ค์ธ ๋ฐ์ดํฐ ์ ํ๊ณผ ์ํํด์ผ ํ ์์ ์ ์ ํฉํ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์ ํํ์ธ์.
- ๋ฉ๋ชจ์ด์ ์ด์ : ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ๊ธฐ ์ํด ๋ฉ๋ชจ์ด์ ์ด์ ์ ์ฌ์ฉํ์ธ์. ์ด๋ ๋์ผํ ์ ๋ ฅ์ด ์ฌ๋ฌ ๋ฒ ์ ๊ณต๋ ๋ ๋ถํ์ํ ์ฌ๊ณ์ฐ์ ๋ฐฉ์งํฉ๋๋ค.
- Track By: ๋ฐ์ดํฐ ๋ชฉ๋ก์ ๋ ๋๋งํ ๋
trackByํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ชฉ๋ก์ ๊ฐ ํญ๋ชฉ์ ๊ณ ์ ํ๊ฒ ์๋ณํ์ธ์. ์ด๋ฅผ ํตํด ๋ชฉ๋ก์ด ๋ณ๊ฒฝ๋ ๋ ๋ธ๋ผ์ฐ์ ๊ฐ DOM์ ํจ์จ์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค. ๋ง์ ํ๋ ์์ํฌ๊ฐ ๊ณ ์ ID๋ฅผ ํ ๋นํ๋ ๋ฑ ํญ๋ชฉ์ ํจ์จ์ ์ผ๋ก ์ถ์ ํ๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค.
์ ๊ทผ์ฑ ๊ณ ๋ ค์ฌํญ
์ฑ๋ฅ ์ต์ ํ๊ฐ ์ ๊ทผ์ฑ์ ํฌ์ํด์๋ ์ ๋ฉ๋๋ค. ๋ค์ ๊ฐ์ด๋๋ผ์ธ์ ๋ฐ๋ผ ์น ์ปดํฌ๋ํธ๊ฐ ์ฅ์ ๋ฅผ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ๋ ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ํ์ธ์:
- ์๋งจํฑ HTML: ์ฝํ ์ธ ์ ์๋ฏธ์ ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์๋งจํฑ HTML ์์๋ฅผ ์ฌ์ฉํ์ธ์.
- ARIA ์์ฑ: ์ปดํฌ๋ํธ์ ์ญํ , ์ํ, ์์ฑ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ARIA ์์ฑ์ ์ฌ์ฉํ์ธ์.
- ํค๋ณด๋ ๋ค๋น๊ฒ์ด์ : ์ปดํฌ๋ํธ๊ฐ ํค๋ณด๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ ํ์ ๊ฐ๋ฅํ๋๋ก ํ์ธ์.
- ์คํฌ๋ฆฐ ๋ฆฌ๋ ํธํ์ฑ: ์คํฌ๋ฆฐ ๋ฆฌ๋๋ก ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ์ฌ ์ ๋๋ก ์๋ด๋๋์ง ํ์ธํ์ธ์.
- ์์ ๋๋น: ์ปดํฌ๋ํธ์ ์์ ๋๋น๊ฐ ์ ๊ทผ์ฑ ํ์ค์ ์ถฉ์กฑํ๋์ง ํ์ธํ์ธ์.
๊ตญ์ ํ(i18n)
๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ ์น ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ถํ ๋๋ ๊ตญ์ ํ๋ฅผ ๊ณ ๋ คํ์ธ์. ๋ค์์ ์ฃผ์ i18n ๊ณ ๋ ค์ฌํญ์ ๋๋ค:
- ํ ์คํธ ๋ฐฉํฅ: ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ(LTR) ๋ฐ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ(RTL) ํ ์คํธ ๋ฐฉํฅ์ ๋ชจ๋ ์ง์ํ์ธ์.
- ๋ ์ง ๋ฐ ์๊ฐ ํ์: ๋ก์ผ์ผ์ ๋ง๋ ๋ ์ง ๋ฐ ์๊ฐ ํ์์ ์ฌ์ฉํ์ธ์.
- ์ซ์ ํ์: ๋ก์ผ์ผ์ ๋ง๋ ์ซ์ ํ์์ ์ฌ์ฉํ์ธ์.
- ํตํ ํ์: ๋ก์ผ์ผ์ ๋ง๋ ํตํ ํ์์ ์ฌ์ฉํ์ธ์.
- ๋ฒ์ญ: ์ปดํฌ๋ํธ์ ๋ชจ๋ ํ ์คํธ์ ๋ํ ๋ฒ์ญ์ ์ ๊ณตํ์ธ์.
- ๋ณต์ํ ์ฒ๋ฆฌ: ๋ค๋ฅธ ์ธ์ด์ ๋ํด ๋ณต์ํ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ธ์.
์์ : ์ซ์ ์์์ Intl API ์ฌ์ฉํ๊ธฐ
const number = 1234567.89;
const locale = 'de-DE'; // ๋
์ผ์ด ๋ก์ผ์ผ
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'EUR',
});
const formattedNumber = formatter.format(number);
console.log(formattedNumber); // ์ถ๋ ฅ: 1.234.567,89 โฌ
์ด ์์ ๋ Intl.NumberFormat API๋ฅผ ์ฌ์ฉํ์ฌ ๋
์ผ์ด ๋ก์ผ์ผ์ ๋ฐ๋ผ ์ซ์์ ์์์ ์ง์ ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
ํ ์คํ ๋ฐ ๋ชจ๋ํฐ๋ง
์ ๊ธฐ์ ์ธ ํ ์คํ ๊ณผ ๋ชจ๋ํฐ๋ง์ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์๋ณํ๊ณ ํด๊ฒฐํ๋ ๋ฐ ํ์์ ์ ๋๋ค. ๋ค์ ๋๊ตฌ์ ๊ธฐ์ ์ ์ฌ์ฉํ์ธ์:
- ์ฑ๋ฅ ํ๋กํ์ผ๋ง: ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ํ๋กํ์ผ๋งํ์ธ์. ๋ณ๋ชฉ ํ์๊ณผ ์ต์ ํ ์์ญ์ ์๋ณํ์ธ์.
- ๋ถํ ํ ์คํธ: ๋ค์์ ์ฌ์ฉ์๋ฅผ ์๋ฎฌ๋ ์ด์ ํ์ฌ ๋ถํ ์ํ์์ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ํ ์คํธํ์ธ์.
- ์๋ํ๋ ํ ์คํธ: ์๋ํ๋ ํ ์คํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ด ์ ์ฉ๋ ํ์๋ ์ปดํฌ๋ํธ๊ฐ ๊ณ์ํด์ ์ข์ ์ฑ๋ฅ์ ์ ์งํ๋์ง ํ์ธํ์ธ์. WebdriverIO ๋ฐ Cypress์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์น ์ปดํฌ๋ํธ์ ์๋ํฌ์๋ ํ ์คํธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ค์ ์ฌ์ฉ์ ๋ชจ๋ํฐ๋ง(RUM): ์ค์ ์ฌ์ฉ์๋ก๋ถํฐ ์ฑ๋ฅ ๋ฐ์ดํฐ๋ฅผ ์์งํ์ฌ ์ค์ ํ๊ฒฝ์์์ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์๋ณํ์ธ์.
- ์ง์์ ํตํฉ(CI): ์ฑ๋ฅ ํ ์คํธ๋ฅผ CI ํ์ดํ๋ผ์ธ์ ํตํฉํ์ฌ ์ฑ๋ฅ ์ ํ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ์ธ์.
๊ฒฐ๋ก
์น ์ปดํฌ๋ํธ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๊ฒ์ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ์ด ์ข์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ ์ฌ์ ์ธ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ดํดํ๊ณ , ์ฌ๋ฐ๋ฅธ ํ๋ ์์ํฌ๋ฅผ ์ ํํ๊ณ , ์ด ๊ฐ์ด๋์์ ์ค๋ช ํ ์ต์ ํ ์ ๋ต์ ๊ตฌํํจ์ผ๋ก์จ ์น ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค. ๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ์ถํ ๋ ์ ๊ทผ์ฑ๊ณผ ๊ตญ์ ํ๋ฅผ ๊ณ ๋ คํ๊ณ , ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์๋ณํ๊ณ ํด๊ฒฐํ๊ธฐ ์ํด ์ ๊ธฐ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ๊ณ ๋ชจ๋ํฐ๋งํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
์ด๋ฌํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ธ ๋ฟ๋ง ์๋๋ผ ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ์ฑ๋ฅ์ด ๋ฐ์ด๋๊ณ ์ ๊ทผ์ฑ์ด ์ข์ ์น ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.