[JavaScript] 콜백 함수

신재욱·2023년 3월 9일
0
post-thumbnail

📒 오늘 공부한 내용

🔍수업목차

✅ 콜백 함수란?


콜백 함수 : 다른 코드의 인자로 넘겨주는 함수

콜백 함수를 사용하는 것은 알람시계를 세팅하는 것과 같다.
시계의 알람을 설정하는 함수를 호출했고, 해당 함수는 호출 당시에는 아무것도 하지 않다가 B가 정해준 시각이 됐을 때 비로소 '알람을 울리는' 결과를 반환한다.
즉 시계 함수에게 요청을 하면서 알람을 울리는 명령에 대한 제어권을 시계에게 넘겨준 것이다.
콜백 함수는 제어권과 관련이 깊다.

이처럼 콜백 함수는 다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수다. 콜백 함수를 위임받은 코드는 자체적인 내부 로직에 의해 이 콜백 함수를 적절한 시점에 실행할 것이다.

✅ 제어권


⏩ 콜백 함수 예제 1

let count =1;
let cbFunc = function (){
  console.log(count);
  if(++count > 5) clearInterval(timer);
};
let timer = setInterval(cbFunc, 1000);
// -- 실행 결과 --
// 1
// 2
// 3
// 4
// 5
  • timer 변수에는 setInterval의 ID 값이 담긴다.
  • setInterval에 전달한 첫 번째 인자인 cbFunc 함수는 1초마다 자동으로 실행될 것이다.
  • 콜백 함수 내부에서는 count 값을 출력하고, count를 1만큼 증가시킨 다음, 그 값이 4보다 크면 반복 실행을 종료한다.

이처럼 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점에 대한 제어권을 가진다.

✅ 인자


⏩ 콜백 함수 예제 2

let newArr = [10, 20, 30].map(function(currentValue, index){
  console.log(currentValue, index);
  return currentValue + 5;
});
console.log(newArr);

// -- 실행 결과 --
// 10 0
// 20 1
// 30 2
// [ 15, 25, 35 ]
  • map 메서드는 첫 번째 인자로 callback 함수를 받고, 생략 가능한 두 번째 인자로 콜백 함수 내부에서 this로 인식할 대상을 특정할 수 있다.
  • map 메서드는 메서드의 대상이 되는 배열의 모든 요소들을 처음부터 끝까지 하나씩 꺼내어 콜백 함수를 반복 호출하고, 콜백 함수의 실행 결과들을 모아 새로운 배열을 만든다.

⏩ 콜백 함수 예제 3

let newArr2 = [10, 20, 30].map(function(index, currentValue){
  console.log(index, currentValue);
  return currentValue + 5;
});
console.log(newArr2);

// -- 실행 결과 --
// 10 0
// 20 1
// 30 2
// [ 5, 6, 7 ]
  • index, currentValue 순서를 바꾸더라도 각 단어의 의미가 바뀌지 않으니까 문제 없을 것이라고 생각하기 쉽지만, 저 단어들은 사용자가 명명한 것일 뿐이다.
  • 컴퓨터는 그저 첫 번째, 두 번째의 순서에 의해서만 각각을 구분하고 인식한다.

✅ 콜백 함수는 함수다


⏩ 메서드를 콜백 함수로 전달한 경우

let obj = {
  vals : [1, 2, 3],
  logValues : function(v, i) {
    console.log(this, v, i);
  }
};

obj.logValues(1,2);
[4, 5, 6].forEach(obj.logValues);
// -- 실행 결과 --
//{ vals: [ 1, 2, 3 ], logValues: ƒ logValues() } 1 2
//Window {...} 4 0
  • obj.logValues(1,2); : thisobj를 가리키고, 인자로 넘어온 1, 2가 출력된다.
  • [4, 5, 6].forEach(obj.logValues); : forEach에 의해 콜백이 함수로서 호출되고 , 별도로 this를 지정하는 인자를 지정하지 않았으므로 함수 내부에서의 this는 전연객체를 바라보게 된다.
  • 어떤 함수의 인자에 객체의 메서드를 전당하더라도 이는 결국 메서드가 아닌 함수일 뿐이다.

