콜백함수 (Callback)

swimming·2023년 6월 25일
0
post-thumbnail

🖊️  콜백함수

자바스크립트에서 함수는 객체다. 함수의 파라미터로서 객체를 전달할 수 있다는 말이다.

그렇듯이 다른 함수에 파라미터로 넘겨준(=전달하는) 함수를 콜백함수라 칭한다.

🖍️ 콜백함수가 필요한 이유

자바스크립트는 위에서 아래로 순차적으로 코드를 실행한다. 그러나, 코드가 다른 행위가 일어난 뒤에 실행되는 경우도 있고, 순차적으로 실행되지 않을 때도 있다.
이때 '비동기(asynchronous)프로그래밍'방식을 사용하자.

'비동기' 란?

 현재 실행중인 작업을 멈추지 않고 다른 작업을 병렬적으로 수행하는 것을 의미한다. 그래서 여러 작업(task)이 있을 때 비동기적으로 수행하면 작업들을 동시에 한번에 수행할 수 있어 위 사진 처럼 결과적으로 최종 작업 수행이 빠르게 처리되게 된다. 그리고 이러한 비동기 방식으로 작업을 처리하는 방법 중 하나가 바로 콜백(callback) 함수이다.

콜백은 현재 실행 중인 태스크가 끝나기 전에 함수가 실행되지 않는 것을 보장한다. 즉, 콜백은 그 태스크가 끝난 직후에 실행된다.

콜백은 비동기 자바스크립트 코드를 작성할 수 있도록 해주고 여러 문제와 에러들로부터 안전하게 지켜준다.

🖍️ 콜백함수는 어떻게 동작하는가?

앞서 말했듯이 js에서 모든 것은 객체다. 함수 또한! 일급객체!!
그래서 함수를 변수처럼 다른 함수의 리턴값으로 사용 가능하다.
함수를 콜백으로 다른 함수의 인자처럼 사용할 경우에는 오직
>> 함수의 이름만 << 넘겨주면 된다.

굳이 함수라고 하여 끝에 () 같은 것을 붙일 필요 없다. 다음과 같은 형태.

setTimeout(callback, 3000);

이처럼 함수의 인자로 전달된 함수의 경우에는 언제든 원하는 시점에 실행을 시킬수가 있다.
콜백함수는 전달 받은 즉시 바로 실행이 될 필요가 없다는 말이다.
함수의 이름처럼 “called back” , 함수의 내부의 어느 특정시점에 실행을 한다.

🖍️ 콜백 사용 예시

// ex 01)
function sayHello(name, callback) {
    const words = '안녕하세요 내 이름은 ' + name + ' 입니다.';
    
    callback(words);
}

sayHello("인파", function (name) { // 함수의 이름이 없는 익명 함수
	console.log(name); 
});

// ex 02)
const msg = function () {
  console.log("This message is shown after 3 sec");
};

setTimeout(msg, 3000);

msg 함수는 어떤 일이 일어나지 전이 아니라 일어난 뒤(여기서는 3초가 지난 후)에 호출된다.

🖍️🖍️ 화살표 함수 모양의 콜백

function sayHello(callback) {
  var name = "Mac";
  callback(name); // 콜백 함수 호출
}

// 익명 화살표 콜백 함수
sayHello((name) => {
  console.log("Hello, " + name);
}); // Hello, Mac


🖍️ 콜백함수 사용 원칙

1. 익명의 함수 사용

// ex 01)
let number = [1, 2, 3, 4, 5];

number.forEach(function(x) {
    console.log(x * 2);
});

// ex 02)
setTimeout(function () {
  console.log("This message is shown after 3 seconds");
}, 3000);

// ex 03) 익명 화살표 콜백 함수
setTimeout(() => {
  console.log("This message is shown after 3 seconds");
}, 3000);

코드의 간결성을 위해 이름이 없는 '익명의 함수'를 사용한다. 함수의 내부에서 실행되기 때문에 이름을 붙이지 않아도 된다.
또한, 함수 이름의 충돌 방지를 예방하기 위함이기도 하다.

2. 함수의 이름(만) 넘기기

//ex 01)  ---------------
function whatYourName(name, callback) {
    console.log('name: ', name);
    callback();
}

function finishFunc() {
    console.log('finish function');
}

whatYourName('xiuying', finishFunc);

<output>
name: xiuying
finish function

//ex 02)  매개변수에 전달할 콜백 함수 종류만을 바꿔줌으로서 여러가지 함수 형태를 다양하게 전달
function introduce (lastName, firstName, callback) {
    var fullName = lastName + firstName;
    
    callback(fullName);
}

function say_hello (name) {
    console.log("안녕하세요 제 이름은 " + name + "입니다");
}

