본문 바로가기

자바스크립트

콜백함수

콜백함수

  • 다른 함수에 인자로 전달되어 특정 시점에 호출되는 함수
  • 함수 호출, 인자, 실행 시점에 대한 제어권을 다른 함수에게 위임한다.
  • 비동기적인 작업을 처리하는데 주로 사용된다.
    • Ajax 요청 : 웹 애플리케이션에서 서버로부터 데이터를 비동기적으로 가져올 때 사용
    • 타이머 : setTimeout이나 setInterval과 같은 타이머 함수에서 지정된 시간 후에 실행될 코드를 콜백함수로 전달
    • 이벤트 핸들링 : DOM 요소의 이벤트 처리
    • 파일 읽기 / 쓰기 : Node.js에서 파일 시스템 작업을 수행할 때 사용
    • 함수의 동작을 동적으로 변경

 

제어권 위임

1. 호출시점

  • 콜백함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점에 대한 제어권을 가진다.
function setTimer(callback) {
    setTimeout(callback, 1000); // 타이머 함수가 호출 시점을 결정함
}

setTimer(() => {
    console.log("1초 후에 호출됨");
});

 

2. 인자

  • 콜백함수의 제어권을 넘겨받은 코드는 콜백 함수를 호출할 때 인자에 어떤 값들을 어떤 순서로 넘길 것인지에 대한 제어권을 가진다.
  • 개발자는 이 규칙에 맞춰서 콜백 함수를 작성해야 한다!
[1, 2, 3].forEach((item, index, array) => {
    console.log(item, index, array);
    // item: 현재 요소 값
    // index: 현재 요소의 인덱스
    // array: 원본 배열 전체
});
// 출력: 
// 1 0 [1, 2, 3]
// 2 1 [1, 2, 3]
// 3 2 [1, 2, 3]


콜백함수와 this

  • 콜백함수도 함수이므로 콜백함수 내부의 this 는 기본적으로 전역객체를 참조한다.
function testCallback() {
    console.log(this); // 브라우저 : window / Node.js : global
}

setTimeout(testCallback, 1000);

 

  • 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this 를 지정한 경우 그 대상을 참조한다. 

       * bind(), 화살표 함수, 명시적 this 바인딩 등을 통해 this 제어 가능

 

 

콜백함수는 함수

  • 콜백 함수로 객체의 메서드를 전달할 시 그 메서드는 메서드가 아닌 함수로서 호출된다. → 객체와의 연결이 끊어짐
  • 함수가 독립적으로 실행되므로 this는 기본적으로 전역객체를 참조한다.
const obj = {
    name: 'hayoung',
    greet: function() {
        console.log(this.name); // 원래는 obj의 name을 참조하길 기대
    }
};

// 콜백으로 전달되면 메서드가 아닌 단순 함수로 호출됨
setTimeout(obj.greet, 1000); // undefined 출력
// this가 전역객체(window)를 참조하게 됨

 

 

해결방법 - 콜백 함수 내부의 this 에 다른 값 바인딩 하기

bind() 메서드 사용

setTimeout(obj.greet.bind(obj), 1000); // 'hayoung' 출력

 

화살표 함수 사용

setTimeout(() => obj.greet(), 1000); // 'hayoung' 출력

 

래퍼 함수 사용 

*다른 함수를 감싸는(wrapping) 함수

setTimeout(function() {
    obj.greet(); // 'hayoung' 출력
}, 1000);

 

 

콜백의 한계

콜백지옥

  • 비동기 작업을 처리하기 위해 콜백 함수를 중첩해서 사용할 때 발생하는 코드의 복잡성과 가독성 문제
// 콜백 지옥 (가독성 저하)
getData(function(a) {
    getMoreData(a, function(b) {
        getMoreData(b, function(c) {
            // 계속되는 중첩
        });
    });
});

 

 

콜백지옥의 해결 방법

  1. 함수 분리 : 각 콜백 함수를 기명함수로 변환해 분리한다.
  2. Promise : Promise를 사용하여 비동기 작업을 체이닝 방식으로 처리한다.
  3. Generator : 복잡한 비동기 흐름을 제어해 실행 중 멈추고 재개할 수 있도록 한다.
  4. async/await : ES2017에서 도입된 async/await를 사용하여 비동기 코드를 동기 코드처럼 작성한다.

 

'자바스크립트' 카테고리의 다른 글

프로토타입(prototype)  (0) 2024.12.18
클로저  (0) 2024.12.15
this  (0) 2024.12.13
실행컨텍스트(Execution Context)  (0) 2024.12.03
얕은복사와 깊은복사, structuredClone()  (0) 2024.12.02