프론트엔드 개발자 - 자곰

Front-end/Javascript

Callback

자곰 2023. 8. 1. 06:44

콜백이란?

자바스크립트에서는 함수는 객체입니다.( 매우 중요한 사실) 함수의 파라미터로서 객체를 전달할 수 있을까요? 네, 할 수 있습니다.

다른 함수에 인수로 전달되는 함수입니다. ( 일급 함수 )

예를 들어, map의 경우 각 반복에 대해 동기적으로 호출 되는 콜백 함수를 사용합니다.

const map = (arr, callback) => {
  const result = []
  for (let i = 0; i < arr.length; i++) {
    result.push(callback(arr[i], i))
  }
  return result
}
map([1, 2, 3, 4, 5], n => n * 2) // [2, 4, 6, 8, 10]

JS는 코드를 위에서 아래로 순차적으로 실행합니다. 그러나 코드가 다른 행위 후에 실행 될수도 있고, 순차적으로 실행되지 않을수도 있습니다.(비동기 프로그래밍이라고 하는 것)

콜백은 비동기 자바스크립트 코드를 작성할 수 있도록 해주고 여러 문제와 에러들로부터 안전하게 지켜줍니다.

콜백함수의 사용처

대표적으로 몇가지 사용처를 적어보겠습니다.

1. 비동기 작업 처리

function fetchDataFromServer(callback) {
  // 서버에서 데이터를 비동기적으로 가져오는 작업을 수행
  // 작업이 완료되면 콜백 함수를 호출하고 데이터를 전달
  const data = ...; // 비동기 작업을 통해 가져온 데이터
  callback(data);
}

// 콜백 함수를 활용하여 비동기 작업의 결과를 처리
fetchDataFromServer(function(data) {
  console.log(data);
});

2. 이벤트 처리

const button = document.getElementById('myButton');

function handleButtonClick(event) {
  console.log('Button clicked!');
}

// 버튼 클릭 이벤트에 콜백 함수를 등록하여 이벤트 처리
button.addEventListener('click', handleButtonClick);

3. 비동기 호출

function calculateAsync(a, b, callback) {
  // 비동기적으로 계산을 수행하고 결과를 콜백 함수에 전달
  setTimeout(function() {
    const result = a + b;
    callback(result);
  }, 1000); // 1초 후에 결과를 전달
}

// 콜백 함수를 사용하여 비동기 호출의 결과 처리
calculateAsync(2, 3, function(result) {
  console.log('Result:', result); // 5
});

4. 고차 함수

// 예시 : 배열의 각 요소를 두 배로 곱해서 새로운 배열을 생성하는 콜백 함수 
let numbers = [1, 2, 3, 4, 5]; // 배열 선언 
let doubled = []; // 빈 배열 선언 

// numbers 배열의 각 요소에 대해 콜백 함수 실행 
numbers.forEach(function (num) { 
    doubled.push(num * 2); // 콜백 함수로 각 요소를 두 배로 곱해서 doubled 배열에 추가 
}); 

console.log(doubled); // [2, 4, 6, 8, 10]

 

콜백 속 콜백

콜백만 쓰다 보면 끝없이 중첩이 될 수 가 있습니다. 이런걸 콜백 지옥이라고 합니다.

콜백지옥

콜백 동작이 하나씩 추가 될때마다 중첩 호출이 만들어내는 코드들은 금방 보기 싫어지고 알아보기 힘들어집니다.

각 동작을 독립적인 함수로 만들어 위와 같은 문제를 완화해 보도록 합시다

loadScript('1.js', step1);

function step1(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', step2);
  }
}

function step2(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('3.js', step3);
  }
}

function step3(error, script) {
  if (error) {
    handleError(error);
  } else {
    // 모든 스크립트가 로딩되면 다른 동작을 수행합니다. (*)
  }
};

이와 같이 단계적으로 함수를 호출하면 중첩은 없어지지만 코드가 찢겨서 읽기가 힘듭니다. 또한 재사용이 불가능합니다. 연쇄 동작이 이뤄지는 코드는 재사용을 하지 않을겁니다. 문제 투성이네요??

이를 해결하기 위해 Promise가 필요해집니다. 다음 챕터에서 다루어 보겠습니다.

'Front-end > Javascript' 카테고리의 다른 글

Promise API  (0) 2023.08.03
Promise(2) - 프라미스 체이닝  (0) 2023.08.02
이벤트 위임  (0) 2023.07.28
이벤트 버블링과 이벤트 캡처링  (0) 2023.07.26
자바스크립트 엔진  (0) 2023.07.23