function say_bye (name) {
    console.log("지금까지 " + name + "이었습니다. 안녕히계세요");
}

introduce("홍", "길동", say_hello); // 안녕하세요 제 이름은 홍길동입니다

introduce("홍", "길동", say_bye); // 지금까지 홍길동이었습니다. 안녕히계세요
[ TIP ]

JavaScript Data Type
- number, string, boolean, object(function, array, data, regexp), null, undefined

자바스크립트는 null과 undefined 타입을 제외하고 모든 것을 객체로 다룬다.
함수를 변수 or 다른 함수의 변수처럼 사용할 수 있다. 함수를 콜백함수로 사용할 경우, 함수의 이름만 넘겨주면 된다.

위의 예제에서, 함수를 인자로 사용할 때 callback, finishFunc 처럼 () 를 붙일 필요가 없다는 것이다.

3. 전역변수, 지역변수 콜백함수의 파라미터로 전달 가능

let fruit = 'apple';	// Global Variable

function callbackFunc(callback) {
    let vegetable = 'tomato';	// Local Variable
    callback(vegetable);
}

function eat(vegetable) {
    console.log(`fruit: ${fruit} / vegetable: ${vegetable}`);
}

callbackFunc(eat);

<output>
fruit: apple / vegetable: tomato


🖍️ 콜백 함수 활용 예제

🖍️🖍️ addEventListener 이벤트 처리

button 클릭 시 console에 출력

<button class="callback-btn">Click here</button>
document.querySelector(".callback-btn")
  .addEventListener("click", function () {
  console.log("User has clicked on the button!");
});

🖍️🖍️ addEventListener 고차함수

forEach 메서드 입력값으로 콜백함수 전달하는 형태.
배열의 각 요소를 두 배로 곱해서 새로운 배열을 생성하는 콜백 함수

let numbers = [1, 2, 3, 4, 5];  
let doubled = [];

// numbers 배열의 각 요소에 대해 콜백 함수 실행 
numbers.forEach(function (num) { 
    doubled.push(num * 2); // 콜백 함수로 각 요소를 두 배로 곱해서 doubled 배열에 추가 
}); 

console.log(doubled); // [2, 4, 6, 8, 10]

🖍️🖍️ 애니메이션

jQuery에서 제공하는 애니메이션 메서드들은 애니메이션이 끝난 후에 실행할 콜백 함수를 인자로 받는다.

// jQuery의 slideUp 메서드를 사용하여 #box 요소를 숨기고 콜백 함수로 콘솔에 메시지 출력
$("#box").slideUp(1000, function () {
  console.log("Animation completed!"); // 콜백 함수로 콘솔에 메시지 출력
});


🚨콜백함수 주의점

⚠️ this를 사용한 콜백함수

콜백함수가 this객체를 사용하는 메서드인 경우에는 반드시 this객체의 컨택스트를 보호할 수 있도록 콜백함수를 수정해야 한다.

let userData = {
    signUp: '2021-4-06 12:00:00',
    name: 'Not Set',
    setName: function(firstName, lastName) {
        this.name = firstName + ' ' + lastName;
    }
}

function getUserName(firstName, lastName, callback) {
    callback(firstName, lastName);
}

getUserName('홍', '길동', userData.setName);

console.log('1: ', userData.name); // Not Set
console.log('2: ', window.name); // 홍 길동

getUserName 함수를 실행한 후 실행 첫 번째 콘솔의 값이 '홍 길동' 이기를 기대했지만, Not Set이 출력되는 걸 볼 수 있다.
왜냐하면 userData 객체의 setName 프로퍼티 함수 내부에서 사용된 this.name 이 userData 객체의 name을 가리키는게 아니라 전역 객체 window 의 name을 가리키기 때문.

콜백 함수 this가 전역 객체인 이유
콜백 함수 this 해결 방안


🖍️ 콜백함수는 클로저다

콜백함수는 콜백함수를 포함한 함수 내부의 인자에 접근이 가능하고 심지어 전역변수에도 접근이 가능한 상태가 됩니다. 즉, 기존의 함수가 가진 스코프에 새로운 내부 스코프가 추가가 되는 것입니다.

이로 인해 발생하는 이슈가 있는데 자세한 내용은 추후 공부.

클로저는 포함하고 있는 함수의 스코프에 접근을 할수 있습니다. 그래서 콜백함수는 포함하고 있는 함수의 변수에 접근이 가능하고 심지어 전역변수에도 접근이 가능합니다.



REFERENCE

자바스크립트 비동기 처리와 콜백 함수
📚 콜백 함수(Callback) 개념 & 응용 - 완벽 정리
자바스크립트의 콜백함수 이해하기! _ v2
JavaScript Callback Functions – What are Callbacks in JS and How to Use Them

0개의 댓글