코드로 우주평화

JavaScript _ 콜백 함수를 알아보자 본문

나는 이렇게 학습한다/Language

JavaScript _ 콜백 함수를 알아보자

daco2020 2023. 5. 9. 18:26
반응형

 

들어가며 

자바스크립트에서 비동기 프로그래밍의 기초 개념 중 하나인 콜백 함수에 대해 알아보자.

 

본 글에서는 콜백 함수의 개념부터 동기 콜백과 비동기 콜백의 차이, 콜백 지옥과 한계, 그리고 콜백 함수 작성 팁까지 다루겠다. 또한 콜백 함수의 대안으로 선호되는 프로미스와 async/await에 대해서도 간략하게 소개하겠다.

 

 

 

콜백 함수란?

콜백 함수란 다른 함수에 인자로 전달되어, 어떤 작업이 완료된 후에 실행되는 함수이다.

 

콜백 함수는 자바스크립트에서 흔히 사용되는 패턴으로, 특히 비동기 작업을 처리할 때 유용하다. 비동기 작업이란, 작업의 실행과 완료 시점이 일치하지 않는 작업을 말하는데, 예를 들어 서버에서 데이터를 가져오는 작업이나 타이머를 사용한 작업 등이 비동기로 이루어질 수 있다.

 


콜백 함수의 사용 예제

아래 예제 코드를 살펴보자. 이 예제에서는 setTimeout이라는 비동기 함수를 사용하여 1초 후에 콜백 함수를 실행한다.

 

function printMessage() {
  console.log('Hello, callback function!');
}

setTimeout(printMessage, 1000);
console.log('Waiting for the callback function...');

 

 

코드 실행 결과는 다음과 같다.

Waiting for the callback function...
Hello, callback function!


setTimeout 함수는 첫 번째 인자로 콜백 함수를, 두 번째 인자로 지연 시간(밀리초)을 받는다. 이 예제에서는 printMessage라는 콜백 함수가 setTimeout에 전달되었고, 1초 뒤에 실행된다.

 

이처럼 콜백 함수를 사용하면 비동기 작업을 구현할 수 있다.

 

 

 

동기 콜백과 비동기 콜백

콜백 함수는 동기적으로 실행되기도 하고 비동기적으로 실행되기도 한다. 동기 콜백은 함수가 호출되는 즉시 실행되는 반면, 비동기 콜백은 특정 조건이 충족되거나 이벤트가 발생한 후 실행된다.


예를 들어, 배열의 forEach 메서드에서 사용되는 콜백은 동기 콜백이다.

 

const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => console.log(num));
console.log('Done!');

 

1
2
3
4
5
Done!

 

위 예제에서는 forEach 메서드가 동기적으로 실행되기 때문에, 숫자가 출력된 후에 'Done!'이 출력된다.

*비동기 콜백 예제는 앞서 살펴본 setTimeout 함수를 들 수 있다.

 

 

 

콜백 지옥과 그 한계

비동기 작업이 중첩되어 여러 개의 콜백 함수를 사용하게 되면, 코드가 복잡하고 가독성이 떨어지는 문제가 발생할 수 있다. 이를 '콜백 지옥(callback hell)'이라고 한다.

 

setTimeout(() => {
  console.log('First callback');
  setTimeout(() => {
    console.log('Second callback');
    setTimeout(() => {
      console.log('Third callback');
    }, 1000);
  }, 1000);
}, 1000);

 

위 코드는 가독성이 좋지 않고, 유지 보수하기도 어렵다. 이러한 문제를 해결하기 위해 프로미스(Promise)와 async/await 같은 비동기 프로그래밍 기법이 도입되었는데 이는 나중에 다뤄보겠다.

 

 

 

콜백 함수 작성팁

콜백 함수를 작성할 때, 도움이 될만한 팁을 준비했다.

 


Tip. 명확한 함수명 사용

콜백 함수의 목적을 명확하게 알 수 있는 함수명을 사용하자. 예를 들어, 이벤트 처리나 결과에 따라 실행되는 함수의 경우 `onSuccess`나 `onError`와 같이 알기 쉬운 이름을 사용하면 좋다.

 


Tip. 코드 분리

콜백 함수를 외부에 정의하고 필요한 곳에서 호출하면 코드의 가독성과 유지 보수성을 높이는 데 도움이 된다.

 

 

Tip. 에러 처리
콜백 함수에서 발생할 수 있는 에러를 고려하고, 적절한 에러 처리를 제공하자. 에러 콜백을 제공하거나, try-catch 문을 사용하여 예외를 처리해 보자.

 

function fetchData(callback) {
  try {
    // 데이터를 가져오는 로직
    const data = { id: 1, name: 'John Doe' };
    callback(null, data);
  } catch (error) {
    callback(error);
  }
}

fetchData((error, data) => {
  if (error) {
    console.error('Error fetching data:', error);
  } else {
    console.log('Fetched data:', data);
  }
});

 

fetchData 함수가 콜백 함수를 호출할 때 에러가 발생하면 에러 객체를 전달하고, 정상적으로 데이터를 가져왔다면 에러 객체에 null을 전달하고 데이터를 함께 전달한다. 이렇게 하면 콜백 함수를 사용하는 쪽에서 에러를 적절히 처리할 수 있다!

 


Tip. 함수를 인자로 직접 전달

익명 함수를 사용하여 콜백 함수를 인자로 직접 전달할 수 있다. 이렇게 하면 코드를 더 간결하게 작성할 수 있지만 이 방법은 콜백 함수의 복잡도가 높아지면 가독성이 떨어질 수 있으므로 주의하자.

 

function greet(name, callback) {
  const message = `Hello, ${name}!`;
  callback(message);
}

// 함수를 인자로 직접 전달
greet('Alice', (message) => {
  console.log(message);
});

 

greet 함수는 이름을 입력받아 인사말을 생성한 후, 콜백 함수를 호출하여 메시지를 출력한다. 익명 화살표 함수`(message) => {console.log(message)}`를 greet 함수의 인자로 직접 전달했다. 

 


Tip. 화살표 함수 활용

화살표 함수(arrow function)를 사용하면 간결한 문법으로 콜백 함수를 작성할 수 있다.

 

function greet(name, callback) {
  const message = `Hello, ${name}!`;
  callback(message);
}

// 화살표 함수 활용
const displayMessage = (message) => {
  console.log(message);
};

greet('Bob', displayMessage);

 

화살표 함수를 사용하여 displayMessage라는 별도의 콜백 함수를 정의하고, 이를 greet 함수에 전달하여 가독성을 높였다.

 

 

 

마치며

이 글에서는 자바스크립트의 비동기 프로그래밍 기초 개념인 콜백 함수를 알아보았다.

 

암시적으로 함수를 호출하여 사용하지 않고 굳이 콜백 함수를 사용하는 이유는 단순히 비동기 프로그래밍만을 위함은 아니다. 콜백 함수를 인자로 전달하는 방식은 암시적으로 함수를 호출하는 방식에 비해 함수의 재사용성, 유연성, 테스트 용이성에서 도움이 된다. 함수를 인자로 전달하기 때문에 갈아끼기가 쉽고 수정이 용이하기 때문이다.

 

콜백 함수를 사용할 때 주의할 점은, 콜백 함수가 중첩되어 복잡한 코드 구조를 만드는 콜백 지옥(callback hell) 현상이 발생할 수 있다는 점이다. 

 

다음 글에서는 콜백 지옥의 대안 중 하나인 프로미스(Promise)를 알아보자.

 

 

 

반응형