왓풀(whatpull)

Callback Functions 본문

웹개발/[지식] 프로그래밍

Callback Functions

이연수(Allen) 2022. 8. 1. 15:52

콜백 함수는 다른 함수에 인수로 전달된 함수이며 외부 함수 내부에서 호출되어 일종의 루틴이나 작업을 완료합니다.

다음은 간단한 예입니다.

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('Please enter your name.');
  callback(name);
}

processUserInput(greeting);

위의 예는 즉시 실행되는 동기식 콜백입니다.

그러나 콜백은 비동기 작업이 완료된 후 코드 실행을 계속하기 위해 자주 사용됩니다. 이를 비동기 콜백이라고 합니다. 좋은 예는 .then()약속이 이행되거나 거부된 후 약속의 끝에 연결된 블록 내에서 실행되는 콜백 함수입니다. 이 구조는 .NET과 같은 많은 최신 웹 API에서 사용됩니다 fetch().

 

콜백함수는 클로저다(Callback Functions Are Closures)

우리가 다른 함수의 인자로 콜백함수를 전달할 때, 전달받은 함수의 특정시점에 그 콜백함수가 동작을 할 것입니다. 마치 전달받은 함수가 이미 콜백함수를 내부에서 정의 한 것처럼 말이지요.
이 말은 콜백은 클로저라는 말과 같습니다. 클로저에 대한 자세한 내용은 자바스크립트-변수로-자바스크립트-이해하기 에서 확인이 가능합니다.
간단하게 설명을하면 전달된 콜백함수는 콜백함수를 포함한 함수 내부의 인자에 접근이 가능하고 심지어 전역변수에도 접근이 가능한 상태가 됩니다. 즉, 기존의 함수가 가진 스코프에 새로운 내부 스코프가 추가가 되는 것입니다. 이로 인해 발생하는 이슈가 있는데 자세한 내용은 자바스크립트-변수로-자바스크립트-이해하기 에서 확인하시기 바랍니다.
우리가 알다시피 클로저는 포함하고 있는 함수의 스코프에 접근을 할수 있습니다. 그래서 콜백함수는 포함하고 있는 함수의 변수에 접근이 가능하고 심지어 전역변수에도 접근이 가능합니다.

출처: https://yubylab.tistory.com/entry/자바스크립트의-콜백함수-이해하기 [Yuby's Lab.:티스토리]

 

콜백함수(Callback Function) 사용 원칙

익명의 함수 사용

let number = [1, 2, 3, 4, 5];

number.forEach(function(x) {
    console.log(x * 2);
});

위의 예제를 화살표 함수에서 일반 함수로 바꾼 예제이다.
콜백함수는 이름이 없는 '익명의 함수'를 사용한다. 함수의 내부에서 실행되기 때문에 이름을 붙이지 않아도 된다.

함수의 이름(만) 넘기기

function whatYourName(name, callback) {
    console.log('name: ', name);
    callback();
}

function finishFunc() {
    console.log('finish function');
}

whatYourName('miniddo', finishFunc);

<output>
name: miniddo
finish function
[ TIP ]

JavaScript Data Type
- number, string, boolean, object(function, array, data, regexp), null, undefined

자바스크립트는 null과 undefined 타입을 제외하고 모든 것을 객체로 다룬다.
함수를 변수 or 다른 함수의 변수처럼 사용할 수 있다. 함수를 콜백함수로 사용할 경우, 함수의 이름만 넘겨주면 된다.
위의 예제에서, 함수를 인자로 사용할 때 callback, finishFunc 처럼 () 를 붙일 필요가 없다는 것이다.

전역변수, 지역변수 콜백함수의 파라미터로 전달 가능

  • 전역변수(Global Variable) : 함수 외부에서 선언된 변수
  • 지역변수(Local Variable) : 함수 내부에서 선언된 변수
let fruit = 'apple';	// Global Variable

function callbackFunc(callback) {
    let vegetable = 'tomato';	// Local Variable
    callback(vegetable);
}

function eat(vegetable) {
    console.log(`fruit: ${fruit} / vegetable: ${vegetable}`);
}

callbackFunc(eat);

<output>
fruit: apple / vegetable: tomato

 

콜백함수(Callback Function) 주의할 점

this를 사용한 콜백함수

해결 방안 : call()과 apply()를 사용하여 this를 보호할 수 있다.

  • call() : 첫 번째 인자로 this 객체 사용, 나머지 인자들은 , 로 구분
  • apply() : 첫 번째 인자로 this 객체 사용, 나머지 인자들은 배열 형태로 전달

 

콜백지옥 (Callback Hell)

비동기 호출이 자주 일어나는 프로그램의 경우 '콜백 지옥'이 발생한다.
함수의 매개변수로 넘겨지는 콜백 함수가 반복되어 코드의 들여쓰기 수준이 감당하기 힘들어질 정도로 깊어지는 현상이다.

function add(x, callback) {
    let sum = x + x;
    console.log(sum);
    callback(sum);
}

add(2, function(result) {
    add(result, function(result) {
        add(result, function(result) {
            console.log('finish!!');
        })
    })
})

<output>
4
8
16
finish!!

해결 방안 : Promise를 사용하여 콜백지옥을 탈출할 수 있다.

function add(x) {
    return new Promise((resolve, reject) => {
        let sum = x + x;
        console.log(sum);
        resolve(sum);
    })
}

add(2).then(result => {
    add(result).then(result => {
        add(result).then(result => {
            console.log('finish!!');
        })
    })
})

<output>
4
8
16
finish!!

Promise 는 정상 수행 후 resolve, 실패 후 reject 가 실행된다.
callback을 사용했던 것과 마찬가지로 resolve에 값을 담아 전달한다.

하지만, 이 패턴도 그리 좋은 방법은 아니다. 결국 콜백지옥처럼 들여쓰기 수준을 감당하기 힘들어진다.

해결 방안 : Promise의 return 사용하여 Promise Hell을 탈출할 수 있다.

프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다. 다만 최종 결과를 반환하지는 않고, 대신 프로미스를 반환해서 미래의 어떤 시점에 결과를 제공합니다.

MDN 에서 정의하고 있는 Promise에 대한 설명이다.
프로미스는 비동기 호출 시, 마치 동기 호출 처럼 값을 반환할 수 있다는 문구에 집중해보자.
즉, resolve를 통해 전달 받은 값을 반환하여 사용해야 한다.

function add(x) {
    return new Promise((resolve, reject) => {
        let sum = x + x;
        console.log(sum);
        resolve(sum);
    })
}

add(2).then(result => {
    return add(result);
}).then(result => {
    return add(result);
}).then(result => {
    console.log('finish!!');
})

<output>
4
8
16
finish!!

'웹개발 > [지식] 프로그래밍' 카테고리의 다른 글

Maven  (0) 2022.08.01
Java VM(Java Virtual Machine)  (0) 2022.08.01
B-Tree 자료 구조  (0) 2022.08.01
Hash 자료 구조  (0) 2022.08.01
Multi-Process server program  (0) 2022.08.01
Comments