λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
JavaScript

[JavaScript] μ½œλ°±ν•¨μˆ˜

by curious week 2024. 12. 20.

πŸ“Œ Callback ν•¨μˆ˜λž€?

πŸ‘‰ **콜백 ν•¨μˆ˜(callback function)**λŠ” λ‹€λ₯Έ ν•¨μˆ˜μ˜ 인자둜 μ „λ‹¬λ˜μ–΄ νŠΉμ • μ‘°κ±΄μ—μ„œ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

πŸ“Œ Callback ν•¨μˆ˜ 예제

function main(callback) {
  console.log('main μ‹€ν–‰');
  callback(); // μ „λ‹¬λœ ν•¨μˆ˜ μ‹€ν–‰
}

main(function () {
  console.log('βœ… 콜백 ν•¨μˆ˜ μ‹€ν–‰');
});

βœ” main() ν•¨μˆ˜λŠ” callback을 인자둜 λ°›μ•„ μ‹€ν–‰ν•©λ‹ˆλ‹€.
βœ” main()을 ν˜ΈμΆœν•  λ•Œ 읡λͺ… ν•¨μˆ˜λ₯Ό μ „λ‹¬ν•˜μ—¬ 콜백 ν•¨μˆ˜λ‘œ μ‹€ν–‰λ©λ‹ˆλ‹€.


πŸ“Œ 비동기 콜백 (Asynchronous Callback)

πŸ‘‰ 비동기 μž‘μ—…μ΄ μ™„λ£Œλœ 후에 μ‹€ν–‰λ˜λŠ” 콜백 ν•¨μˆ˜μž…λ‹ˆλ‹€.
πŸ‘‰ 비동기 μ½”λ“œλŠ” μ‹€ν–‰ μˆœμ„œκ°€ 보μž₯λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 콜백 ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄ μˆœμ„œλ₯Ό μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

❌ 비동기 처리 없이 μ‹€ν–‰

function getData() {
  setTimeout(() => {
    console.log('πŸ“‘ 데이터 κ°€μ Έμ˜€κΈ° μ™„λ£Œ');
  }, 1000);
}

getData();
console.log('πŸš€ ν›„μ²˜λ¦¬ μ‹€ν–‰'); // 데이터보닀 λ¨Όμ € 싀행됨

βœ” getData()λŠ” 1초 후에 μ‹€ν–‰λ˜μ§€λ§Œ,
βœ” console.log('πŸš€ ν›„μ²˜λ¦¬ μ‹€ν–‰')λŠ” μ¦‰μ‹œ μ‹€ν–‰λ˜λ―€λ‘œ 데이터보닀 λ¨Όμ € 좜λ ₯λ©λ‹ˆλ‹€.


πŸ“Œ 비동기 μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” 콜백

πŸ‘‰ μ½œλ°±μ„ ν™œμš©ν•˜λ©΄ 데이터λ₯Ό κ°€μ Έμ˜¨ ν›„ μ‹€ν–‰ν•  μž‘μ—…μ„ μ§€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

βœ… μ½œλ°±μ„ μ‚¬μš©ν•œ 비동기 μž‘μ—…

 function getData2(callback) {
  setTimeout(() => {
    console.log('πŸ“‘ 데이터 κ°€μ Έμ˜€κΈ° μ™„λ£Œ');
    callback({ data1: 'βœ… 데이터' }); // 데이터 처리 ν›„ 콜백 μ‹€ν–‰
  }, 1000);
}

getData2((data) => {
  console.log(data.data1); // 데이터 좜λ ₯
});

βœ” getData2()κ°€ μ™„λ£Œλœ ν›„ μ½œλ°±μ„ μ‹€ν–‰ν•˜μ—¬ 데이터λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€.
βœ” 이 방식은 비동기 μž‘μ—…μ΄ μˆœμ„œλŒ€λ‘œ μ‹€ν–‰λ˜λ„λ‘ 보μž₯ν•©λ‹ˆλ‹€.


🚨 콜백 μ§€μ˜₯ (Callback Hell)

πŸ‘‰ 콜백이 계속 μ€‘μ²©λ˜λ©΄ μ½”λ“œκ°€ 읽기 μ–΄λ ΅κ³  μœ μ§€λ³΄μˆ˜ν•˜κΈ° μ–΄λ €μ›Œμ§‘λ‹ˆλ‹€.
πŸ‘‰ 이λ₯Ό **콜백 μ§€μ˜₯(Callback Hell)**이라고 ν•©λ‹ˆλ‹€.

❌ 콜백 μ§€μ˜₯ 예제

function step1(callback) {
  setTimeout(() => {
    console.log('πŸ“Œ Step 1 μ™„λ£Œ');
    callback();
  }, 1000);
}

function step2(callback) {
  setTimeout(() => {
    console.log('πŸ“Œ Step 2 μ™„λ£Œ');
    callback();
  }, 1000);
}

function step3(callback) {
  setTimeout(() => {
    console.log('πŸ“Œ Step 3 μ™„λ£Œ');
    callback();
  }, 1000);
}

// 콜백 μ§€μ˜₯ λ°œμƒ
step1(() => {
  step2(() => {
    step3(() => {
      console.log('πŸŽ‰ λͺ¨λ“  μž‘μ—… μ™„λ£Œ');
    });
  });
});

βœ” λ“€μ—¬μ“°κΈ°κ°€ κΉŠμ–΄μ§€κ³ , μ½”λ“œκ°€ λ³΅μž‘ν•΄μ Έμ„œ 가독성이 λ–¨μ–΄μ§‘λ‹ˆλ‹€.
βœ” μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Promiseλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.


πŸš€ 콜백 μ§€μ˜₯ ν•΄κ²°: Promise μ‚¬μš©

