본문 바로가기
JavaScript

[JS] Callback

by goblin- 2024. 9. 8.

1. 자바스크립트의 콜백(Callback) 함수

 

콜백 함수는 자바스크립트에서 매우 중요한 개념 중 하나입니다. 기본적으로 콜백 함수다른 함수의 인자로 전달되어 그 함수가 실행된 이후에 호출되는 함수를 의미합니다. 자바스크립트는 비동기 처리가 필요한 작업(예: 데이터베이스 호출, 파일 읽기, HTTP 요청 등)에서 주로 콜백을 사용하여 해당 작업이 완료된 후 어떤 동작을 수행할지 정의합니다.

 

1.1 콜백 함수의 특징

 

비동기 작업에서 주로 사용되지만, 동기 작업에서도 사용될 수 있습니다.

콜백 함수는 나중에 호출될 함수를 인자로 받는 패턴으로, 특정 작업이 완료되면 해당 함수가 호출됩니다.

콜백 패턴은 자바스크립트의 이벤트 기반 구조와 비동기 처리에서 매우 자주 사용됩니다.

 

1.2 콜백 함수 예시

 

1. 동기 콜백 예시: 동기 작업에서의 콜백 함수는 작업이 즉시 완료되며, 함수가 순차적으로 실행됩니다.

function greeting(name) {
  console.log(`Hello, ${name}`);
}

function processUserInput(callback) {
  const name = "Alice";
  callback(name);  // 콜백 함수 호출
}

processUserInput(greeting);  // "Hello, Alice"

 

2. 비동기 콜백 예시: 비동기 작업에서의 콜백 함수는 시간이 걸리는 작업(예: HTTP 요청) 이후에 실행됩니다.

function fetchData(callback) {
  setTimeout(() => {
    console.log("Data fetched!");
    callback();  // 콜백 함수 실행
  }, 2000);  // 2초 후 데이터 가져오기를 완료
}

fetchData(() => {
  console.log("Processing fetched data...");
});

// 출력:
// "Data fetched!" (2초 후)
// "Processing fetched data..."

 

위 코드에서 fetchData 함수는 setTimeout을 사용해 비동기 작업을 시뮬레이션하고, 작업이 끝난 후 콜백 함수가 실행됩니다.

 

 

2. 콜백 헬(Callback Hell)

 

**콜백 헬(Callback Hell)**은 비동기 작업을 처리할 때 중첩된 콜백 함수들로 인해 코드의 가독성이 떨어지고, 유지보수가 어려워지는 상황을 일컫는 용어입니다. 콜백 함수가 여러 번 중첩되면 코드가 계단 형태로 깊이 들어가게 되어, 코드의 흐름을 이해하고 관리하기가 어려워집니다.

 

2.1 콜백 헬의 원인

 

콜백 헬은 비동기 작업이 연속적으로 실행되어야 할 때 발생합니다. 즉, 첫 번째 작업이 완료된 후 두 번째 작업이 시작되고, 두 번째 작업이 완료된 후 세 번째 작업이 시작되는 연쇄적인 비동기 작업을 처리할 때 콜백 함수들이 여러 번 중첩되는 방식으로 작성되기 때문에 코드가 복잡해집니다.

 

2.2 콜백 헬의 예시

 

아래는 콜백 헬의 대표적인 예시입니다. 여러 비동기 작업이 순차적으로 실행되면서 코드가 중첩됩니다.

function fetchData(url, callback) {
  setTimeout(() => {
    console.log(`Fetched data from ${url}`);
    callback();
  }, 1000);
}

fetchData('url1', () => {
  fetchData('url2', () => {
    fetchData('url3', () => {
      fetchData('url4', () => {
        console.log('All data fetched');
      });
    });
  });
});

 

