λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Language/Javascript

[Javascript]μžλ°”μŠ€ν¬λ¦½νŠΈ Async μ™„λ²½ κ°€μ΄λ“œ: 비동기 ν”„λ‘œκ·Έλž˜λ°μ˜ λͺ¨λ“  것

by YJ Dev 2024. 7. 9.
728x90
λ°˜μ‘ν˜•
SMALL

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 비동기 ν”„λ‘œκ·Έλž˜λ°μ€ 맀우 μ€‘μš”ν•œ κ°œλ…μž…λ‹ˆλ‹€. 특히, λ„€νŠΈμ›Œν¬ μš”μ²­, 파일 읽기/μ“°κΈ° λ“± μ‹œκ°„μ΄ 였래 κ±Έλ¦¬λŠ” μž‘μ—…μ„ μ²˜λ¦¬ν•  λ•Œ νš¨μœ¨μ μž…λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ Async와 비동기 ν”„λ‘œκ·Έλž˜λ°μ„ μ‰½κ²Œ μ΄ν•΄ν•˜κ³  ν™œμš©ν•  수 μžˆλ„λ‘ λ„μ™€λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈ 비동기 ν”„λ‘œκ·Έλž˜λ°


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

이유

  1. 콜 μŠ€νƒ: console.log('Start')와 console.log('End')κ°€ 콜 μŠ€νƒμ—μ„œ λ°”λ‘œ μ‹€ν–‰λ©λ‹ˆλ‹€.
  2. λ§ˆμ΄ν¬λ‘œνƒœμŠ€ν¬ 큐: Promise.resolve().then()의 콜백이 λ§ˆμ΄ν¬λ‘œνƒœμŠ€ν¬ 큐에 μΆ”κ°€λ©λ‹ˆλ‹€.
  3. νƒœμŠ€ν¬ 큐: setTimeout의 콜백이 νƒœμŠ€ν¬ 큐에 μΆ”κ°€λ©λ‹ˆλ‹€.
  4. 콜 μŠ€νƒμ΄ λΉ„μ–΄μžˆμ„ λ•Œ λ§ˆμ΄ν¬λ‘œνƒœμŠ€ν¬ 큐의 Promise μ½œλ°±λ“€μ΄ μ‹€ν–‰λ©λ‹ˆλ‹€.
  5. 이후 νƒœμŠ€ν¬ 큐의 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);
});
728x90
λ°˜μ‘ν˜•