πŸ‘‰ Promiseλ₯Ό μ‚¬μš©ν•˜λ©΄ 가독성을 높이고 비동기 처리λ₯Ό 순차적으둜 μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

function step1() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('πŸ“Œ Step 1 μ™„λ£Œ');
      resolve();
    }, 1000);
  });
}

function step2() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('πŸ“Œ Step 2 μ™„λ£Œ');
      resolve();
    }, 1000);
  });
}

function step3() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('πŸ“Œ Step 3 μ™„λ£Œ');
      resolve();
    }, 1000);
  });
}

// Promise 체이닝을 ν™œμš©ν•œ 비동기 처리
step1()
  .then(step2)
  .then(step3)
  .then(() => {
    console.log('πŸŽ‰ λͺ¨λ“  μž‘μ—… μ™„λ£Œ');
  });

βœ” .then() 체이닝을 μ‚¬μš©ν•˜λ©΄ 콜백 μ§€μ˜₯ 없이 비동기 처리λ₯Ό 순차적으둜 μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
βœ” μ½”λ“œκ°€ κ°„κ²°ν•˜κ³  가독성이 μ’‹μ•„μ§‘λ‹ˆλ‹€.


πŸš€ μ΅œμ‹  방식: async / await

πŸ‘‰ async / awaitλ₯Ό μ‚¬μš©ν•˜λ©΄ 더 직관적인 μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

async function processSteps() {
  await step1();
  await step2();
  await step3();
  console.log('πŸŽ‰ λͺ¨λ“  μž‘μ—… μ™„λ£Œ');
}

processSteps();

βœ” await을 μ‚¬μš©ν•˜λ©΄ 마치 동기 μ½”λ“œμ²˜λŸΌ 비동기 μž‘μ—…μ„ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
βœ” async ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ await을 μ‚¬μš©ν•˜λ©΄ μ½”λ“œμ˜ 흐름이 직관적이 λ©λ‹ˆλ‹€.


πŸ“Œ 정리

  • 콜백 ν•¨μˆ˜ → λ‹€λ₯Έ ν•¨μˆ˜μ˜ 인자둜 μ „λ‹¬λ˜μ–΄ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜
  • 비동기 콜백 → 비동기 μž‘μ—…μ΄ μ™„λ£Œλœ ν›„ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜
  • 콜백 μ§€μ˜₯ → 콜백이 μ€‘μ²©λ˜μ–΄ μ½”λ“œκ°€ λ³΅μž‘ν•΄μ§€λŠ” ν˜„μƒ
  • Promise → 콜백 μ§€μ˜₯을 ν•΄κ²°ν•˜κΈ° μœ„ν•œ 객체 (.then() 체이닝)
  • async / await → Promiseλ₯Ό 더 μ‰½κ²Œ μ‚¬μš©ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” μ΅œμ‹  문법

πŸ“’ μ½œλ°±λ³΄λ‹€ Promise λ˜λŠ” async/await을 ν™œμš©ν•˜λ©΄ μ½”λ“œκ°€ 더 읽기 쉽고 μœ μ§€λ³΄μˆ˜κ°€ νŽΈλ¦¬ν•©λ‹ˆλ‹€! πŸš€


// callback ν•¨μˆ˜: λ‹€λ₯Έ ν•¨μˆ˜μ˜ 인자둜 μ „λ‹¬λ˜λŠ” ν•¨μˆ˜
function main(callback) {
  callback();
}
// main에 인자둜 μ „λ‹¬λ˜λŠ” ν•¨μˆ˜κ°€ callback ν•¨μˆ˜λ‹€.
main(function () {});
main(() => {});

// 비동기 콜백: λΉ„λ™κΈ°μ˜ 경우 μ½”λ“œμ˜ μ‹€ν–‰ μˆœμ„œκ°€ λ’€μ£½λ°•μ£½ 될 수 μžˆμœΌλ―€λ‘œ 비동기 μ½œλ°±μ„ μ‚¬μš©ν•΄μ„œ
// μ°¨λ‘€λŒ€λ‘œ λ‹€μŒ ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λ„λ‘ν•œλ‹€.
// μ„œλ²„ -> λΉ„λ™κΈ°μž‘μ—… -> λ‹€μŒμž‘μ—… -> ν›„μ²˜λ¦¬
function getData() {
  setTimeout(() => {
    console.log('data');
  }, 1000);
}
getData();
console.log('ν›„μ²˜λ¦¬');
// μœ„μ˜ 경우 데이터λ₯Ό λ°›μ•„μ˜€κΈ° 전에 λ‹€μŒ μž‘μ—…μ„ μ‹€ν–‰ν•˜κ²Œ λœλ‹€.

function getData2(callback) {
  setTimeout(() => {
    console.log('data');
    callback({ data1: 'data' });
  }, 1000);
}
getData2((data) => {
  console.log(data.data1);
});
// μœ„μ˜ 경우 getData2μ—μ„œ dataλ₯Ό ν‘œμ‹œν•œ ν›„ data1 객체λ₯Ό λ°›μ•„μ˜€κ³  data1의 값을 ν‘œμ‹œν•œλ‹€.
// μœ„ 같은 κ²½μš°κ°€ 반볡되면 콜백 μ§€μ˜₯에 λΉ μ§€κ²Œ λœλ‹€. μ΄λ•Œ promiseλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.​

'JavaScript' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[JavaScript] ꡬ쑰 λΆ„ν•΄ ν• λ‹Ή  (4) 2024.12.22
[JavaScript] Reduce  (5) 2024.12.22
[JavaScript] async & await  (6) 2024.12.20
[JavaScript] Fetch, AJAX, Axios  (2) 2024.12.20
[JavaScript] Promise  (0) 2024.12.20