콜백함수
- 다른 함수에 인자로 전달되어 특정 시점에 호출되는 함수
- 함수 호출, 인자, 실행 시점에 대한 제어권을 다른 함수에게 위임한다.
- 비동기적인 작업을 처리하는데 주로 사용된다.
- 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) {
// 계속되는 중첩
});
});
});
콜백지옥의 해결 방법
- 함수 분리 : 각 콜백 함수를 기명함수로 변환해 분리한다.
- Promise : Promise를 사용하여 비동기 작업을 체이닝 방식으로 처리한다.
- Generator : 복잡한 비동기 흐름을 제어해 실행 중 멈추고 재개할 수 있도록 한다.
- 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 |