위 코드를 보면 각 작업이 완료될 때마다 다음 비동기 작업이 중첩된 콜백 안에서 호출됩니다. 이런 구조는 코드를 수정하거나 확장하기 어려워질 뿐만 아니라, 오류 처리가 복잡해지고 유지보수가 매우 어려워집니다. 또한, 이 방식으로 작성된 코드는 콜백 피라미드크리스마스트리라고 불리기도 합니다.

 

3. 콜백 헬의 해결책

 

콜백 헬을 해결하기 위해 여러 방법이 고안되었습니다. 그중 가장 대표적인 해결책은 프로미스(Promise), **async/await**입니다. 이들은 콜백 함수의 중첩을 줄이고, 비동기 코드를 동기적인 방식으로 작성할 수 있게 해줍니다.

 

3.1 프로미스(Promise) 사용

 

프로미스는 비동기 작업의 성공(이행) 또는 실패(거부)를 처리하는 객체입니다. 프로미스를 사용하면 비동기 작업이 완료되었을 때 then() 메서드를 사용해 콜백을 연결할 수 있습니다.

 

프로미스 예시:

function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`Fetched data from ${url}`);
      resolve();
    }, 1000);
  });
}

fetchData('url1')
  .then(() => fetchData('url2'))
  .then(() => fetchData('url3'))
  .then(() => fetchData('url4'))
  .then(() => {
    console.log('All data fetched');
  });

 

위 코드에서는 Promise 객체를 반환하여 then() 체인을 사용해 비동기 작업을 순차적으로 처리합니다. 콜백 헬에 비해 가독성이 훨씬 좋아졌고, 흐름을 쉽게 파악할 수 있습니다.

 

3.2 async/await 사용

 

**async/await**는 ES8에서 도입된 기능으로, 프로미스를 더 간결하고 동기적인 코드 스타일로 작성할 수 있게 도와줍니다. async 함수는 항상 프로미스를 반환하며, 함수 내부에서 await 키워드를 사용해 프로미스가 완료될 때까지 기다릴 수 있습니다.

 

async/await 예시:

function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`Fetched data from ${url}`);
      resolve();
    }, 1000);
  });
}

async function fetchAllData() {
  await fetchData('url1');
  await fetchData('url2');
  await fetchData('url3');
  await fetchData('url4');
  console.log('All data fetched');
}

fetchAllData();

위 예시에서 async/await를 사용하면 코드의 흐름이 마치 동기 함수처럼 간결해집니다. 이 방식은 콜백 헬을 방지하고 비동기 코드를 읽기 쉽고, 유지보수하기 좋은 방식으로 작성할 수 있게 도와줍니다.

 

4. 콜백, 프로미스, async/await 비교

 

콜백: 비동기 작업 완료 후 실행될 함수를 전달하는 기본적인 방식. 중첩이 많아질 경우 콜백 헬 발생.

프로미스: 콜백 헬을 방지하고, then() 체인으로 비동기 작업을 순차적으로 처리 가능.

async/await: 프로미스를 기반으로 한 구문으로, 비동기 작업을 마치 동기 코드처럼 작성할 수 있음. 가독성과 유지보수성이 가장 뛰어남.

 

결론

 

콜백 함수는 자바스크립트의 핵심 개념으로, 비동기 작업에서 필수적인 기능입니다. 하지만 여러 비동기 작업을 처리할 때 콜백 헬 문제가 발생할 수 있으며, 이를 해결하기 위해 프로미스async/await 같은 구조가 도입되었습니다. 이들은 코드의 가독성유지보수성을 크게 개선해주며, 비동기 처리를 보다 쉽게 관리할 수 있게 해줍니다.

'JavaScript' 카테고리의 다른 글

[JS] Promise  (0) 2024.09.08
[JS] 자바스크립트의 동작방식(비동기,동기)  (0) 2024.09.08
[JS] 함수와 클래스(this)  (0) 2024.09.08
[JS] Scope  (0) 2024.09.08
[JS] Execution context  (0) 2024.09.08