Callback

Happhee·2022년 5월 12일
1

AvenJS

목록 보기
12/17
post-thumbnail

자바스크립트는 이벤트 중심의 언어이기에 이벤트의 값이 반환될 때까지 기다리지 않고 다음의 이벤트를 진행하게 된다.
때문에, API 요청과 같이 비동기적인 함수를 실행할 경우 특별한 처리를 해주지 않으면 원하는 대로 동작하지 않을 수 있다.

이러한 문제를 해결하기 위해 나타난 방법이 콜백이다.


✨ 비동기적 프로그래밍

블록킹을 방지하여 싱글 스레드가 논블록킹으로 동작하게 하는 프로그래밍이다.

❗️ 동기 vs 비동기 ❗️

  • 동기식(synchronous) 순차적, 직렬적으로 작업(task)을 수행한다.
    👉 서버에게 요청을 한 뒤 데이터를 받아야 이어서 데이터를 가지고 처리를 할 수 있다.
    👉 blocking

  • 비동기(asynchronous) 병렬적으로 작업을 수행한다.
    👉 서버에게 데이터를 요청 한 후 응답을 기다리지 않고 바로 다음 작업을 수행한다
    👉 non-blocking

자바스크립트는 싱글 스레드 언어이기에 비동기적 프로그래밍을 구현하기 위해서비동기 작업을 병렬적으로 수행하기 위해 Web API와 Callback Queue를 이용한다.

싱글 스레드 👉 한 번에 한 가지 일만 실행할 수 있다.


✨ Callback

나중에 호출되는 함수이다.

우선, 자바스크립트에서 함수는 객체이고, 함수는 인자를 가질 수 있다.
이때, 인자로 대입되는 함수를 콜백함수라고 하는 것이다.

어떤 이벤트가 발생했거나 특정 시점에 도달했을 때, 시스템에서 호출하는 함수이다.

👇 이벤트 핸들러를 처리하는 코드를 살펴보자.

<button onclick="onClick">버튼</button>
<script>
function onClick(){
 	alert("버튼을 누르셨습니다"); 
 }
</script>

HTML의 onClick함수가 브라우저의 Javascript API에서 DOM 이벤트 핸들러에 등록되고, 해당 버튼을 클릭하면 이벤트 핸들러가 콜백 함수 onClick을 호출한다.

즉, 특정 함수에 전달되어 있는 함수가 어떤 조건에 의해 호출되는 함수이다.

Callback 비동기 예시

앞서 말했듯이 콜백함수는 일반적으로 다른 함수에 넘기거나 객체의 프로퍼티로 사용하고, 보통 익명함수로 사용한다.

콜백함수도 일반적인 함수라는 것을 명심하자.

function whereAsync(callback){
  callback();
}
console.log('whereAsync 호출 전');
whereAsync(function(){
  console.log('비동기??');
});
console.log('whereAsync 호출 후');

단순하게 함수에 콜백 함수를 전달하는 것만으로는 비동기적인 수행이 불가능하다.

따라서 비동기 프로그래밍을 위해서는 2가지가 필요하다는 것을 알았다.

  1. 비동기적으로 콜백 함수를 호출하는 함수

  2. 비동기적으로 호출되기를 원하는 콜백 함수

    setTimeout( ) setInterval( ) clearInterval( )에서 자세한 예제를 다루고 있다.


❗️ 주의사항 ❗️

중첩된 callback

const printFruitDelay = (fruit, callback) => {
  setTimeout(	// 타이머 API
    () => {
      console.log(fruit, time);
      callback();   // 콜백 함수를 전달받아 실행
    },2000); // 2초
}
const printFruits = () => {
  printFruitDelay("apple", () => {
    printFruitDelay("orange", () => {  // 콜백 안에서 콜백을 실행 
      printFruitDelay("grape", () => {})
    })
  })
}
printFruits();		

비동기 작업들의 처리 순서를 보장하기 위해서 printFruitDelay라는 콜백 함수 내부에서 익명함수를 콜백함수로 인자로 받는 printFruits 비동기 함수를 호출하였다.

순서대로 apple 👉 orange 👉 graphe가 출력되지만, 콜백 안에 콜백을 넣는 방식은 지양해야 한다.

callback 에러 핸들링

콜백 함수를 사용할 때, 비동기 작업이 실패될 수도 있으므로 이에 대한 에러를 핸들링 해야 한다.

const handleError = (src, callback) => {
  // ...src로 작업 수행

  if (비동기 작업 성공) {
    callback(null, value);	// src를 이용한 결과값
  } else { // 에러가 발생한 경우
    callback(error, null);
  }
}

handleError(src, (err, data) => {
  if (err) {
    // 에러 처리
    // err 👉 error
    // data 👉 null
  } else {
    // Do something
    // err 👉 null
    // data 👉 value
  }
})

에러가 발생하면 callback(error, null)를 호출하고, 성공하면 callback(null, value)를 호출하여 오류 우선 콜백을 사용한다.

callback hell

많이 들어봤을 콜백 지옥이다.
복잡한 비동기 작업이 들어왔을 때, 여러 개의 콜백 함수를 중첩시켜 사용할 때 나타나는 문제이다.

// step1부터 6까지 순서대로 실행되어야 하는 경우
step1(function (value1) {
    step2(function (value2) {
        step3(function (value3) {
            step4(function (value4) {
                step5(function (value5) {
                    step6(function (value6) {
                        // Do something use value6
                    });
                });
            });
        });
    });
});

가독성도 떨어지고, 에러 및 디버깅, 유지보수에도 좋지 않다.


📚 학습할 때, 참고한 자료 📚

profile
즐기면서 정확하게 나아가는 웹프론트엔드 개발자 https://happhee-dev.tistory.com/ 로 이전하였습니다

0개의 댓글