Juni_Dev_log

(node.js) [Part.3] 노드와 자바스크립트 - 콜백 함수 이해하기 본문

Theorem (정리)/node.js

(node.js) [Part.3] 노드와 자바스크립트 - 콜백 함수 이해하기

Juni_K 2020. 12. 1. 12:26

자바스크립트의 변수에는 숫자나 문자열 같은 데이터, 그리고 중괄호를 이용해 만든 객체 뿐만 아니라 함수도 할당할 수 있다.

이렇게 변수에 함수를 할당할 수 있다는 특징은 함수를 호출할 때 다른 함수를 파라미터로 전달하거나 함수 안에서 또 다른 함수를 만들어 반환할 수 있다.

 

함수를 파라미터로 전달하기

함수를 호출했을 때 또 다른 함수를 파라미터로 전달하는 방법

함수를 파라미터로 전달하는 경우는 대부분 비동기 프로그래밍(NoN-Blocking Programming) 방식으로 코딩을 만들 때이다.

예를 들어, 더하기 함수를 실행한 후, 결과 값이 반환될 때까지 기다리지 않고 그 다음 코드를 실행하려면 비동기 방식으로 코드를 만들어야한다.

즉 더하기 함수를 실행하는 데 시간이 걸릴 수 있기 때문에 그 다음 코드를 바로 실행한다.

그러고 나서 연산이 끝났을 때 파라미터로 전달한 함수가 실행될 수 있다면, 그 시점에 결과를 처리할 수 있으므로 효율적인 프로그램을 만들 수 있다.

이때 파라미터로 전달되는 함수를 콜백함수(Callback Function) 라고 한다.

 

콜백 함수는 함수가 실행되는 중간에 호출되어 상태 정보를 전달하거나 값을 처리하는데 사용된다.

ch03_test15.js 파일을 만들고 작성해보자.

function add(a,b,callback){
    var result = a+b;
    callback(result);
}

add(10,10,function(result){
    console.log('파라미터로 전달된 콜백 함수 호출됨.');
    console.log('더하기 (10,10)의 결과 : %d',result);
})

/*
파라미터로 전달된 콜백 함수 호출됨.
더하기 (10,10)의 결과 : 20
*/

더하기 함수를 정의할 때는 더 이상 값을 반환하지 않도록 return 키워드를 사용하는 코드 부분을 삭제한다.

 

그 대신, 더하기 연산을 한 결과 값은 파라미터로 전달된 콜백 함수를 호출하면서 그 콜백 함수로 전달한다.

콜백 함수는 미리 변수에 할당해 두었다가 add() 함수를 호출할 때 파라미터로 전달할 수도 있지만, add()함수를 호출할 때 익명 함수로 만들어서 바로 파라미터로 바로 전달할 수도 있다.

콜백 함수는 더하기 연산을 하는 코드 아래에서 호출되는데 이 때 콘솔 창에서 메세지를 출력한다.

 

노드에서는 대부분의 코드를 비동기 방식으로 만들기 때문에 위와 같이 콜백 함수를 만들어 파라미터로 전달하고 콜백 함수가 호출될 떄 결과값을 콘솔 창에 뿌려 줄 수 있다

 

함수 안에서 값을 반환할 때 새로운 함수를 만들어 반환하는 방법

지금까지 함수를 호출했을 때 또 다른 함수를 파라미터로 전달하는 방법에 대해서 알아보았다.

그러면 함수 안에서 값을 반환할 때 새로운 함수를 만들어 반환하는 방법도 살펴보자.

 

함수에서 반환하는 값이 함수 객체인 경우

어떤 함수를 실행했을 때 또 다른 함수를 반환받으면  그대로 실행할 수 있다.

이렇게 만들면 하나의 함수를 실행했을 때, 추가적인 결과를 얻거나 또는 추가 작업을 할 수 있다.

