본문 바로가기
Language/Javascript

비동기 호출 (1) callback 함수

by joooing 2020. 12. 30.
반응형
비동기 호출 (1) callback 함수
비동기 호출 (2) 동기(sync) vs 비동기(async)
비동기 호출 (3) Timer API

Callback 함수


callback함수는 '다른함수의 전달인자(argument)로 넘겨주는 함수'이다. parameter를 넘겨받는 함수는 callback함수를 필요에 따라 즉시 실행할 수도 있고, 나중에 실행할 수도 있다. 아래 예시에서는 B가 parameter로 쓰이는 'callback함수'이고, A는 B를 parameter로 쓰는 함수이다.

 

✔️ 즉시 실행 = synchronously (동기)
✔️ 나중에 실행 = asynchronously (비동기)
function B(){
	console.log('나중'); 
} 
function A(callback){
	callback(); 
} 
A(B);

 

동기, 비동기 비유 ⏱

콜백함수는 '제어권'을 다른 함수에게 넘겨준 함수라고 생각할 수 있다. 위에서는 B가 A에게 제어권을 넘겨준 것이다. 다음 날 친구와 약속이 있는 상황에 비유를 해보자. 동기 방식을 사용하는 것은 약속 시간까지 계속해서 시계를 보며 시간을 확인하는 것이고, 비동기 방식은 약속 시간에 알람을 맞춰두고 기다리는 것에 비유할 수 있다. 시계 입장에서 보면, 동기 방식일 때는 요청이 들어올 때마다 시간을 알려주는 명령을 실행야 하기 때문에 권한이 사람에게 있다. 반면 비동기 방식일 때는 알람에 대한 요청만 받고 시간을 알려주는 명령은 시계가 알아서 처리하기 때문에 권한이 시계에게 있다. 위의 코드에서 사람이 A, 시계가 B 역할을 한다고 생각하면 된다.

 

callback함수 활용

callback함수라는 용어가 낯설어서 그렇지, 지금까지 callback함수는 고차함수 메서드나 이벤트 핸들러에서 등 생각보다 많이 사용되어 왔다.

 

iterator (반복 실행)

[1,2,3].map(function(el, idx)){
	return el * el; 
});

// [1,4,9]

 

event handler (이벤트에 따라 실행)

document.querySelector('#btn').addEventListener('click', function(){
	console.log('clicked!'); 
});

 

주의 사항

onclick이라는 이벤트에 handleBtn()이라는 이벤트 핸들러 연결하는 상황을 가정해보자. 이벤트에는 함수의 실행이 아닌 '함수 자체'를 연결해 줘야한다. 여기서 handleBtn()는 return값을 가지고 있지 않기 때문에 'undefined'와 마찬가지라고 생각하면 된다. 함수를 연결해야하는데 undefined가 연결되었으므로 잘못 사용한 것이다.

function handleBtn(){
	console.log('clicked!'); 
}; 

// 올바르게 사용 (O) 
document.querySelector('#btn').onclick = handleBtn; 
document.querySelector('#btn').onclick = function() {
	handleBtn(); 
} 
document.querySelector('#btn').onclick = handleBtn.bind(); 

// 올바르지 않게 사용 (X) 
document.querySelector('#btn').onclick = handleBtn();

 

콜백함수 = 클로저

콜백함수는 클로저이다. 비동기 방식을 사용하면, 함수가 실행되고 특정 시점에 콜백함수가 불려진다. 콜백함수는 자신이 포함된 함수 환경에 접근할 수 있기 때문에, 콜백함수는 클로저라고 할 수 있다. 아래 예시에서도 '콜백함수'만 있을 때는 hi라는 변수는 존재하지 않지만, 더 큰 환경인 '콜백함수를 포함한 함수'의 hi라는 변수에 접근함으로써 오류없이 제대로 출력하는 것을 볼 수 있다.

 


✔️클로저는 '함수와 함수가 선언된 어휘적 환경(lexical environment)의 조합'이다.
✔️내부 함수가 외부 함수 안에 선언된 변수에 접근할 수 있다. 내부 함수를 클로저 함수라고 부르기도 한다.  
✔️클로저는 독립적인 (자유) 변수를 가르키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경을 '기억한다'

function callback(cb){
    cb();
}

function hi(){
    let hi = 'hi';
    callback( function(){
        console.log(hi);
    })
}

hi();
// hi

 

동기, 비동기 방식을 설명하려면 콜백함수의 내용이 바탕이 되어야 해서 우선은 콜백함수에 대해 자세히 알아봤다. 이어서 동기, 비동기 방식의 차이점과 Timer API에 대해서도 더 알아보려고 한다 👏

반응형

댓글