λ λΉ λ₯΄κ³ ν¨μ¨μ μΈ κΈλ‘λ² μΉ μ ν리μΌμ΄μ μ μν΄ μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ‘λ©μ μ΅μ ννμΈμ. ν₯μλ μ¬μ©μ κ²½νμ μν ν΅μ¬ κΈ°μ , μ±λ₯ λ©νΈλ¦, λͺ¨λ² μ¬λ‘λ₯Ό μ΄ν΄λ³΄μΈμ.
μλ°μ€ν¬λ¦½νΈ λͺ¨λ μ±λ₯: κΈλ‘λ² μ ν리μΌμ΄μ μ μν λ‘λ© μ΅μ ν λ° λ©νΈλ¦
μ€λλ κ³Ό κ°μ΄ μνΈ μ°κ²°λ λμ§νΈ νκ²½μμλ μ μΈκ³ μ¬μ©μμκ² λΉ λ₯΄κ³ λ°μμ±μ΄ λ°μ΄λ μΉ μ ν리μΌμ΄μ μ μ 곡νλ κ²μ΄ 무μλ³΄λ€ μ€μν©λλ€. μΈν°λν°λΈν μΉ κ²½νμ κ·Όκ°μ΄ λλ μλ°μ€ν¬λ¦½νΈλ μ¬κΈ°μ μ€μν μν μ ν©λλ€. νμ§λ§ μλ°μ€ν¬λ¦½νΈ λͺ¨λμ λΉν¨μ¨μ μΈ λ‘λ©μ μ±λ₯μ ν¬κ² μ νμμΌ λ‘λ μκ°μ λλ¦¬κ³ μ¬μ©μλ₯Ό λΆνΈνκ² νλ©°, κΆκ·Ήμ μΌλ‘λ κΈ°ν μμ€λ‘ μ΄μ΄μ§ μ μμ΅λλ€. μ΄ μ’ ν© κ°μ΄λμμλ μλ°μ€ν¬λ¦½νΈ λͺ¨λ μ±λ₯μ 볡μ‘μ±μ κΉμ΄ νκ³ λ€μ΄, μ§μ ν κΈλ‘λ² κ³ μ±λ₯ μ ν리μΌμ΄μ μ μν΄ μΆμ ν΄μΌ ν λ‘λ© μ΅μ ν κΈ°λ²κ³Ό ν΅μ¬ λ©νΈλ¦μ μ΄μ μ λ§μΆ₯λλ€.
μ μ λ μ€μν΄μ§λ μλ°μ€ν¬λ¦½νΈ λͺ¨λ μ±λ₯
μΉ μ ν리μΌμ΄μ μ΄ λ³΅μ‘ν΄μ§κ³ κΈ°λ₯μ΄ νλΆν΄μ§μλ‘ νμν μλ°μ€ν¬λ¦½νΈ μ½λμ μλ λμ΄λ©λλ€. μ»΄ν¬λνΈ κΈ°λ° μν€ν μ²λ μλνν° λΌμ΄λΈλ¬λ¦¬μ κ΄λ²μν μ¬μ©κ³Ό κ°μ νλ κ°λ° λ°©μμ λ ν° μλ°μ€ν¬λ¦½νΈ λ²λ€μ λ§λλλ€. μ΄λ¬ν λ²λ€μ΄ λ¨μΌ νμΌ(monolithic)λ‘ μ λ¬λλ©΄, μ¬μ©μλ μ§λ¦¬μ μμΉλ λ€νΈμν¬ μνμ κ΄κ³μμ΄ μλΉν λ€μ΄λ‘λ λ° νμ± μκ°μ κ²ͺκ² λ©λλ€. μ΄λ μΈνλΌκ° λ λ°λ¬λ μ§μμ΄λ λμνμ΄ μ νλ λͺ¨λ°μΌ κΈ°κΈ°λ₯Ό μ¬μ©νλ μ¬μ©μμκ² νΉν μ€μν©λλ€.
μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ‘λ© λ°©μμ μ΅μ ννλ κ²μ μ¬μ©μ κ²½νκ³Ό μ ν리μΌμ΄μ μ±κ³΅μ μ¬λ¬ ν΅μ¬ μΈ‘λ©΄μ μ§μ μ μΈ μν₯μ λ―ΈμΉ©λλ€:
- μ΄κΈ° λ‘λ μκ°: λ§μ μ¬μ©μμκ² μ΄κΈ° λ‘λ μκ°μ μ ν리μΌμ΄μ μ λν 첫μΈμμ λλ€. λ‘λ©μ΄ λ리면 μ¦μ μ΄νλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
- μνΈμμ©μ±: HTMLκ³Ό CSSκ° λ λλ§λ ν, μ ν리μΌμ΄μ μ΄ μνΈμμ© κ°λ₯ν΄μ§λ €λ©΄ μλ°μ€ν¬λ¦½νΈκ° νμν©λλ€. μ¬κΈ°μ μ§μ°μ΄ λ°μνλ©΄ μ ν리μΌμ΄μ μ΄ κ΅Όλ¨κ² λκ»΄μ§ μ μμ΅λλ€.
- μ¬μ©μ μ°Έμ¬: μΌλ°μ μΌλ‘ μ ν리μΌμ΄μ μ΄ λΉ λ₯Όμλ‘ μ°Έμ¬λκ° λμμ§κ³ , μΈμ μ§μ μκ°μ΄ κΈΈμ΄μ§λ©°, μ νμ¨μ΄ ν₯μλ©λλ€.
- SEO: κ²μ μμ§μ νμ΄μ§ μλλ₯Ό μμ κ²°μ μμΈμΌλ‘ κ³ λ €ν©λλ€. μ΅μ νλ μλ°μ€ν¬λ¦½νΈ λ‘λ©μ λ λμ κ²μ μμ§ κ°μμ±μ κΈ°μ¬ν©λλ€.
- μ κ·Όμ±: λλ¦° μ°κ²°μ΄λ ꡬν κΈ°κΈ°λ₯Ό μ¬μ©νλ μ¬μ©μμκ² ν¨μ¨μ μΈ λ‘λ©μ λ 곡νν κ²½νμ 보μ₯ν©λλ€.
μλ°μ€ν¬λ¦½νΈ λͺ¨λ μ΄ν΄νκΈ°
μ΅μ νμ λν΄ μμ보기 μ μ, μλ°μ€ν¬λ¦½νΈ λͺ¨λμ΄ μ΄λ»κ² μλνλμ§ νμ€ν μ΄ν΄νλ κ²μ΄ μ€μν©λλ€. νλ μλ°μ€ν¬λ¦½νΈλ ES λͺ¨λ(ESM)μ΄λ CommonJS(μ£Όλ‘ Node.jsμμ μ¬μ©)μ κ°μ λͺ¨λ μμ€ν μ μ¬μ©ν©λλ€. λΈλΌμ°μ μ νμ€μΈ ESMμ κ°λ°μκ° μ½λλ₯Ό μ¬μ¬μ© κ°λ₯ν μ‘°κ°μΌλ‘ λλκ³ , κ° μ‘°κ°μ΄ κ³ μ ν μ€μ½νλ₯Ό κ°λλ‘ ν©λλ€. μ΄λ¬ν λͺ¨λμ±μ λ§μ μ±λ₯ μ΅μ νμ κΈ°λ°μ΄ λ©λλ€.
λΈλΌμ°μ κ° <script type="module"> νκ·Έλ₯Ό λ§λλ©΄ μμ‘΄μ± κ·Έλν μνλ₯Ό μμν©λλ€. λ©μΈ λͺ¨λμ κ°μ Έμ¨ λ€μ, ν΄λΉ λͺ¨λμ΄ μν¬νΈνλ λͺ¨λ λͺ¨λμ κ°μ Έμ€λ μμΌλ‘ μ¬κ·μ μΌλ‘ μ€νμ νμν μ 체 μ½λλ₯Ό ꡬμΆν©λλ€. μ΄ κ³Όμ μ΄ μ μ€νκ² κ΄λ¦¬λμ§ μμΌλ©΄ μλ§μ κ°λ³ HTTP μμ²μ΄ λ°μνκ±°λ κ±°λν λ¨μΌ μλ°μ€ν¬λ¦½νΈ νμΌμ΄ μμ±λ μ μμ΅λλ€.
μ£Όμ λ‘λ© μ΅μ ν κΈ°λ²
λ‘λ© μ΅μ νμ λͺ©νλ νμν μλ°μ€ν¬λ¦½νΈ μ½λλ§ μ μμ μ¬μ©μμκ² μ λ¬νλ κ²μ λλ€. μ΄λ₯Ό ν΅ν΄ μ μ‘λκ³ μ²λ¦¬λλ λ°μ΄ν°μ μμ μ΅μννμ¬ ν¨μ¬ λ λΉ λ₯Έ κ²½νμ μ 곡ν μ μμ΅λλ€.
1. μ½λ μ€ν리ν (Code Splitting)
μ μ: μ½λ μ€ν리ν μ μλ°μ€ν¬λ¦½νΈ λ²λ€μ λ μκ³ κ΄λ¦¬νκΈ° μ¬μ΄ μ²ν¬(chunk)λ‘ λλμ΄ νμν λ λ‘λν μ μκ² νλ κΈ°λ²μ λλ€. μ 체 μ ν리μΌμ΄μ μ μν΄ νλμ ν° νμΌμ μ 곡νλ λμ , κ°κ° νΉμ κΈ°λ₯μ ν¬ν¨νλ μ¬λ¬ κ°μ μμ νμΌμ μμ±ν©λλ€.
μ₯μ :
- μ΄κΈ° λ€μ΄λ‘λ ν¬κΈ° κ°μ: μ¬μ©μλ μ΄κΈ° λ·°μ μ¦κ°μ μΈ μνΈμμ©μ νμν μλ°μ€ν¬λ¦½νΈλ§ λ€μ΄λ‘λν©λλ€.
- μΊμ± κ°μ : μκ³ λ 립μ μΈ μ²ν¬λ λΈλΌμ°μ μ μν΄ μΊμλ κ°λ₯μ±μ΄ λμμ Έ νμ λ°©λ¬Έ μλλ₯Ό λμ λλ€.
- μ¨λ맨λ λ‘λ© κ°λ₯: μ¦μ νμνμ§ μμ κΈ°λ₯μ μ¬μ©μκ° μ κ·Όν λλ§ λ‘λν μ μμ΅λλ€.
ꡬν: Webpack, Rollup, Parcelκ³Ό κ°μ λλΆλΆμ νλ μλ°μ€ν¬λ¦½νΈ λ²λ€λ¬λ μ½λ μ€ν리ν μ κΈ°λ³Έμ μΌλ‘ μ§μν©λλ€. μ§μ μ (entry points), λμ μν¬νΈ, λλ λ²€λ λΌμ΄λΈλ¬λ¦¬λ₯Ό κΈ°λ°μΌλ‘ μ½λλ₯Ό μλμΌλ‘ λΆν νλλ‘ κ΅¬μ±ν μ μμ΅λλ€.
μμ (Webpack):
Webpack μ€μ μμ μ§μ μ μ μ μν μ μμ΅λλ€:
// webpack.config.js
module.exports = {
entry: {
main: './src/index.js',
vendors: './src/vendors.js'
},
output: {
filename: '[name].bundle.js',
path: __dirname + '/dist'
}
};
λμ μν¬νΈ(Dynamic Imports): λ κ°λ ₯ν μ κ·Ό λ°©μμ λμ μν¬νΈ(import())λ₯Ό μ¬μ©νλ κ²μ
λλ€. μ΄λ₯Ό ν΅ν΄ λͺ¨λμ΄ νμν λ, μΌλ°μ μΌλ‘ μ¬μ©μ νλμ λν μλ΅μΌλ‘ λͺ¨λμ λ‘λν μ μμ΅λλ€.
// src/components/UserProfile.js
export default function UserProfile() {
console.log('User profile loaded!');
}
// src/index.js
const userProfileButton = document.getElementById('load-profile');
userProfileButton.addEventListener('click', () => {
import('./components/UserProfile.js').then(module => {
const UserProfile = module.default;
UserProfile();
}).catch(err => {
console.error('Failed to load UserProfile module', err);
});
});
μ΄ μ κ·Ό λ°©μμ UserProfile.jsμ λν λ³λμ μλ°μ€ν¬λ¦½νΈ μ²ν¬λ₯Ό μμ±νλ©°, μ΄ μ²ν¬λ λ²νΌμ ν΄λ¦νμ λλ§ λ€μ΄λ‘λλκ³ μ€νλ©λλ€.
2. νΈλ¦¬ μμ΄νΉ(Tree Shaking)
μ μ: νΈλ¦¬ μμ΄νΉμ λ²λ€λ¬κ° μλ°μ€ν¬λ¦½νΈ λ²λ€μμ μ¬μ©λμ§ μλ μ½λλ₯Ό μ κ±°νλ νλ‘μΈμ€μ λλ€. μ½λλ₯Ό λΆμνμ¬ μ ν μν¬νΈλκ±°λ μ¬μ©λμ§ μλ exportλ₯Ό μλ³νκ³ μ΅μ’ κ²°κ³Όλ¬Όμμ ν¨κ³Όμ μΌλ‘ μ κ±°ν©λλ€.
μ₯μ :
- λ²λ€ ν¬κΈ° λν κ°μ: λ°λ μ½λλ₯Ό μ κ±°ν¨μΌλ‘μ¨ νΈλ¦¬ μμ΄νΉμ μ€μ λ‘ μ¬μ©λλ μ½λλ§ μ λ¬νλλ‘ λ³΄μ₯ν©λλ€.
- νμ± λ° μ€ν μκ° κ°μ : μ½λκ° μ μμλ‘ λΈλΌμ°μ κ° νμ±νκ³ μ€νν μμ΄ μ€μ΄λ€μ΄ μμ μλκ° λΉ¨λΌμ§λλ€.
ꡬν: νΈλ¦¬ μμ΄νΉμ Webpack(v2+) λ° Rollupκ³Ό κ°μ νλ λ²λ€λ¬μ κΈ°λ₯μ λλ€. μ μ ꡬ쑰 λλΆμ μ νν λΆμμ΄ κ°λ₯ν ES λͺ¨λκ³Ό κ°μ₯ μ μλν©λλ€. νΈλ¦¬ μμ΄νΉκ³Ό κ°μ μ΅μ νλ μΌλ°μ μΌλ‘ νλ‘λμ λΉλ λͺ¨λμμ νμ±νλλ―λ‘ λ²λ€λ¬κ° ν΄λΉ λͺ¨λλ‘ κ΅¬μ±λμλμ§ νμΈνμΈμ.
μμ:
μ νΈλ¦¬ν° νμΌμ κ³ λ €ν΄ λ³΄μΈμ:
// src/utils.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
λ§μ½ `add` ν¨μλ§ μν¬νΈνκ³ μ¬μ©νλ€λ©΄:
// src/main.js
import { add } from './utils.js';
console.log(add(5, 3));
μ¬λ°λ₯΄κ² ꡬμ±λ λ²λ€λ¬λ νΈλ¦¬ μμ΄νΉμ μννμ¬ `subtract` λ° `multiply` ν¨μλ₯Ό μ΅μ’ λ²λ€μμ μ μΈν©λλ€.
μ€μ μ°Έκ³ μ¬ν: νΈλ¦¬ μμ΄νΉμ ES λͺ¨λ ꡬ문μ μμ‘΄ν©λλ€. λͺ¨λμ λΆμ ν¨κ³Ό(side effects, exportλ₯Ό λͺ
μμ μΌλ‘ μ¬μ©νμ§ μκ³ λͺ¨λμ μν¬νΈνλ κ²λ§μΌλ‘ μ€νλλ μ½λ)λ νΈλ¦¬ μμ΄νΉμ΄ μ¬λ°λ₯΄κ² μλνλ κ²μ λ°©ν΄ν μ μμ΅λλ€. λͺ¨λμ λΆμ ν¨κ³Όκ° μλ€κ³ νμ νλ€λ©΄ package.jsonμ sideEffects: falseλ₯Ό μ¬μ©νκ±°λ λ²λ€λ¬λ₯Ό κ·Έμ λ§κ² ꡬμ±νμΈμ.
3. μ§μ° λ‘λ©(Lazy Loading)
μ μ: μ§μ° λ‘λ©μ μ€μνμ§ μμ 리μμ€μ λ‘λ©μ νμν λκΉμ§ μ§μ°μν€λ μ λ΅μ λλ€. μλ°μ€ν¬λ¦½νΈμ λ§₯λ½μμλ νΉμ κΈ°λ₯μ΄λ μ»΄ν¬λνΈκ° μ¬μ©λκΈ° μ§μ μλ§ μλ°μ€ν¬λ¦½νΈ μ½λλ₯Ό λ‘λνλ κ²μ μλ―Έν©λλ€.
μ₯μ :
- μ΄κΈ° νμ΄μ§ λ‘λ μλ ν₯μ: νμμ μ΄μ§ μμ μλ°μ€ν¬λ¦½νΈμ λ‘λ©μ μ§μ°μν΄μΌλ‘μ¨ ν¬λ¦¬ν°μ»¬ ν¨μ€(critical path)κ° λ¨μΆλμ΄ νμ΄μ§κ° λ 빨리 μνΈμμ© κ°λ₯ν΄μ§λλ€.
- μ²΄κ° μ±λ₯ κ°μ : λ€λ₯Έ κΈ°λ₯λ€μ΄ λ°±κ·ΈλΌμ΄λμμ λ‘λ©λλ λμμλ μ¬μ©μλ μ½ν μΈ λ₯Ό λ³΄κ³ μ ν리μΌμ΄μ μ μΌλΆμ λ 빨리 μνΈμμ©ν μ μμ΅λλ€.
ꡬν: μ§μ° λ‘λ©μ μ½λ μ€ν리ν
μμμμ 보μ¬μ€ κ²μ²λΌ λμ import() λ¬Έμ μ¬μ©νμ¬ μ’
μ’
ꡬνλ©λλ€. λ€λ₯Έ μ λ΅μΌλ‘λ μ¬μ©μ μνΈμμ©(μ: μμλ‘ μ€ν¬λ‘€, λ²νΌ ν΄λ¦)μ μλ΅νμ¬ μ€ν¬λ¦½νΈλ₯Ό λ‘λνκ±°λ, Intersection Observerμ κ°μ λΈλΌμ°μ APIλ₯Ό μ¬μ©νμ¬ μμκ° λ·°ν¬νΈμ λ€μ΄μ€λ μμ μ κ°μ§νλ λ°©λ²μ΄ μμ΅λλ€.
Intersection Observerλ₯Ό μ¬μ©ν μμ:
// src/components/HeavyComponent.js
export default function HeavyComponent() {
console.log('Heavy component rendered!');
const element = document.createElement('div');
element.textContent = 'This is a heavy component.';
return element;
}
// src/index.js
const lazyLoadTrigger = document.getElementById('lazy-load-trigger');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
import('./components/HeavyComponent.js').then(module => {
const HeavyComponent = module.default;
const component = HeavyComponent();
entry.target.appendChild(component);
observer.unobserve(entry.target); // Stop observing once loaded
}).catch(err => {
console.error('Failed to load HeavyComponent', err);
});
}
});
}, {
threshold: 0.1 // Trigger when 10% of the element is visible
});
observer.observe(lazyLoadTrigger);
μ΄ μ½λλ lazyLoadTrigger μμκ° λ·°ν¬νΈμ λ³΄μΌ λλ§ HeavyComponent.jsλ₯Ό λ‘λν©λλ€.
4. λͺ¨λ νλλ μ΄μ (Module Federation)
μ μ: λͺ¨λ νλλ μ΄μ μ Webpack 5μ μν΄ λμ€νλ κ³ κΈ μν€ν μ² ν¨ν΄μΌλ‘, λ 립μ μΌλ‘ λ°°ν¬λ λ€λ₯Έ μλ°μ€ν¬λ¦½νΈ μ ν리μΌμ΄μ μμ λμ μΌλ‘ μ½λλ₯Ό λ‘λν μ μκ² ν΄μ€λλ€. μ΄λ₯Ό ν΅ν΄ μ ν리μΌμ΄μ μ λ€λ₯Έ λΆλΆμ λ 립μ μΌλ‘ κ°λ°, λ°°ν¬ λ° νμ₯ν μ μλ λ§μ΄ν¬λ‘ νλ‘ νΈμλ μν€ν μ²λ₯Ό ꡬνν μ μμ΅λλ€.
μ₯μ :
- λ§μ΄ν¬λ‘ νλ‘ νΈμλ ꡬν κ°λ₯: νλ€μ΄ μλ‘ κ°μ μμ΄ λκ·λͺ¨ μ ν리μΌμ΄μ μ κ°κΈ° λ€λ₯Έ λΆλΆμ μμ ν μ μμ΅λλ€.
- μμ‘΄μ± κ³΅μ : κ³΅ν΅ λΌμ΄λΈλ¬λ¦¬(μ: React, Vue)λ₯Ό μ¬λ¬ μ ν리μΌμ΄μ μμ 곡μ νμ¬ μ 체 λ€μ΄λ‘λ ν¬κΈ°λ₯Ό μ€μ΄κ³ μΊμ±μ κ°μ ν μ μμ΅λλ€.
- λμ μ½λ λ‘λ©: μ ν리μΌμ΄μ μ΄ λ°νμμ λ€λ₯Έ νλλ μ΄μ λ μ ν리μΌμ΄μ μ λͺ¨λμ μμ²νκ³ λ‘λν μ μμ΅λλ€.
ꡬν: λͺ¨λ νλλ μ΄μ μ λ²λ€λ¬(μ: Webpack)μμ νΉμ ꡬμ±μ΄ νμν©λλ€. μ ν리μΌμ΄μ μ΄ μ 곡νλ λͺ¨λμΈ 'exposes'μ μ ν리μΌμ΄μ μ΄ λͺ¨λμ λ‘λν μ μλ λ€λ₯Έ μ ν리μΌμ΄μ μΈ 'remotes'λ₯Ό μ μν©λλ€.
κ°λ μ μμ (Webpack 5 μ€μ ):
μ± A (컨ν μ΄λ/νΈμ€νΈ):
// webpack.config.js (for App A)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ... other config
plugins: [
new ModuleFederationPlugin({
name: 'app_a',
remotes: {
app_b: 'app_b@http://localhost:3002/remoteEntry.js'
},
shared: ['react', 'react-dom'] // Share React dependencies
})
]
};
μ± B (리λͺ¨νΈ):
// webpack.config.js (for App B)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ... other config
plugins: [
new ModuleFederationPlugin({
name: 'app_b',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button.js'
},
shared: ['react', 'react-dom']
})
]
};
μ± Aμμλ μ± Bμ Buttonμ λμ μΌλ‘ λ‘λν μ μμ΅λλ€:
// In App A's code
import React from 'react';
const Button = React.lazy(() => import('app_b/Button'));
function App() {
return (
App A
Loading Button... }>
5. λ€μν νκ²½μ λ§λ λͺ¨λ λ‘λ© μ΅μ ν
μλ² μ¬μ΄λ λ λλ§(SSR) λ° μ¬μ λ λλ§(Pre-rendering): μ€μν μ΄κΈ° μ½ν μΈ μ κ²½μ°, SSR λλ μ¬μ λ λλ§μ μ²΄κ° μ±λ₯κ³Ό SEOλ₯Ό ν¬κ² ν₯μμν¬ μ μμ΅λλ€. μλ²λ λΉλ νλ‘μΈμ€κ° μ΄κΈ° HTMLμ μμ±νκ³ , ν΄λΌμ΄μΈνΈ μΈ‘μμ μλ°μ€ν¬λ¦½νΈλ‘ κΈ°λ₯μ ν₯μμν΅λλ€(μ΄ κ³Όμ μ νμ΄λλ μ΄μ μ΄λΌκ³ ν©λλ€). μ΄λ μ¬μ©μκ° μλ―Έ μλ μ½ν μΈ λ₯Ό ν¨μ¬ λ 빨리 λ³Ό μ μμμ μλ―Έν©λλ€.
νμ΄λλ μ΄μ μ μ¬μ©ν ν΄λΌμ΄μΈνΈ μ¬μ΄λ λ λλ§(CSR): React, Vue, Angularμ κ°μ CSR νλ μμν¬λ₯Ό μ¬μ©νλλΌλ νμ΄λλ μ΄μ μ€ μλ°μ€ν¬λ¦½νΈ λ‘λ©μ μ μ€νκ² κ΄λ¦¬νλ κ²μ΄ μ€μν©λλ€. μ΄κΈ° λ λλ§μ νμμ μΈ μλ°μ€ν¬λ¦½νΈλ§ λ¨Όμ λ‘λνκ³ λλ¨Έμ§λ μ μ§μ μΌλ‘ λ‘λνλλ‘ νμΈμ.
μ μ§μ ν₯μ(Progressive Enhancement): λ¨Όμ κΈ°λ³Έμ μΈ HTMLκ³Ό CSSλ‘ μλνλλ‘ μ ν리μΌμ΄μ μ μ€κ³ν λ€μ, μλ°μ€ν¬λ¦½νΈ ν₯μ κΈ°λ₯μ λ§λΆμ΄μΈμ. μ΄λ μλ°μ€ν¬λ¦½νΈκ° λΉνμ±νλμκ±°λ λ§€μ° λλ¦° μ°κ²°μ μ¬μ©νλ μ¬μ©μλ μνΈμμ©μ±μ λνμ§λ§ μ¬μ© κ°λ₯ν κ²½νμ ν μ μλλ‘ λ³΄μ₯ν©λλ€.
6. ν¨μ¨μ μΈ λ²€λ λ²λ€λ§(Vendor Bundling)
μ μ: React, Lodash, Axiosμ κ°μ μλνν° λΌμ΄λΈλ¬λ¦¬λ₯Ό ν¬ν¨νλ λ²€λ μ½λλ μ’ μ’ μλ°μ€ν¬λ¦½νΈ λ²λ€μ μλΉ λΆλΆμ μ°¨μ§ν©λλ€. μ΄ λ²€λ μ½λλ₯Ό μ²λ¦¬νλ λ°©λ²μ μ΅μ ννλ©΄ μλΉν μ±λ₯ ν₯μμ μ»μ μ μμ΅λλ€.
μ₯μ :
- μΊμ± κ°μ : λ²€λ μ½λλ₯Ό λ³λμ λ²λ€λ‘ λΆλ¦¬νλ©΄ μ ν리μΌμ΄μ μ½λμ λ 립μ μΌλ‘ μΊμν μ μμ΅λλ€. μ ν리μΌμ΄μ μ½λλ λ³κ²½λμ§λ§ λ²€λ μ½λλ κ·Έλλ‘μΈ κ²½μ°, μ¬μ©μλ ν° λ²€λ λ²λ€μ λ€μ λ€μ΄λ‘λν νμκ° μμ΅λλ€.
- μ ν리μΌμ΄μ λ²λ€ ν¬κΈ° κ°μ: λ²€λ μ½λλ₯Ό λΆλ¦¬νλ©΄ λ©μΈ μ ν리μΌμ΄μ λ²λ€μ΄ λ μμμ§κ³ λ‘λ μλκ° λΉ¨λΌμ§λλ€.
ꡬν: Webpack λ° Rollupκ³Ό κ°μ λ²λ€λ¬λ λ²€λ μ²ν¬ μ΅μ νλ₯Ό μν λ΄μ₯ κΈ°λ₯μ κ°μΆκ³ μμ΅λλ€. μΌλ°μ μΌλ‘ 'λ²€λ'λ‘ κ°μ£Όλλ λͺ¨λμ μλ³νμ¬ λ³λμ νμΌλ‘ λ²λ€λ§νλλ‘ κ΅¬μ±ν©λλ€.
μμ (Webpack):
Webpackμ μ΅μ ν μ€μ μ μλ λ²€λ μ€ν리ν μ μ¬μ©λ μ μμ΅λλ€:
// webpack.config.js
module.exports = {
// ... other config
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
μ΄ μ€μ μ Webpackμκ² node_modulesμ λͺ¨λ λͺ¨λμ λ³λμ vendors μ²ν¬μ λ£λλ‘ μ§μν©λλ€.
7. HTTP/2μ HTTP/3
μ μ: HTTP νλ‘ν μ½μ μ΅μ λ²μ (HTTP/2 λ° HTTP/3)μ HTTP/1.1μ λΉν΄ νΉν μ¬λ¬ κ°μ μμ νμΌμ λ‘λν λ μλΉν μ±λ₯ ν₯μμ μ 곡ν©λλ€. HTTP/2λ λ©ν°νλ μ±μ λμ νμ¬ λ¨μΌ TCP μ°κ²°μ ν΅ν΄ μ¬λ¬ μμ²κ³Ό μλ΅μ λμμ λ³΄λΌ μ μκ² νμ¬ μ€λ²ν€λλ₯Ό μ€μ λλ€.
μ₯μ :
- λ§μ μμ μμ²μ μ€λ²ν€λ κ°μ: HTTP/2λ₯Ό μ¬μ©νλ©΄ λ§μ μμ μλ°μ€ν¬λ¦½νΈ λͺ¨λ(μ: μ½λ μ€ν리ν μΌλ‘ μμ±λ)μ κ°μ§ λμ λΆμ΄μ΅μ΄ ν¬κ² μ€μ΄λλλ€.
- μ§μ° μκ° κ°μ : ν€λ μμΆ λ° μλ² νΈμμ κ°μ κΈ°λ₯μ λ‘λ© μλλ₯Ό λμ± ν₯μμν΅λλ€.
ꡬν: μΉ μλ²(μ: Nginx, Apache)μ νΈμ€ν μ 곡μ μ²΄κ° HTTP/2 λλ HTTP/3λ₯Ό μ§μνλμ§ νμΈνμΈμ. HTTP/3λ QUICμ μμ‘΄νλ©°, μ΄λ μ μΈκ³ λ§μ μ§μμμ νν μμ€μ΄ λ§μ λ€νΈμν¬μμ ν¨μ¬ λ λμ μ§μ° μκ°μ μ 곡ν μ μμ΅λλ€.
μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ‘λ©μ ν΅μ¬ μ±λ₯ λ©νΈλ¦
μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ‘λ©μ ν¨κ³Όμ μΌλ‘ μ΅μ ννλ €λ©΄ κ·Έ μν₯μ μΈ‘μ ν΄μΌ ν©λλ€. λ€μμ μΆμ ν΄μΌ ν νμ λ©νΈλ¦μ λλ€:
1. μ΅μ΄ μ½ν μΈ ν νμΈνΈ(First Contentful Paint, FCP)
μ μ: FCPλ νμ΄μ§ λ‘λ© μμλΆν° νμ΄μ§ μ½ν μΈ μ μΌλΆκ° νλ©΄μ λ λλ§λ λκΉμ§μ μκ°μ μΈ‘μ ν©λλ€. μ¬κΈ°μλ ν μ€νΈ, μ΄λ―Έμ§, μΊλ²μ€κ° ν¬ν¨λ©λλ€.
μ€μμ±: μ’μ FCPλ νμ΄μ§κ° μμ§ μμ ν μνΈμμ© κ°λ₯νμ§ μλλΌλ μ¬μ©μκ° κ°μΉ μλ μ½ν μΈ λ₯Ό λΉ λ₯΄κ² λ°κ³ μμμ λνλ λλ€. λλ¦° μλ°μ€ν¬λ¦½νΈ μ€νμ΄λ ν° μ΄κΈ° λ²λ€μ FCPλ₯Ό μ§μ°μν¬ μ μμ΅λλ€.
2. μνΈμμ©κΉμ§μ μκ°(Time to Interactive, TTI)
μ μ: TTIλ νμ΄μ§κ° μμ ν μνΈμμ© κ°λ₯ν΄μ§κΈ°κΉμ§ 걸리λ μκ°μ μΈ‘μ ν©λλ€. νμ΄μ§λ λ€μκ³Ό κ°μ κ²½μ°μ μνΈμμ© κ°λ₯ν κ²μΌλ‘ κ°μ£Όλ©λλ€:
- μ μ©ν μ½ν μΈ λ₯Ό λ λλ§νμ΅λλ€(FCP λ°μ).
- 50λ°λ¦¬μ΄ μ΄λ΄μ μ¬μ©μ μ λ ₯μ μμ μ μΌλ‘ μλ΅ν μ μμ΅λλ€.
- μ¬μ©μ μ λ ₯μ μ²λ¦¬νλλ‘ μ€λΉλμμ΅λλ€.
μ€μμ±: μ΄λ μ¬μ©μκ° μ ν리μΌμ΄μ κ³Ό μΌλ§λ 빨리 μνΈμμ©ν μ μλμ§μ μ§μ μ μΌλ‘ κ΄λ ¨λλ―λ‘ μ¬μ©μ κ²½νμ λ§€μ° μ€μν λ©νΈλ¦μ λλ€. μλ°μ€ν¬λ¦½νΈ νμ±, μ»΄νμΌ λ° μ€νμ΄ TTIμ μ£Όμ μμΈμ λλ€.
3. μ΄ μ°¨λ¨ μκ°(Total Blocking Time, TBT)
μ μ: TBTλ μ λ ₯ μλ΅μ±μ λ°©ν΄ν λ§νΌ μ€λ«λμ λ©μΈ μ€λ λκ° μ°¨λ¨λ μ΄ μκ°μ μΈ‘μ ν©λλ€. λ©μΈ μ€λ λλ μλ°μ€ν¬λ¦½νΈ νμ±, μ»΄νμΌ, μ€ν λ° κ°λΉμ§ 컬λ μ κ³Ό κ°μ μμ μ μν΄ μ°¨λ¨λ©λλ€.
μ€μμ±: λμ TBTλ κ΅Όλ¨κ³ λ°μμ΄ μλ μ¬μ©μ κ²½νκ³Ό μ§μ μ μΌλ‘ κ΄λ ¨μ΄ μμ΅λλ€. νΉν μ΄κΈ° λ‘λ μ€ μλ°μ€ν¬λ¦½νΈ μ€νμ μ΅μ ννλ κ²μ΄ TBTλ₯Ό μ€μ΄λ ν΅μ¬μ λλ€.
4. μ΅λ μ½ν μΈ ν νμΈνΈ(Largest Contentful Paint, LCP)
μ μ: LCPλ λ·°ν¬νΈ λ΄μμ κ°μ₯ ν° μ½ν μΈ μμκ° λ³΄μ΄κ² λ λκΉμ§μ μκ°μ μΈ‘μ ν©λλ€. μ΄λ μΌλ°μ μΌλ‘ μ΄λ―Έμ§, ν° ν μ€νΈ λΈλ‘ λλ λΉλμ€μ λλ€.
μ€μμ±: LCPλ νμ΄μ§μ μ£Όμ μ½ν μΈ κ° μΌλ§λ 빨리 μ¬μ© κ°λ₯νμ§λ₯Ό λνλ΄λ μ¬μ©μ μ€μ¬ λ©νΈλ¦μ λλ€. μ§μ μ μΈ μλ°μ€ν¬λ¦½νΈ λ‘λ© λ©νΈλ¦μ μλμ§λ§, μλ°μ€ν¬λ¦½νΈκ° LCP μμμ λ λλ§μ μ°¨λ¨νκ±°λ μ²λ¦¬λ₯Ό μ§μ°μν€λ©΄ LCPμ μν₯μ λ―ΈμΉ©λλ€.
5. λ²λ€ ν¬κΈ° λ° λ€νΈμν¬ μμ²
μ μ: μ΄λ μ¬μ©μμκ² μ μ‘λλ μλ°μ€ν¬λ¦½νΈμ μμν μκ³Ό λ€μ΄λ‘λλλ κ°λ³ νμΌμ μλ₯Ό λνλ΄λ κΈ°λ³Έμ μΈ λ©νΈλ¦μ λλ€.
μ€μμ±: λ μμ λ²λ€κ³Ό λ μ μ λ€νΈμν¬ μμ²μ μΌλ°μ μΌλ‘ λ λΉ λ₯Έ λ‘λ©μΌλ‘ μ΄μ΄μ§λ©°, νΉν λλ¦° λ€νΈμν¬λ μ§μ° μκ°μ΄ λμ μ§μμμ κ·Έλ μ΅λλ€. Webpack Bundle Analyzerμ κ°μ λꡬλ λ²λ€μ ꡬμ±μ μκ°ννλ λ° λμμ΄ λ μ μμ΅λλ€.
6. μ€ν¬λ¦½νΈ νκ° λ° μ€ν μκ°
μ μ: μ΄λ λΈλΌμ°μ κ° μλ°μ€ν¬λ¦½νΈ μ½λλ₯Ό νμ±, μ»΄νμΌ λ° μ€ννλ λ° μλΉνλ μκ°μ μλ―Έν©λλ€. μ΄λ λΈλΌμ°μ κ°λ°μ λꡬ(μ±λ₯ ν)μμ κ΄μ°°ν μ μμ΅λλ€.
μ€μμ±: λΉν¨μ¨μ μΈ μ½λ, λ¬΄κ±°μ΄ κ³μ° λλ νμ±ν μ½λμ μμ΄ λ§μΌλ©΄ λ©μΈ μ€λ λλ₯Ό μ μ νμ¬ TTI λ° TBTμ μν₯μ μ€ μ μμ΅λλ€. μκ³ λ¦¬μ¦μ μ΅μ ννκ³ μ΄κΈ°μ μ²λ¦¬λλ μ½λμ μμ μ€μ΄λ κ²μ΄ μ€μν©λλ€.
μ±λ₯ μΈ‘μ λ° λΆμ λꡬ
μ¬λ¬ λκ΅¬κ° μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ‘λ© μ±λ₯μ μΈ‘μ νκ³ μ§λ¨νλ λ° λμμ΄ λ μ μμ΅λλ€:
- Google PageSpeed Insights: Core Web Vitalsμ λν ν΅μ°°λ ₯μ μ 곡νκ³ μλ°μ€ν¬λ¦½νΈ μ΅μ νλ₯Ό ν¬ν¨ν μ±λ₯ κ°μ κΆμ₯ μ¬νμ μ 곡ν©λλ€.
- Lighthouse (Chrome DevTools λ΄): μΉ νμ΄μ§μ νμ§, μ±λ₯ λ° μ κ·Όμ±μ κ°μ νκΈ° μν μλνλ λꡬμ λλ€. νμ΄μ§λ₯Ό κ°μ¬νκ³ FCP, TTI, TBT, LCPμ κ°μ λ©νΈλ¦μ λν μμΈ λ³΄κ³ μμ ꡬ체μ μΈ κΆμ₯ μ¬νμ μ 곡ν©λλ€.
- WebPageTest: μ μΈκ³ μ¬λ¬ μμΉμ λ€μν λ€νΈμν¬ μ‘°κ±΄μμ μΉμ¬μ΄νΈ μλλ₯Ό ν μ€νΈν μ μλ λ¬΄λ£ λꡬμ λλ€. κΈλ‘λ² μ±λ₯μ μ΄ν΄νλ λ° νμμ μ λλ€.
- Webpack Bundle Analyzer: Webpack μΆλ ₯ νμΌμ ν¬κΈ°λ₯Ό μκ°ννκ³ κ·Έ λ΄μ©μ λΆμνμ¬ ν° μμ‘΄μ±μ μλ³νκ±°λ μ½λ μ€ν리ν κΈ°νλ₯Ό μ°Ύλ λ° λμμ΄ λλ νλ¬κ·ΈμΈμ λλ€.
- λΈλΌμ°μ κ°λ°μ λꡬ (μ±λ₯ ν): Chrome, Firefox, Edgeμ κ°μ λΈλΌμ°μ μ λ΄μ₯λ μ±λ₯ νλ‘νμΌλ¬λ μ€ν¬λ¦½νΈ μ€ν, λ λλ§ λ° λ€νΈμν¬ νλμ λν μμΈ λΆμμ λ§€μ° μ μ©ν©λλ€.
κΈλ‘λ² μλ°μ€ν¬λ¦½νΈ λͺ¨λ μ΅μ νλ₯Ό μν λͺ¨λ² μ¬λ‘
μ΄λ¬ν κΈ°λ²μ μ μ©νκ³ λ©νΈλ¦μ μ΄ν΄νλ κ²λ μ€μνμ§λ§, μ΅μ νκ° νλ₯ν κΈλ‘λ² κ²½νμΌλ‘ μ΄μ΄μ§λλ‘ λ³΄μ₯νλ λͺ κ°μ§ ν¬κ΄μ μΈ λͺ¨λ² μ¬λ‘κ° μμ΅λλ€:
- μ€μ μλ°μ€ν¬λ¦½νΈ μ°μ μμ μ§μ : μ΄κΈ° λ λλ§κ³Ό μ¬μ©μ μνΈμμ©μ νμν μλ°μ€ν¬λ¦½νΈλ₯Ό μλ³νμΈμ. μ΄ μ½λλ₯Ό κ°λ₯ν ν 빨리 λ‘λνκ³ , κ°μ₯ μ€μν λΆλΆμ μΈλΌμΈμΌλ‘ μ²λ¦¬νκ±°λ μμ μ§μ°λ λͺ¨λλ‘ λ‘λνλ κ²μ΄ μ΄μμ μ λλ€.
- μ€μνμ§ μμ μλ°μ€ν¬λ¦½νΈ μ§μ°: μ§μ° λ‘λ©, λμ μν¬νΈ, μ€ν¬λ¦½νΈ νκ·Έμ `defer` λλ `async` μμ±μ μ¬μ©νμ¬ νμν λλ§ λ€λ₯Έ λͺ¨λ κ²μ λ‘λνμΈμ.
- μλνν° μ€ν¬λ¦½νΈ μ΅μν: μΈλΆ μ€ν¬λ¦½νΈ(λΆμ, κ΄κ³ , μμ ―) μ¬μ©μ μ μ€νμΈμ. κ°κ°μ΄ λ‘λ μκ°μ μΆκ°λκ³ μ μ¬μ μΌλ‘ λ©μΈ μ€λ λλ₯Ό μ°¨λ¨ν μ μμ΅λλ€. λΉλκΈ°μ μΌλ‘ λ‘λνκ±°λ νμ΄μ§κ° μνΈμμ© κ°λ₯ν΄μ§ νμ λ‘λνλ κ²μ κ³ λ €νμΈμ.
- λͺ¨λ°μΌ μ°μ μ΅μ ν: μ μΈκ³μ μΌλ‘ λͺ¨λ°μΌ μΈν°λ· μ¬μ©μ΄ 보νΈνλ¨μ λ°λΌ, λͺ¨λ°μΌ μ¬μ©μμ λλ¦° λ€νΈμν¬λ₯Ό μΌλμ λκ³ μλ°μ€ν¬λ¦½νΈ λ‘λ© μ λ΅μ μ€κ³νκ³ μ΅μ ννμΈμ.
- μΊμ± ν¨κ³Όμ μΌλ‘ νμ©: μλ°μ€ν¬λ¦½νΈ μμ°μ λν΄ κ°λ ₯ν λΈλΌμ°μ μΊμ± μ λ΅μ ꡬννμΈμ. μΊμ λ²μ€ν κΈ°λ²(μ: νμΌ μ΄λ¦μ ν΄μ μΆκ°)μ μ¬μ©νλ©΄ μ½λκ° λ³κ²½λ λ μ¬μ©μκ° μ΅μ μ½λλ₯Ό λ°μ μ μλλ‘ λ³΄μ₯ν©λλ€.
- Brotli λλ Gzip μμΆ κ΅¬ν: μλ²κ° μλ°μ€ν¬λ¦½νΈ νμΌμ μμΆνλλ‘ κ΅¬μ±λμλμ§ νμΈνμΈμ. Brotliλ μΌλ°μ μΌλ‘ Gzipλ³΄λ€ λ λμ μμΆλ₯ μ μ 곡ν©λλ€.
- λͺ¨λν°λ§ λ° λ°λ³΅: μ±λ₯μ μΌνμ± μμ μ΄ μλλλ€. νΉν μλ‘μ΄ κΈ°λ₯μ΄λ μ λ°μ΄νΈλ₯Ό λ°°ν¬ν νμλ ν΅μ¬ λ©νΈλ¦μ μ§μμ μΌλ‘ λͺ¨λν°λ§νκ³ μ΅μ ν μ λ΅μ λ°λ³΅μ μΌλ‘ κ°μ νμΈμ. μ€μ μ¬μ©μ λͺ¨λν°λ§(RUM) λꡬλ₯Ό μ¬μ©νμ¬ λ€μν μ§μ λ° κΈ°κΈ°μμ μ¬μ©μμ κ΄μ μμ μ±λ₯μ μ΄ν΄νμΈμ.
- μ¬μ©μ 컨ν μ€νΈ κ³ λ €: μ μΈκ³ μ¬μ©μκ° μ¬μ©νλ λ€μν νκ²½μ μκ°νμΈμ. μ¬κΈ°μλ λ€νΈμν¬ μλ, κΈ°κΈ° μ±λ₯, μ¬μ§μ΄ λ°μ΄ν° λΉμ©λ ν¬ν¨λ©λλ€. μ½λ μ€ν리ν λ° μ§μ° λ‘λ©κ³Ό κ°μ μ λ΅μ μ΄λ¬ν λ§₯λ½μμ νΉν μ μ©ν©λλ€.
κ²°λ‘
μλ°μ€ν¬λ¦½νΈ λͺ¨λ λ‘λ© μ΅μ νλ μ μΈκ³ μ¬μ©μλ₯Ό μν κ³ μ±λ₯μ μ¬μ©μ μΉνμ μΈ μΉ μ ν리μΌμ΄μ μ ꡬμΆνλ λ° μμ΄μλ μ λ νμμ μΈ μΈ‘λ©΄μ λλ€. μ½λ μ€ν리ν , νΈλ¦¬ μμ΄νΉ, μ§μ° λ‘λ© λ° ν¨μ¨μ μΈ λ²€λ λ²λ€λ§κ³Ό κ°μ κΈ°λ²μ μ±νν¨μΌλ‘μ¨ λ‘λ μκ°μ λν λ¨μΆνκ³ μνΈμμ©μ±μ κ°μ νλ©° μ λ°μ μΈ μ¬μ©μ κ²½νμ ν₯μμν¬ μ μμ΅λλ€. FCP, TTI, TBTμ κ°μ μ€μν μ±λ₯ λ©νΈλ¦μ λν μ리ν μκ°κ³Ό κ°λ ₯ν λΆμ λꡬλ₯Ό νμ©νμ¬ κ°λ°μλ μμΉλ λ€νΈμν¬ μ‘°κ±΄μ κ΄κ³μμ΄ μ μΈκ³ μ¬μ©μμκ² λΉ λ₯΄κ³ μμ μ μ΄λ©° μ κ·Ό κ°λ₯ν μ ν리μΌμ΄μ μ 보μ₯ν μ μμ΅λλ€. μ§μμ μΈ μ±λ₯ λͺ¨λν°λ§κ³Ό λ°λ³΅μ λν μ½μμ μ§μ μΌλ‘ νμν κΈλ‘λ² μΉ μ‘΄μ¬κ°μ μν κΈΈμ μ΄μ΄μ€ κ²μ λλ€.