μλ°μ€ν¬λ¦½νΈμμ λΉλκΈ° νλ‘κ·Έλλ°μ λ§€μ° μ€μν κ°λ μ λλ€. νΉν, λ€νΈμν¬ μμ², νμΌ μ½κΈ°/μ°κΈ° λ± μκ°μ΄ μ€λ 걸리λ μμ μ μ²λ¦¬ν λ ν¨μ¨μ μ λλ€. μ΄λ² ν¬μ€ν μμλ μλ°μ€ν¬λ¦½νΈμμ Asyncμ λΉλκΈ° νλ‘κ·Έλλ°μ μ½κ² μ΄ν΄νκ³ νμ©ν μ μλλ‘ λμλλ¦¬κ² μ΅λλ€.
β£ λͺ©μ°¨
- μκ°π
- κΈ°λ³Έ κ°λ λ° ν€μλπ
- Async/Await κΈ°λ³Έ μ¬μ©λ²π οΈ
- μ€μ μ¬μ© μ¬λ‘π
- μλ¬ μ²λ¦¬ λ°©λ²π§
- μ΅μ ν λ° μ±λ₯ ν₯μ νπ
01. μκ°π
μλ°μ€ν¬λ¦½νΈλ λ¨μΌ μ€λ λ μΈμ΄λ‘, ν λ²μ νλμ μμ λ§ μ²λ¦¬ν μ μμ΅λλ€. κ·Έλ°λ° λ€νΈμν¬ μμ²μ΄λ νμΌ μ½κΈ°/μ°κΈ° κ°μ μμ μ μκ°μ΄ μ€λ 걸리기 λλ¬Έμ, μ΄λ° μμ μ ν λλ λ€λ₯Έ μμ μ λ©μΆμ§ μκ³ λμμ μ²λ¦¬ν μ μλλ‘ λΉλκΈ° νλ‘κ·Έλλ°μ΄ νμν©λλ€. Asyncλ μ΄λ° λΉλκΈ° νλ‘κ·Έλλ°μ μ½κ² ν μ μκ² λμμ€λλ€.
02. κΈ°λ³Έ κ°λ λ° ν€μλπ
μλ°μ€ν¬λ¦½νΈ λΉλκΈ° νλ‘κ·Έλλ°μ λκΈ°μ μΈ λ°©μμΌλ‘ μ²λ¦¬νκΈ° μ΄λ €μ΄ μμ μ ν¨μ¨μ μΌλ‘ μ²λ¦¬ν μ μκ² ν΄ μ€λλ€. μ΄λ νΉν I/O μμ , λ€νΈμν¬ μμ², νμ΄λ¨Έ λ± μκ°μ΄ 걸리λ μμ μμ μ μ©ν©λλ€. μλ°μ€ν¬λ¦½νΈμ λΉλκΈ° νλ‘κ·Έλλ°μ μ΄ν΄νκΈ° μν΄ μμμΌ ν κΈ°λ³Έ κ°λ λ° ν€μλλ λ€μκ³Ό κ°μ΅λλ€. μ½λ°± ν¨μλ λ€λ₯Έ ν¨μμ μΈμλ‘ μ λ¬λμ΄ νΉμ μμ μ΄ μλ£λ ν νΈμΆλλ ν¨μμ λλ€. λΉλκΈ° μμ μ κ²°κ³Όλ₯Ό μ²λ¦¬νκΈ° μν΄ μ¬μ©λ©λλ€.
1. μ½λ°± ν¨μ (Callback Function)
function fetchData(callback) {
setTimeout(() => {
callback('Data loaded');
}, 1000);
}
fetchData((data) => {
console.log(data); // 'Data loaded'
});
2. νλ‘λ―Έμ€ (Promise)
νλ‘λ―Έμ€λ λΉλκΈ° μμ μ μλ£ λλ μ€ν¨λ₯Ό λνλ΄λ κ°μ²΄μ λλ€. .then()κ³Ό .catch() λ©μλλ₯Ό μ¬μ©νμ¬ λΉλκΈ° μμ μ κ²°κ³Όλ₯Ό μ²λ¦¬ν μ μμ΅λλ€.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data loaded');
}, 1000);
});
promise.then((data) => {
console.log(data); // 'Data loaded'
}).catch((error) => {
console.error(error);
});
3. async/await
async ν¨μλ νλ‘λ―Έμ€λ₯Ό λ°ννλ©°, await ν€μλλ νλ‘λ―Έμ€κ° ν΄κ²°λ λκΉμ§ ν¨μ μ€νμ μΌμ μ€μ§ν©λλ€. μ΄λ₯Ό ν΅ν΄ λΉλκΈ° μ½λλ₯Ό λ μ½κΈ° μ½κ² μμ±ν μ μμ΅λλ€.
async function fetchData() {
const data = await new Promise((resolve) => {
setTimeout(() => {
resolve('Data loaded');
}, 1000);
});
console.log(data); // 'Data loaded'
}
fetchData();
4. μ΄λ²€νΈ 루ν (Event Loop)
μ΄λ²€νΈ 루νλ μλ°μ€ν¬λ¦½νΈ λ°νμμ΄ λΉλκΈ° μμ μ κ΄λ¦¬νκ³ μ€ν μμλ₯Ό μ μ΄νλ λ©μ»€λμ¦μ λλ€. μ΄λ²€νΈ 루νλ μ½ μ€ν(Call Stack), ν(Heap), νμ€ν¬ ν(Task Queue) λ±μ κ΅¬μ± μμλ₯Ό μ¬μ©νμ¬ λΉλκΈ° μμ μ μ²λ¦¬ν©λλ€.
μ£Όμ κ΅¬μ± μμ
1. μ½ μ€ν (Call Stack)
- ν¨μ νΈμΆμ΄ μμ΄λ κ³³μ λλ€.
- μλ°μ€ν¬λ¦½νΈ μμ§μ μ½ μ€νμ 맨 μμ μλ ν¨μλΆν° μ€νν©λλ€.
- ν¨μκ° μ€νμ λ§μΉλ©΄ μ€νμμ μ κ±°λ©λλ€.
2. ν (Heap)
- λμ μΌλ‘ μμ±λ κ°μ²΄λ€μ΄ μ μ₯λλ λ©λͺ¨λ¦¬ μμμ λλ€.
3. νμ€ν¬ ν (Task Queue)
- λΉλκΈ° μμ μ μ½λ°± ν¨μκ° λκΈ°νλ νμ λλ€.
- νμ΄λ¨Έ, λ€νΈμν¬ μμ², μ΄λ²€νΈ 리μ€λ λ± λΉλκΈ° μμ μ΄ μλ£λλ©΄ ν΄λΉ μ½λ°±μ΄ νμ€ν¬ νμ μΆκ°λ©λλ€.
4. λ§μ΄ν¬λ‘νμ€ν¬ ν (Microtask Queue)
- νλ‘λ―Έμ€μ .then() μ½λ°±κ³Ό κ°μ λ§μ΄ν¬λ‘νμ€ν¬λ€μ΄ λκΈ°νλ νμ λλ€.
- νμ€ν¬ νλ³΄λ€ μ°μ μμκ° λμ΅λλ€.
μ΄λ²€νΈ 루νμ λμ λ°©μ
μ΄λ²€νΈ 루νλ λ€μκ³Ό κ°μ λ¨κ³λ₯Ό λ°λ³΅νλ©΄μ λμν©λλ€:
1. μ½ μ€νμ μμ μ€ν
- μ½ μ€νμ΄ λΉμ΄ μμ§ μμ λμ μ€νμ 맨 μμ μλ μμ μ μ€νν©λλ€.
- ν¨μ νΈμΆμ΄ μλ£λλ©΄ μ½ μ€νμμ μ κ±°λ©λλ€.
2. λ§μ΄ν¬λ‘νμ€ν¬ μ²λ¦¬
- μ½ μ€νμ΄ λΉμ΄ μμ λ λ§μ΄ν¬λ‘νμ€ν¬ νμ λͺ¨λ μμ μ μ²λ¦¬ν©λλ€.
- μ΄λ κ° λ§μ΄ν¬λ‘νμ€ν¬λ μμλλ‘ μ€νλλ©°, λ§μ΄ν¬λ‘νμ€ν¬ νκ° λΉμ΄ μμ λκΉμ§ λ°λ³΅λ©λλ€.
3. νμ€ν¬ ν μ²λ¦¬
- μ½ μ€νκ³Ό λ§μ΄ν¬λ‘νμ€ν¬ νκ° λΉμ΄ μμΌλ©΄ νμ€ν¬ νμ μμ μ νλμ© μ½ μ€νμΌλ‘ μ΄λμμΌ μ€νν©λλ€.
μμ
μλλ μ΄λ²€νΈ 루νμ λμ λ°©μμ 보μ¬μ£Όλ κ°λ¨ν μμμ λλ€.
console.log('Start');
setTimeout(() => {
console.log('Timeout 1');
}, 0);
Promise.resolve().then(() => {
console.log('Promise 1');
});
setTimeout(() => {
console.log('Timeout 2');
}, 0);
Promise.resolve().then(() => {
console.log('Promise 2');
});
console.log('End');
μ μ½λλ₯Ό μ€ννλ©΄ λ€μκ³Ό κ°μ μμλ‘ μΆλ ₯λ©λλ€.
Start
End
Promise 1
Promise 2
Timeout 1
Timeout 2
μ΄μ
- μ½ μ€ν: console.log('Start')μ console.log('End')κ° μ½ μ€νμμ λ°λ‘ μ€νλ©λλ€.
- λ§μ΄ν¬λ‘νμ€ν¬ ν: Promise.resolve().then()μ μ½λ°±μ΄ λ§μ΄ν¬λ‘νμ€ν¬ νμ μΆκ°λ©λλ€.
- νμ€ν¬ ν: setTimeoutμ μ½λ°±μ΄ νμ€ν¬ νμ μΆκ°λ©λλ€.
- μ½ μ€νμ΄ λΉμ΄μμ λ λ§μ΄ν¬λ‘νμ€ν¬ νμ Promise μ½λ°±λ€μ΄ μ€νλ©λλ€.
- μ΄ν νμ€ν¬ νμ setTimeout μ½λ°±λ€μ΄ μ€νλ©λλ€.
μ΄μ κ°μ΄ μ΄λ²€νΈ 루νλ λΉλκΈ° μμ μ κ΄λ¦¬νκ³ μμ°¨μ μΌλ‘ μ€ννμ¬ μλ°μ€ν¬λ¦½νΈμ λμμ±μ ꡬνν©λλ€.
5. λ§μ΄ν¬λ‘νμ€ν¬μ 맀ν¬λ‘νμ€ν¬ (Microtasks and Macrotasks)
λΉλκΈ° μμ μ λ§μ΄ν¬λ‘νμ€ν¬ ν λλ 맀ν¬λ‘νμ€ν¬ νμ λ€μ΄κ°λλ€. Promiseμ. then()μ λ§μ΄ν¬λ‘νμ€ν¬λ‘ μ²λ¦¬λλ©°, setTimeoutκ³Ό κ°μ νμ΄λ¨Έ ν¨μλ 맀ν¬λ‘νμ€ν¬λ‘ μ²λ¦¬λ©λλ€.
console.log('Start');
setTimeout(() => {
console.log('Timeout');
}, 0);
Promise.resolve().then(() => {
console.log('Promise');
});
console.log('End');
μ μ½λμ μΆλ ₯μ Start, End, Promise, Timeout μμΌλ‘ λνλ©λλ€. μ΄λ λ§μ΄ν¬λ‘νμ€ν¬κ° 맀ν¬λ‘νμ€ν¬λ³΄λ€ λ¨Όμ μ€νλκΈ° λλ¬Έμ λλ€.
03. Async/Await κΈ°λ³Έ μ¬μ©λ²π οΈ
Async/Awaitλ Promise κΈ°λ°μ λΉλκΈ° μ½λλ₯Ό λ κ°λ¨νκ³ μ§κ΄μ μΌλ‘ μμ±ν μ μκ² ν΄ μ€λλ€. κΈ°λ³Έ λ¬Έλ²μ λ€μκ³Ό κ°μ΅λλ€.
async function fetchData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
- async: ν¨μ μμ λΆμ¬μ μ΄ ν¨μκ° λΉλκΈ° ν¨μλ₯Ό λνλ΄λλ‘ ν©λλ€.
- await: Promiseκ° ν΄κ²°λ λκΉμ§ ν¨μμ μ€νμ μΌμ μ€μ§ν©λλ€.
04. μ€μ μ¬μ© μ¬λ‘π
λΉλκΈ° νλ‘κ·Έλλ°μ μ£Όλ‘ API νΈμΆμ΄λ νμΌ μ½κΈ°/μ°κΈ° μμ μ μ¬μ©λ©λλ€. μλ₯Ό λ€μ΄, API νΈμΆμ ν΅ν΄ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ μ½λλ₯Ό λ³΄κ² μ΅λλ€.
async function getUserData() {
try {
let response = await fetch('https://api.example.com/user');
let user = await response.json();
console.log(user);
} catch (error) {
console.error('Failed to fetch user data:', error);
}
}
μ΄ μ½λμμ fetch ν¨μλ λ€νΈμν¬ μμ²μ 보λ΄κ³ , await ν€μλλ₯Ό μ¬μ©νμ¬ μλ΅μ΄ μ¬ λκΉμ§ κΈ°λ€λ¦½λλ€.
05. μλ¬ μ²λ¦¬ λ°©λ²π§
Async/Awaitλ₯Ό μ¬μ©ν λλ try/catch λΈλ‘μ μ¬μ©νμ¬ μλ¬λ₯Ό μ²λ¦¬ν μ μμ΅λλ€. μλ₯Ό λ€μ΄
async function fetchData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
μ΄λ κ² νλ©΄ fetch λλ response.json()μμ μλ¬κ° λ°μνμ λ catch λΈλ‘μμ μλ¬λ₯Ό μ²λ¦¬ν μ μμ΅λλ€.
06. μ΅μ ν λ° μ±λ₯ ν₯μ νπ
μλ°μ€ν¬λ¦½νΈμμ λΉλκΈ° ν¨μλ₯Ό μ΅μ ννκ³ μ±λ₯μ ν₯μμν€κΈ° μν μ¬λ¬ κ°μ§ λ°©λ²μ΄ μμ΅λλ€. μ΄λ€ λ°©λ²μ ν΅ν΄ λΉλκΈ° μμ μ ν¨μ¨μ±μ λμ΄κ³ , μ ν리μΌμ΄μ μ μ λ°μ μΈ μ±λ₯μ κ°μ ν μ μμ΅λλ€. λΉλκΈ° μμ μ λ³λ ¬λ‘ μ€ννλ©΄ μ±λ₯μ ν¬κ² ν₯μν μ μμ΅λλ€. μλ₯Ό λ€μ΄, Promise.allμ μ¬μ©νμ¬ μ¬λ¬ λΉλκΈ° μμ μ λμμ μ€ννκ³ , λͺ¨λ μμ μ΄ μλ£λ λκΉμ§ κΈ°λ€λ¦΄ μ μμ΅λλ€.
1. λ³λ ¬ μ²λ¦¬
λΉλκΈ° μμ μ λ³λ ¬λ‘ μ€ννλ©΄ μ±λ₯μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€. μλ₯Ό λ€μ΄, Promise.allμ μ¬μ©νμ¬ μ¬λ¬ λΉλκΈ° μμ μ λμμ μ€ννκ³ , λͺ¨λ μμ μ΄ μλ£λ λκΉμ§ κΈ°λ€λ¦΄ μ μμ΅λλ€.
async function fetchAllData(urls) {
const promises = urls.map(url => fetch(url).then(response => response.json()));
const results = await Promise.all(promises);
return results;
}
2. λ μ΄μ§ λ‘λ© (Lazy Loading)
νμν μμ μ λ°μ΄ν°λ₯Ό λΉλκΈ°μ μΌλ‘ λ‘λ©νλ λ μ΄μ§ λ‘λ©μ ν΅ν΄ μ΄κΈ° λ‘λ© μκ°μ μ€μΌ μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λΆνμν λ°μ΄ν°λ₯Ό 미리 λ‘λνμ§ μμμΌλ‘μ¨ μ±λ₯μ μ΅μ νν μ μμ΅λλ€.
function lazyLoadData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Data loaded');
}, 1000);
});
}
// μ¬μ©μκ° νΉμ λμμ μννμ λ λ°μ΄ν° λ‘λ
document.getElementById('loadButton').addEventListener('click', async () => {
const data = await lazyLoadData();
console.log(data);
});
3. μ°λ‘νλ§ λ° λλ°μ΄μ± (Throttling and Debouncing)
μμ£Ό νΈμΆλλ λΉλκΈ° μμ (μ: μ€ν¬λ‘€ μ΄λ²€νΈ, μ λ ₯ νλμ λ³κ²½ μ΄λ²€νΈ)μ μ΅μ ννκΈ° μν΄ μ°λ‘νλ§κ³Ό λλ°μ΄μ± κΈ°λ²μ μ¬μ©ν μ μμ΅λλ€.
- μ°λ‘νλ§ (Throttling): μΌμ μκ° κ°κ²©μΌλ‘λ§ ν¨μλ₯Ό μ€νν©λλ€.
- λλ°μ΄μ± (Debouncing): μΌμ μκ° λμ μ΄λ²€νΈκ° λ°μνμ§ μμ λ ν¨μλ₯Ό μ€νν©λλ€.
// λλ°μ΄μ€ ν¨μ
function debounce(func, delay) {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
}
// μ°λ‘ν ν¨μ
function throttle(func, delay) {
let lastCall = 0;
return (...args) => {
const now = new Date().getTime();
if (now - lastCall < delay) {
return;
}
lastCall = now;
func(...args);
};
}
// μμ: μ€ν¬λ‘€ μ΄λ²€νΈμ μ°λ‘ν μ μ©
window.addEventListener('scroll', throttle(() => {
console.log('Scrolled');
}, 200));
// μμ: μ
λ ₯ νλμ λλ°μ΄μ€ μ μ©
document.getElementById('inputField').addEventListener('input', debounce((event) => {
console.log('Input:', event.target.value);
}, 300));
4. μλΉμ€ μ컀 (Service Worker)
μλΉμ€ μ컀λ₯Ό μ¬μ©νμ¬ λ°±κ·ΈλΌμ΄λμμ λΉλκΈ° μμ μ μ²λ¦¬νκ³ , λ€νΈμν¬ μμ²μ μΊμ ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ€νΈμν¬ μμ²μ λΉλλ₯Ό μ€μ΄κ³ , μ€νλΌμΈμμλ μ±μ΄ λμν μ μκ² ν©λλ€.
// μλΉμ€ μ컀 λ±λ‘
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
5. ν¨μ¨μ μΈ λ°μ΄ν° νμΉ (Efficient Data Fetching)
λ°μ΄ν°λ₯Ό ν¨μ¨μ μΌλ‘ νμΉνμ¬ λ€νΈμν¬ μμ²μ μ΅μνν©λλ€. μλ₯Ό λ€μ΄, λ°μ΄ν°κ° μμ£Ό λ³κ²½λμ§ μλ κ²½μ°μλ μΊμ±μ νμ©νκ±°λ, μλ²λ‘λΆν° νμν λ°μ΄ν°λ§ νμΉ ν©λλ€.
// λ°μ΄ν° μΊμ± μμ
let cache = {};
async function fetchDataWithCache(url) {
if (cache[url]) {
return cache[url];
}
const response = await fetch(url);
const data = await response.json();
cache[url] = data;
return data;
}
6. μΉ μ컀 (Web Worker)
μΉ μ컀λ₯Ό μ¬μ©νμ¬ λ©μΈ μ€λ λμ λ³κ°λ‘ λ¬΄κ±°μ΄ μμ μ λΉλκΈ°μ μΌλ‘ μ²λ¦¬ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ©μΈ μ€λ λκ° λΈλ‘νΉλμ§ μκ³ , UIκ° λΆλλ½κ² λμν©λλ€.
// μΉ μ컀 νμΌ (worker.js)
self.addEventListener('message', event => {
const result = performHeavyComputation(event.data);
self.postMessage(result);
});
// λ©μΈ μ€ν¬λ¦½νΈ
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.addEventListener('message', event => {
console.log('Result from worker:', event.data);
});