본문 바로가기
개발/Frontend

콜백함수

by lewns2 2023. 2. 6.

콜백함수란?

01. 정의
    예시) addEventListener
    예시) 콜백 함수를 사용하는 고차 함수 - map(), filter(), reduce()

02. 설명
    예시) 덧셈을 출력하는 로직

03. 용도
    01. 순차적 실행 보장
    02. 로직의 추상화

04. 콜백 함수의 장단점

05. 정리

정의


콜백 함수는

  • 다른 함수의 인자(파라미터)로써 넘겨지는 함수
  • 특정 이벤트에 의해 호출되는 함수

예시) addEventListener

button.addEventListener("click", myFunction);

function myFunction() {
  document.getElementById("demo").innerHTML = "Hello World";
}

addEventListener 함수에 안에 myFunction 함수를 넘겨주므로 myFunction 함수는 콜백 함수이다.

매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수는 고차 함수(Higher-Order Function)라 한다.

예시) 콜백 함수를 사용하는 고차 함수 map(), filter(), reduce()

// 콜백 함수를 사용하는 고차 함수 map
var res = [1, 2, 3].map(function(item) {
    return item * 2;
});

console.log(res);  // [2, 4, 6]

// 콜백 함수를 사용하는 고차 함수 filter
res = [1, 2, 3].filter(function(item) {
    return item % 2;
})

console.log(res);  // [1, 3];

// 콜백 함수를 사용하는 고차 함수 reduce
res = [3, 4, 5, 6].reduce(function(acc, cur) {
    return acc * cur;  // f(f(f(3, 4), 5), 6)
})

console.log(res); // 360;

 

설명


콜백을 넘겨받는 코드(고차 함수)는 이 콜백을 필요에 따라 즉시 실행할 수 있거나, 나중에 실행할 수 있다.

즉, 콜백 함수는 고차 함수에 의해 호출 시점이 결정된다.

 

자바스크립트에서 함수를 인자로 넘기는 것이 가능한 이유는 함수를 “일급 객체”로 취급하기 때문이다.

(참고로, 콜백 함수는 자바스크립트에 국한된 개념이 아닌 프로그래밍에서 통용되는 개념이다. 그렇기 때문에 다른 언어에서는 콜백 함수의 전달을 포인터, 서브 루틴, 람다함수 등의 형태로 한다.)

예시) 덧셈을 출력하는 로직

  1. 단순한 구현 방법
function add(x, y) {
    return x + y;
}

function printResult(result) {
    console.log(result);
}

printResult(add(10, 2));  // 프린트 함수 호출 -> 덧셈 함수 호출

 

  1. 콜백 함수를 사용한 구현.
    콜백 함수가 다른 곳에서도 필요하거나, 자주 호출되는 경우에 외부에서 콜백 함수를 정의한 후 참조를 통해 전달한다.
function add(x, y, print) {
    print(x+y);
}

function printResult(result) {
    console.log(result);
}

add(10, 20, printResult);  // printResult 함수를 인자로 전달(함수 형태가 아니다!)

 

  1. 익명 함수를 통한 콜백 함수 사용
    주로 고차 함수 내부에만 호출되는 경우 사용된다.
function add(x, y, print) {
    print(x+y);
}

add(10, 20, (result) => {
    console.log(result);
})

 

  1. [참고] C에서 포인터를 통한 콜백 함수 구현
#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
    int(*fp)(int, int);  // 함수포인터 선언 - '반환자료형(*이름)(인자 자료형, 인자 자료형)'
    fp = add;
    printf("%d", fp(1, 2));
}

 

용도


01. 순차적 실행을 보장하고 싶을 때 사용한다.

  • 특정 이벤트 발생 후 실행

예시) “1” 출력하고 “2”출력하기

  1. 단순하게 구현하기.
function printOne() {
    console.log('1');
}

function printTwo() {
    console.log('2');
}

printOne();
printTwo();

 

  1. 콜백 함수로 구현하기.
function printOne(afterPrintOne) {
    console.log('1');
    afterPrintOne();
}

function printTwo() {
    console.log('2');
}

printOne(printTwo);  // 함수를 인자로 넘긴다.

 

02. 로직의 추상화를 위해 사용된다.

예시) N까지 숫자 출력, N까지 숫자 중 홀수만 출력하기.

 

// N까지 숫자 출력
function repeat(n) {
    for(var i=0; i<n; i++) {
        console.log(i);
    }
}

repeat(5);  // 0 1 2 3 4

여기서, N까지의 숫자 중 홀수만 출력하는 기능도 만들고 싶다라고 가정하자.

 

repeat 함수는 console.log(i)에 강하게 의존하고 있어 다른 일을 할 수 없다.

그러므로 repeat 함수의 반복문 내부에서 다른 일을 하려면 함수를 새롭게 작성하는 수 밖에 없다.

 

// N까지 숫자 출력
function repeat(n) {
    for(var i=0; i<n; i++) {
        console.log(i);
    }
}

repeat(5);  // 0 1 2 3 4

// N까지 숫자 중 홀수만 출력
function repeat2(n) {
    for(var i=0; i<n; i++) {
        if(i % 2) console.log(i);
    }
}

repeat(5); // 1 3

살펴보면, N까지 for문을 돌리는 것은 중복되지만 for문 내부에서 하는 일이 다른 것을 볼 수 있다.

이를 함수를 합성하는 것으로 해결할 수 있다. (고차 함수는 콜백 함수를 자신의 일부분으로 합성한다.)

 

// 중복: N까지 for문을 도는 것
function repeat(n, f) {
    for(var i=0; i<n; i++) {
        f(i);
    }
}

// 분리 1: 모두 출력
var printAll = function(i) {
    console.log(i);
};

// 분리 2: 홀수만 출력
var printOdds = function(i) {
    if(i % 2) console.log(i);
};

repeat(5, printAll);  // 0 1 2 3 4
repeat(5, printOdds); // 1 3

 

콜백 함수의 장단점


장점

  • 함수를 인자로 받기 때문에 필요에 따라 함수의 정의를 달리해 전달할 수 있다.
  • 함수를 굳이 정의하지 않고 익명 함수로도 전달이 가능하다.
  • 비동기 처리 방식의 문제점을 해결할 수 있다. (함수 제어권을 위임했기 때문.)

단점(정확히는 비동기 처리에서의 단점)

  • 콜백함수의 남용은 코드 가독성을 해친다.(콜백 지옥)
  • 비동기 처리 중 발생한 에러의 처리가 어렵다.

 

정리


  • 콜백 함수를 비동기 처리만을 위한 패턴이 절대! 아니다.
    • 콜백 함수는 함수형 프로그래밍에서 고차 함수를 만드는 패턴이기도 하며, 자바스크립트에서 비동기 처리를 위한 하나의 패턴으로도 사용되는 것이다.

 

 

 

 

728x90
반응형

'개발 > Frontend' 카테고리의 다른 글

[FE/Test] MSW에 대하여  (0) 2023.02.04
PWA 도입하기 - CRA 4.x 버전에서 PWA 도입하기  (0) 2023.02.04