✅ 콜백 지옥과 비동기 제어


동기적인 코드는 현재 실행 중인 코드가 완료된 후에야 다음 코드를 실행하는 방식이다. 반대로 비동기적인 코드는 현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어간다. CPU의 계산에 의해 즉시 처리가 가능한 대부분의 코드는 동기적인 코드다. 반명 사용자의 요청에 의해 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 `비동기적인 코드다.

웹의 복잡도가 높아진 만큼 비동기적인 코드의 비중이 예전보다 훨씬 높아진 상황이다. 그와 동시에 콜백 지옥에 빠지기도 훨씬 쉬워졌다.

⏩ 콜백 지옥

setTimeout(function (name) {
           let coffeeList = name;
           console.log(coffeeList);

setTimeout(function (name) {
            coffeeList += ', '+name;
           console.log(coffeeList);

setTimeout(function (name) {
            coffeeList += ', '+name;
           console.log(coffeeList);

setTimeout(function (name) {
            coffeeList += ', '+name;
           console.log(coffeeList);
           }, 500, '카페라떼');
          }, 500, '카페모카');
      }, 500, '아메리카노');
}, 500, '에스프레소');
// -- 실행 결과 --

//'에스프레소'
//'에스프레소, 아메리카노'
//'에스프레소, 아메리카노, 카페모카'
//'에스프레소, 아메리카노, 카페모카, 카페라떼'

⏩ 비동기 작업의 동기적 표현

new Promise(function (resolve) {
            setTimeout(function(){
  var name = '에스프레소';
  console.log(name);
              resolve(name);
            },500);
}).then(function(prevName) {
  return new Promise(function (resolve) {
    setTimeout(function(){
  var name = '아메리카노';
  console.log(name);
              resolve(name);
            },500);
});
}).then(function(prevName) {
  return new Promise(function (resolve) {
    setTimeout(function(){
  var name = '카페모카';
  console.log(name);
              resolve(name);
            },500);
});
  }).then(function(prevName) {
  return new Promise(function (resolve) {
    setTimeout(function(){
  var name = '카페라떼';
  console.log(name);
              resolve(name);
            },500);
});  
});

// -- 실행 결과 --

//'에스프레소'
//'아메리카노'
//'카페모카'
//'카페라떼'
  • Promise를 이용한 방식이다.
  • Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만 내부에 resolve 또는 reject 함수를 호출하는 구문이 있을 경우
  • 둘중 하나가 실행되기 전까지는 then 또는 catch로 넘어가지 않는다.
  • 비동기 작업이 완료될 때 비로소 resolve 또는 reject를 호출하는 방법으로 비동기 작업의 동기적 표현이 가능하다.

📌 정리


  • 콜백 함수는 다른 코드에 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수다.
  • 제어권을 넘겨받은 코드는 다음과 같은 제어권을 가진다.
    1. 콜백 함수를 호출하는 시점을 스스로 판단해서 실행
    2. 콜백 함수를 호출할 때 인자로 넘겨줄 값들 및 그 순서가 정해져 있다.
    3. 콜백 함수의 this가 무엇을 바라보도록 할지가 정해져 있는 경우도 있다. 정하지 않은 경우에는 전역객체를 바라본다. 사용자가 임의로 this를 바꾸고 싶을 경우 bind 메서드를 활용하면 된다.
  • 어떤 함수에 인자로 메서드를 전달하더라도 이는 결국 함수로서 실행된다.
  • 비동기 제어를 위해 콜백 함수를 사용하다 보면콜백 지옥에 빠지기 쉽다.최근에는 Promise와 같은 방법들이 등장하고 있다.
profile
1년차 프론트엔드 개발자

0개의 댓글