비동기적 프로그래밍
Callback에 대해 본격적으로 설명하기 전, JavaScript의 비동기적 프로그래밍에 대해 잠시 알아보자.
자바스크립트 에플리케이션은 single thread에서 동작한다. 즉, 자바스크립트는 한 번에 한 가지 일만 할 수 있다. single thread이기 때문에 여러 문제를 비동기적 관점에서 생각해야 한다. 비동기적이라는 것은 하나를 끝낼 때까지 무조건 기다리고 다음 걸로 넘어가는 게 아니라, 하나가 다 끝나지 않아도 다른 걸 시작할 수 있음을 의미한다.
Callback 이란?
다른 함수가 실행을 끝낸 뒤 실행되는 함수이다. - 'Call back' 다시 불러줘!
Callback 이 필요한 이유
자바스크립트는 이벤트 기반 언어이기 때문이다. 자바스크립트는 다음 명령어를 실행하기 전, 이전 명령어의 응답을 기다린다기 보다, 다른 이벤트를 계속해서 실행할 것이기 때문이다.
예를 들어,
function first() {
console.log(1);
}
function second(){
console.log(2);
}
first();
second();
이렇게 되면 first가 먼저 실행되고 나서 second 가 실행될 것이다.
//1
//2
그런데 만일 first안에 우리가 응답을 기다려야 하는 함수가 있다면, 바로 실행되지는 않을 것이다. 가장 기본적인 예로,마치 API가 존재하는 것처럼 setTimeout 함수를 사용해 1000ms(1s) 정도 딜레이를 시켜 보자.
function first(){
setTimeout(function() {
console.log(1);
},1000)
}
이렇게 되면 second 함수의 결과값이 먼저 나올 것이다.
//2
//1
왜 이럴까? 자바스크립트는 second() 로 넘어가기 전, first()의 response에 대해 기다리지 않기 때문이다.
콜백은, 특정 코드가 끝나기 전까지는 다른 코드가 실행되지 않게 하기 위해 쓰인다.
Callback 만들어 보기
function doHomework(subject){
alert(`Starting my ${subject} homework`);
}
doHomework('math');
이렇게 함수를 call할 수 있다.
여기서 callback을 추가해 보자. doHomework()함수의 두 번째 인자로 callback을 추가하자.
function doHomework(subject, callback){
alert(`Starting my ${subject} homework`);
callback();
}
doHomework('math', function(){
alert('Finished my homework');
});
이렇게 하면 다음과 같은 순서로 결과가 나올 것이다.
'Starting homework' -> 'Finished homework'
callback 함수는 코드의 다른 곳에서도 정의될 수 있다.
function doHomework(subject, callback){
alert(`Starting my ${subject} homework`);
callback();
}
function alertFinished(){
alert('Finished my homework');
}
doHomework('math',alertFinished);
실생활 예제
콜백을 가장 많이 사용하는 경우는 아마도 API를 사용할 때일 것이다. API에 request를 보내면, 그 response를 가지고 뭔가를 하기 전에 response 값을 받을 때까지 기다려야 하기 때문이다.
만일 Twitters API를 사용해서 트윗을 가져온다고 쳤을 때, request는 다음과 같을 것이다.
T.get('search/tweets',params, function(err,data, response){
if(!err){
//callback
console.log('success')
}else{
console.log(errr)
}
})
search/tweets: route of our request
params: search parameters
//callback 에 있는 코드가 실행되려면 우리는 서버로부터 response를 기다려야 한다. 트위터는 err(error) 오브젝트 혹은 response 오브젝트를 보낼 것이다. 우리의 callback function에서 우리는 if()문을 사용해 request가 성공적이었는지 아니었는지를 판단하여, 새로운 데이터를 사용할 수 있다.
콜백 지옥은 안돼
콜백 함수를 과도하게 사용하면, '콜백 지옥'을 경험할 수 있다.😭
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 {
// ...continue after all scripts are loaded (*)
}
});
}
});
}
});
이렇게 되면 1. 가독성이 떨어지고 2.디버깅이 매우 어려워진다.
즉 이러한 콜백 지옥에 빠지는 걸 방지하기 위해 나타난 것이 promise 이다.
최근댓글