[JavaScript] 비동기식 처리 모델 - callback

miaa·2023년 2월 10일
0

FE

목록 보기
8/8
post-thumbnail

되짚어보기


비동기 함수란 쉽게 설명하면 호출부에서 실행 결과를 가다리지 않아도 되는 함수이고, 반대로 동기 함수는 호출부에서 실행 결과가 리턴될 때 까지 기다려야 하는 함수다.

때문에 자바스크립트처럼 싱글 쓰레드 환경에서 실행되는 언어에서 광범위하게 사용 되고 많은 시간이 할애되는 로직을 처리하는데 오랜 시간 동안 대기 해야하는 불상사를 막을 수 있다.


하지만 비동기식 처리 모델은 순서 보장이 되지 않는다는 단점이 하나 있는데,

이 단점을 콜백함수로 해결할 수 있다



콜백함수?


콜백함수를 알기 위해선 아래의 개념들을 정리할 필요가 있다

일급객체 : 일반 객체처럼 모든 연산이 가능한 것

  • 함수의 매개변수로 전달이 가능

  • 함수의 반환 값(return)으로 사용 가능

  • 할당 및 동일 비교도 가능함

    • 함수를 변수에 할당할 수 있기 때문에, 함수를 배열의 요소나 객체의 속성값으로 저장할 수 있다

위의 설명과 같이, 함수는 변수에 저장할 수 있다.

그리고 함수는, 함수를 담은 변수를 전달인자로 받을 수 있다

마찬가지로 함수 내부에서 변수에 함수를 할당할 수 있고 함수는 이 변수를 리턴할 수 있다


여기서 변수에 할당하지 않고 함수를 바로 이용할 수 있는데, 어떤 *고차 함수에 함수를 전달인자로 전달하고, 고차 함수는 함수 자체를 리턴하는 방법이 바로 그것이다

변수가 빠졌을 뿐, 동일하게 동작한다

이때 다른 함수(caller)의 전달인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 한다.

어떤 작업이 완료되었을 때 호출하는 경우가 많아서, 답신 전화를 뜻하는 콜백 함수라는 이름이 붙여졌다.

*고차함수

  • 인자로 함수를 받거나 ( = 콜백함수 )

  • 함수를 반환하는 함수


예시


  1. 다른 함수를 인자로 받는 경우

     function double(num) {
       return num * 2;
     }
    
     function doubleNum(func, num) {
       return func(num);
     }
    
     /*
      * 함수 doubleNum은 다른 함수를 인자로 받는 고차 함수입니다.
      * 함수 doubleNum의 첫 번째 인자 func에 함수가 들어올 경우
      * 함수 func는 함수 doubleNum의 콜백 함수입니다.
      * 아래와 같은 경우, 함수 double은 함수 doubleNum의 콜백 함수입니다.
      */
     let output = doubleNum(double, 4);
     console.log(output); // -> 8
    
  2. 함수를 리턴하는 경우

    function adder(added) {
     return function (num) {
      return num + added;
      };
    }
    
    /*
     * 함수 adder는 다른 함수를 리턴하는 고차 함수입니다.
     * adder는 인자 한 개를 입력받아서 함수(익명 함수)를 리턴합니다.
     * 리턴되는 익명 함수는 인자 한 개를 받아서 added와 더한 값을 리턴합니다.
     */
    
    // adder(5)는 함수이므로 함수 호출 연산자 '()'를 사용할 수 있습니다.
    let output = adder(5)(3); // -> 8
    console.log(output); // -> 8
    
    // adder가 리턴하는 함수를 변수에 저장할 수 있습니다.
    // javascript에서 함수는 일급 객체이기 때문입니다.
    const add3 = adder(3);
    output = add3(2);
    console.log(output); // -> 5
    
  3. 함수를 인자로 받고, 함수를 리턴하는 경우

    function double(num) {
      return num * 2;
    }
    
    function doubleAdder(added, func) {
      const doubled = func(added);
      return function (num) {
        return num + doubled;
      };
    }
    
    /*
     * 함수 doubleAdder는 고차 함수입니다.
     * 함수 doubleAdder의 인자 func는 함수 doubleAdder의 콜백 함수입니다.
     * 함수 double은 함수 doubleAdder의 콜백으로 전달되었습니다.
     */
    
    // doubleAdder(5, double)는 함수이므로 함수 호출 기호 '()'를 사용할 수 있습니다.
    doubleAdder(5, double)(3); // -> 13
    
    // doubleAdder가 리턴하는 함수를 변수에 저장할 수 있습니다. (일급 객체)
    const addTwice3 = doubleAdder(3, double);
    addTwice3(2); // --> 8

즉, 정리하자면 콜백함수는 파라미터로 전달받은 함수

파라미터로 콜백함수를 전달받고 함수 내부에서 필요할 때 콜백함수를 호출할 수 있다.



콜백함수를 통한 비동기 처리


const printString = (string, callback) => {
  setTimeout (
    () => {
      console.log(string)
      callback()
    },
    Math.floor(Math.random() * 100) + 1
  )
}

const printAll = () => {
  printString("A", () => { 
    printString("B", () => {
      printString("C", () => {})
    })
  })
}
printAll() // ABC
  • const printAll 은 printString을 실행하는데, 처음엔 A와 콜백을 받아서 넘긴다

  • 그러면 setTimeout의 콜백에서 A단계에서 넘겨진 콜백이 실행된다

  • 마찬가지로 B와 또 콜백을 받아서 넘기게 되어 setTimeout을 거치게 되고

  • 마지막엔 C와 콜백을 받아 넘겨서 또 똑같은 루트대로 실행이 된다



profile
엉금엉금

0개의 댓글