[코어 자바스크립트] 4.콜백 함수

홍예찬·2021년 1월 11일
0
post-thumbnail

4-1 콜백 함수란?

콜백함수는 다른 코드의 인자로 넘겨주는 함수를 의미합니다.
콜백함수의 가장 큰 특징은 다른 코드에 인자로 넘겨주면서 그 제어권도 함께 위임한다는 것입니다. 콜백 함수를 위임받은 코드는 로직에 의해 이 함수를 적절한 시점에서 실행하게 되는 것입니다.

4-2 제어권

그렇다면 제어권을 위임한다는 것은 어떤 의미일까요?
다음의 예시 코드를 보면서 설명하겠습니다.


var count = 0;
var cbFunc = function() {
  console.log(count);
  if(++count > 4) clearInterval(timer);
};
var timer = setInterval(cbFunc, 300);

위의 코드를 실행하게 되면 콘솔창에는 0.3초마다 한 번씩 숫자가 1씩 증가하면서 출력되게 됩니다. 그리고 4가 출력되면 clearInterval(timer)으로 인해 종료됩니다.

즉, setInterval 함수에 cbFunc를 첫 번째 인자로 넘겨주니, 제어권을 위임받은 setInterval 스스로 적절한 시점에 함수를 실행하게 되는 것이죠.

이와 같이 콜백 함수를 인자로 받은 코드가 함수 호출 시점에 대한 제어권을 가지게 됩니다.

4-3 콜백 함수는 함수다

콜백 함수로 어떤 객체의 메소드를 전달하더라도 그 메소드는 함수로서 호출됩니다.


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

[4,5,6].forEach(obj.logValues);

// Window { ... } 4 0
// Window { ... } 5 1
// Window { ... } 6 2

obj 객체의 logValues는 메소드로 호출됐습니다. 이에 따라 this는 obj를 가리키고, 인자로 넘어온 1,2가 출력됩니다.

한편 forEach 함수에서는 이 메소드를 콜백함수로 전달했습니다. 또한, this가 될 대상을 지정하지 않았기 때문에 this는 전역객체를 바라보게 됩니다.

즉, 어떤 함수의 인자에 객체의 메소드를 전달하더라도 이는 결국 메소드가 아닌 함수인 것입니다.

4-4 콜백 함수 내부의 this에 다른 값 바인딩하기

전통적인 방식으로는 this를 다른 변수에 담아 콜백 함수로 활용할 함수에 this대신 그 변수를 사용하게 하고, 이를 클로저로 만드는 방식이 많이 쓰였습니다.(클로저의 개념은 다음 장에서 다룰 예정입니다.)


var obj1 = {
  name: 'obj1',
  func: function () {
    var self = this;
    return function () {
      console.log(self.name)
    }
  }
}
var callback = obj1.func();
setTimeout(callback, 1000)	//obj1

그러나 이 방식은 실제로 this를 사용하지 않을뿐더러 변수에 담는 과정이 번거롭습니다. ES5에서는 bind메소드를 통해 이런 전통적 방식을 보완할 수 있습니다.


var obj1 = {
  name : 'obj1',
  func: function () {
    console.log(this.name);
  }
}
setTimeout(obj1.func.bind(obj1), 1000);	// 'obj1'

var obj2 = { name: 'obj2' }
setTimeout(obj1.func.bind(obj2), 1500);	// 'obj2'

4-5 콜백 지옥과 비동기 제어

콜백 지옥은 콜백함수를 익명함수로 전달하는 과정이 반복되어 가독성이 떨어지는 현상을 의미합니다. (콜백함수는 비동기적인 작업을 수행할 때 주로 사용됩니다. 콜백함수를 통한 비동기 처리에 대해서는 여기를 클릭하세요!)

콜백함수의 이러한 단점으로 인해, 비동기 처리를 위한 새로운 방식이 나왔습니다.

첫 번째로는 ES6에 추가된 Promise를 이용한 방식입니다.


Promise에 대해서는 여기를 클릭하세요!


두 번째로는 ES2017에 추가된 async, await 방식입니다.
비동기 처리를 하는 함수 앞에 async를 쓰고, 함수 내부에서 실질적으로 비동기 작업이 필요한 위치에 await을 표기하게 되면, 뒤의 내용을 Promise로 자동 전환하고, 해당 내용이 resolve된 이후 다음 일을 처리하게 됩니다.(Promise의 then과 비슷한 효과를 얻게 되는 것입니다.)


async/await에 대해서는 여기를 클릭하세요!


위의 글은 온전히 학습 목적을 위해 작성한 글입니다. 위 내용의 모든 지적 재산권,저작권은 코어 자바스크립트 저자에게 있으며, 무단 전재 및 재배포를 금합니다.

profile
내실 있는 프론트엔드 개발자가 되기 위해 오늘도 최선을 다하고 있습니다.

0개의 댓글