그러면 더하기 함수를 실행했을 때 그 기록을 남겨두었다가 출력하는 기능을 가상으로 만들어 보자.

ch03_test16.js 파일을 만든 후, 입력한다.

function add(a,b,callback){
    var result = a+b;
    callback(result);
    
    var history = function(){
        return a + ' + ' + b + ' = ' + result;
    };
    return history;
};

var add_history = add(10,10,function(result){
    console.log('파라미터로 전달된 콜백 함수 호출됨.');
    console.log('더하기 (10,10)의 결과 : %d',result);
});

console.log('결과값으로 받은 함수 실행 결과 : ' + add_history());

/*
파라미터로 전달된 콜백 함수 호출됨.
더하기 (10,10)의 결과 : 20
결과값으로 받은 함수 실행 결과 : 10 + 10 = 20
*/

여기에서는 add() 함수를 호출했을 때 콜백 함수를 호출할 뿐만 아니라, 함수 객체를 새로 만들어 반환하도록 만들었다.

반환된 함수 객체는 어떤 연산이 수행되었는지 문자열로 알려주는 함수이다.

 

함수를 실행한 후, 반환받은 함수 객체를 add_history 변수에 할당한 후, 그 함수를 실행하였다.

파일을 실행하면 다음과 같은 결과가 콘솔 창에 출력된다.

 

반환받은 history 객체가 함수이고 이 함수를 실행했을 때, 어떤 값으로 더하기 연산을 했는지 알 수 있도록 만들었다.

이렇게 함수의 실행 결과로 함수 객체를 받을 수 있다는 것을 잘 이해했다면 반환된 함수에서 접근할 수 있는 변수에 대해서도 알아볼 필요가 있다.

 

반환된 함수는 보통 처음 실행한 함수 안에서 만들어지는데 그 안에 있는 변수들은 함수가 반환된 후에도 계속 접근할 수 있다.

반환된 함수 객체에서 함수를 만들어 준 add 함수 안의 변수에 접근하기

 

add 함수 안에 history 함수를 몇 번이나 실행하는지 알 수 있도록 count 변수를 만들었다면 이 변수는 add 함수에서 반환된 함수 안에서 계속 접근할 수 있다.

다음과 같이 ch03_test17.js 파일을 만들어 코드를 입력한다.

function add(a,b,callback){
    var result = a+b;
    callback(result);
    
    var count = 0;
    var history = function(){
        count++;
        return count + ' : ' + a + ' + ' + b + ' = ' + result; 
    };
    return history;
}

var add_history = add(10,10,function(result){
    console.log('파라미터로 전달된 콜백 함수 호출됨.');
    console.log('더하기 (10,10)의 결과 : %d',result);
});

console.log('결과 값으로 받은 함수 실행 결과 : '+add_history());
console.log('결과 값으로 받은 함수 실행 결과 : '+add_history());
console.log('결과 값으로 받은 함수 실행 결과 : '+add_history());

/*
파라미터로 전달된 콜백 함수 호출됨.
더하기 (10,10)의 결과 : 20
결과 값으로 받은 함수 실행 결과 : 1 : 10 + 10 = 20
결과 값으로 받은 함수 실행 결과 : 2 : 10 + 10 = 20
결과 값으로 받은 함수 실행 결과 : 3 : 10 + 10 = 20
*/

 

반환된 함수를 반복해서 실행하면,  count 의 값이 증가하는 것을 볼 수 있다.

반환된 history() 함수가 실행될 때는 이미 add() 함수가 메모리에서 접근할 수 없는 상태가 된 다음이다.

 

따라서 history() 함수가 실행될 때는 add 함수 안에 만들어진 count 변수도 같이 접근할 수 없어야한다.

하지만, 이와 같이 함수 안에서 새로운 함수를 만들어 반환하는 경우에는 예외적으로 변수 접근을 허용한다.

이것을 클로저(Closure)라고 부른다.

Comments