[Javascript]callback 함수란? / callback의 문제와 해결 / 콜백 지옥

kaya·2023년 11월 23일

Javascript

목록 보기
6/13

어떤 함수 a의 parameter로 들어가서 a 함수 내부에서 호출되는 함수이다.
다른 함수에 parameter로 전달되는 함수

종류

동기식(synchronous) 콜백

  • 외부 함수 호출 직후에 호출되는 함수
  • 예) Array.prototype.map(), Array.prototype.forEach()에 인자로 들어가는 함수

비동기식(asynchronous) 콜백

  • 비동기 작업이 완료된 후 호출되는 함수 ➡️ task가 끝나기 전에 함수가 실행되지 않는 것을 보장한다
  • 예) setTimeOut(), addEventListener()에 인자로 들어가는 함수

(비동기식) 콜백 사용 시 생기는 문제점

1. 콜백 지옥이 발생할 수 있다

  • 비동기 처리를 할 때 어떤 처리를 하고 => 또 그걸 받아서 어떤 처리를 하고 => ... 이렇게 연쇄적으로 콜백 함수를 쓰면 발생한다

  • 가독성이 떨어지고 유지보수가 어려운 코드 구조이다

  • 챗 선생님이 알려준 예시

// 비동기적으로 동작하는 함수 1
function asyncFunction1(callback) {
    setTimeout(function () {
        console.log("Async Function 1");
        callback();
    }, 1000);
}

// 비동기적으로 동작하는 함수 2
function asyncFunction2(callback) {
    setTimeout(function () {
        console.log("Async Function 2");
        callback();
    }, 1000);
}

// 비동기적으로 동작하는 함수 3
function asyncFunction3(callback) {
    setTimeout(function () {
        console.log("Async Function 3");
        callback();
    }, 1000);
}

// 콜백 지옥
asyncFunction1(function () {
    asyncFunction2(function () {
        asyncFunction3(function () {
            console.log("작업 완료");
        });
    });
});

2. 에러 처리가 어렵다

  • 콜백 함수 수행 중에 예외가 발생하면 비동기 동작의 최초 실행자에 전달할 방법이 없다
  • 구조 상 에러 처리하기가 어렵다

해결

  • Promiseasync/await을 쓰면 해결이 가능하다

Promise(비동기 작업의 결과를 나타내는 객체)

  • .then() 으로 콜백 함수를 chaining하기 때문에 가독성, 유지보수성이 좋게 콜백 함수들을 작성할 수 있다
  • .then()의 두번째 인자에 에러 발생 시 호출할 콜백 함수를 주거나, .catch()를 사용해 에러를 처리할 수 있다

async/await

  • 비동기 코드를 동기 코드처럼 작성할 수 있게 도와주는 문법이기에 간결하게 작성할 수 있다.
  • try...catch 블록을 사용해 간편하게 예외 처리를 할 수 있다

callback 함수로 예외 처리

function asyncFunction(callback) {
    setTimeout(function () {
        const error = Math.random() > 0.5 ? new Error("에러 발생!") : null;
        if (error) {
            callback(error, null);
        } else {
            callback(null, "작업 완료!");
        }
    }, 1000);
}

asyncFunction((error, result) => {
    if (error) {
        console.error("에러 발생:", error);
    } else {
        console.log("결과:", result);
    }
});

async/await로 예외 처리

function asyncFunction() {
  	// resolve: 프로미스가 이행됐을 때(정상적일 때) 호출할 함수
  	// reject: 프로미스가 거절되었을 때(비정상적일 때) 호출할 함수
    return new Promise((resolve, reject) => {
        setTimeout(function () {
            const error = Math.random() > 0.5 ? new Error("에러 발생!") : null;
            if (error) {
                reject(error);
            } else {
                resolve("작업 완료!");
            }
        }, 1000);
    });
}

async function executeAsyncFunction() {
    try {
        const result = await asyncFunction();
        console.log("결과:", result);
    } catch (error) {
        console.error("에러 발생:", error);
    }
}

executeAsyncFunction();

참고 자료

profile
🏟 튼튼한 성은 튼튼한 벽돌로부터

0개의 댓글