Call back함수, 콜백이 뭔데!

Minju Kim·2022년 2월 24일
0

JavaScript

목록 보기
5/7
post-thumbnail

출처 : 코어자바스크립트, [콜백], (https://ko.javascript.info/callbacks)

1. 콜백 함수란?

call back은 ‘부르다' + ‘되돌아오다', 즉 ‘되돌아 호출해달라'라는 의미이다. 어떤 함수 X를 호출하면서, ‘특정 조건일 때 함수 Y’를 실행해서 나에게 알려달라는 요청을 함께 보내는 것이다. 이 요청을 받은 함수 X의 입정에서는 해당 조건이 갖춰졌는지 여부를 스스로 판단하고 Y를 직접 호출한다.

이렇듯, 콜백함수는 다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써, 그 제어권도 함께 위임한 함수이다.

콜백함수를 위임받은 코드는 자체적인 내부 로직에 의해 이 콜백 함수를 적절한 시점에 실행할 것이다.

2. 제어권

2-1) 호출 시점

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

let count = 0;
let Func = function(){
	console.log(count);
	if(++count > 4) clearInterval(timer);
};
let timer = setInterval(Func, 300); // setInterval이 알아서 0.3초마다 호출해줌

2-1) 인자

콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수를 호출할 때 인자에 어떤 값들을 어떤 순서로 넘길 것인지에 대한 제어권을 갖는다.

👶 이게 무슨 말이냐?! 자 내가 CurrentValue와 index의 순서를 바꾸어서 넘겼다고 해보자. 아무리 이름을 자리를 바꿔서 넣었다고 한들, 콜백함수를 호출하는 주체가 사용자가 아닌 map메서드이므로, map 메서드가 콜백 함수를 호출할 때 인자에 어떤 값들을 어떤 순서로 넘길 것인지가 전적으로 map 메서드에 달려있다.

👉 다시 말하면, 컴퓨터는 그저 첫 번째, 두 번 째의 순서에 의해서만 각각을 구분하고 인식하기 때문에, 그 콜백을 호출하고 있는 메서드가 정의한 콜배함수의 인자를 ‘순서대로' 문법에 맞게 넣어줘야 한다는 것!

let myArr = [10,20,30].map(function(CurrentValue, index)){
	console.log(currentValue, index);
	return currentValue + 5;
});
console.log(myArr);
// 10 0
// 20 1
// 30 2
// [15,25,35]

/* 다음은 위 코드의 인자의 순서를 임의로 바꾸어 사용한 경우 */
let myArr = [10,20,30].map(function(index, CurrentValue)){
	console.log(index, CurrentValue);
	return currentValue + 5;
});
console.log(myArr);
// 10 0
// 20 1
// 30 2
// [6,7,8]

2-1) this

콜백함수도 함수이기에, 기본적으로는 this가 전역객체를 바라본다!

만약 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 this는 그 대상을 참조!

Array.prototype.map = function(callback, thisArg){....}

위 처럼 this의 대상을 thisArg로 지정한 경우에는 this가 그 대상을 바라보고 있다는 것이다.

3. 콜백 함수는 함수다

this를 공부할 때 봤지만, 결국에 콜백함수는 함수다! 다시말해, 콜백 함수로 어떤 객체의 메서드를 전달하더라도, 그 메서드는 메서드가 아닌 함수로서 호출된다.

무슨 말이냐면, this는 함께 전달 되는 것이 아니라, 일반 함수 호출이기 때문에 그 메서드가 가리키는 함수만 전달되어 this는 문맥을 잃고 전역객체를 바라보게 된다는 것이다.

let obj = {
	mynum : [1,2,3],
	logMynums : function(num,i){
			console.log(this,v,i);
	}
};
obj.logMynums(2,3); // {mynum:[1,2,3], logMynums:f} 2,3
[4,5,6].forEach(obj.logMynums); // window,4,0 //window,5,1 //window 6,2 	

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

앞서 살펴봤던 bind를 통해 콜백 함수 내부의 this에 다른 값을 바인딩 할 수 있다.

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

setTimeout(obj1.func.bind(obj1),1000);

5. 콜백 지옥과 비동기 제어

비동기란, 즉시 처리가 하는 것이 아닌 별도의 요청, 실행대기, 보류등과 관련된 코드이다.

어떤 함수의 실행을 특정 시간경과까지 보류한다거나(setTimeout), 사용자의 직접적인 개입이 있을 때까지 함수의 실행을 대기한다거나(addEventListener), 웹브라우저가 아닌 별도의 대상에 무언가를 요청하고 그에 대한 응답이 왔을 때, 비로소 어떤 함수를 실행하도록 대기하는등(XMLHttpRequest)의 즉시 실행되는 것이 아닌 것을 의미한다. (이전에 배웠던 마이크로태스크큐, 태스크큐 등과 연관지어서 다시 한번 이벤트 루프와 과정을 떠올려본다.)

<콜백 지옥을 보아라..>

loadScript('1.js', function(error, script) {

  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {
      if (error) {
        handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {
          if (error) {
            handleError(error);
          } else {
            // 모든 스크립트가 로딩된 후, 실행 흐름이 이어집니다. (*)
          }
        });

      }
    })
  }
});

콜백 지옥을 해결하는 가장 간단한 방법은 ‘기명 함수'로 바꾸는 거다.

그런데, 이것도 좋지는 않다. 왜냐? 이 함수들을 재사용 할게 아니라면, 굳이 이렇게 별도로 함수를 만들어줘야하나,, 그리고 눈을 이리저리 굴리며 읽어야 하기도..! 그래서 나오게 된 게 promise, await, async이다!

profile
⚓ A smooth sea never made a skillful mariner

0개의 댓글