[JS] 콜백 함수

Pavel_Dmr·2022년 6월 23일
0

JavaScript

목록 보기
6/9
post-thumbnail

🍝 콜백함수란

콜백은 간단히 말하면 함수 안에서 실행하는 또 다른 함수이다.
또 다른 함수를 만들 때 인풋(Parameter)을 함수로 받아서 사용할 수 있는데, 이 때 인자로 사용되는 함수를 말한다.

즉, 파라미터로 변수가 아닌 함수롤 전달하는 것을 말하며,또한 함수이름 없이(무명) 익명으로도 전달 가능한 함수를 일컫는다.

function introduce (lastName, firstName, callback) {
    var fullName = lastName + firstName;
    
    callback(fullName);
}
//함수 선언식
introduce("김", "무무", function(name) {
    console.log(name);
});
//화살표 함수(람다식),함수 표현식(리터럴)
introduce("김","상무",name =>{
  console.log(name);
});
// 결과 -> 김무무
// 결과 -> 김상무

introduce 함수에서는 var fullName 변수을 선언해서 callback 함수에 파라미터로 인자을 전달하는데 해당 인자를 파라미터로 받은 함수는 console.log로 해당 인자를 출력한다.

introduce에 그냥 console.log을 추가하면되는데 왜 이렇게 번거롭게 하는걸까?

콜백이 유용한 이유는, 콜백 함수만을 바꿔줌으로서 하나의 함수를 다채롭게 응용 할 수 있기 때문이다.

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);
// 결과 -> 지금까지 김무무이었습니다. 안녕히계세요

callback 함수을 파라미터를 이렇게 사용하게 되면, introduce 함수하나로 다양한 동작이 가능하게 되고, introduce을 기능용도에 따라 수정하거나, 재정의할 필요 없이 사용이 가능하다.

이런식으로 함수를 나눠줌으로써 코드를 재활용하고, 관리을 용이하게 할수 있다.

콜백 자체는 코드를 더 읽기 편하고 용이하게 해주지만, 과한 콜백 사용은 디버깅이 어렵기 때문에, 적절하게 사용하는 것이 중요하다.


🥨 콜백함수 사용법

함수 리터럴,화살표 함수 사용

let number = [1, 2, 3, 4, 5];

//함수 표현식,리터럴
number.forEach(function(x) 
{
  	console.log(x * 2);
});

//화살표 함수
number.forEach((x) => {
  console.log(x * 2);
});

재사용이 필요없는 용도의 기능수행의 경우에 함수내에 리터럴 또는 화살표(람다식) 함수을 이용하여 콜백함수을 사용 할 수 있다.

함수 선언식을 파라미터로 넘기기

function Dog_Name(name, callback) {
  console.log("이름: ", name);
  callback();
}

function Finish_Func() {
  console.log("함수 종료");
}

Dog_Name("겨울이", Finish_Func);

/*
name: 겨울이
함수 종료
*/

선언된 함수를 파라미터로 전달합니다. 자바스크립트가 null과 underfined 타입을 제외하고 제외하고 모든 것을 객체로 다루기 때문에(원시 타입도 일시적으로 객체로 다룰 수 있다).

함수를 변수 or 다른 함수의 변수처럼 사용할 수 있다.
함수를 콜백함수로 사용할 경우, 함수의 이름만 넘겨주면 된다.
참고로 함수 선언식을 인자로 넘길때는 괄호()는 쓰면 안된다. 타입에러가 난다.

전역변수, 지역변수를 콜백함수의 파라미터로 전달

let drink = "orange juice"; // 전역 변수

function Today_Food(callback) {
  let food = "pizza"; // 지역 변수
  callback(food);
}

function eat(food) {
  console.log(`음료: ${drink} / 음식: ${food}`);
}

Today_Food(eat);
 
// 음료: orange juice / 음식: pizza

전역변수는 그냥 불러오면 되고.. 지역변수는 위 예제처럼 콜백함수의 파라미터로 넣어주면 되겠다.


🥮 콜백함수 사용시 유의점

this를 사용한 콜백함수

let User_Data = {
  name: "None",
  setName: function (firstName, lastName) {
    this.name = firstName + " " + lastName;
  },
};

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

Get_User_Name('김', '무무', User_Data.setName);

console.log(User_Data.name); // None
console.log(window.name); // 김 무무

User_Data.name이 김 무무가 나올 거 같지만, 콜백함수는 기본적으로 콜 바이 밸류기 때문에 메소드 외 다른 변수에 값을 선언해 줄 수가 없다. 또한 메소드을 통해 접근한 this.name은 window 전역변수로 참조되어서 window 객체의 name 프로퍼티가 김 무무로 바뀌었다.

따라서 원하는대로 객체 User_Data의 프로퍼티 name을 수정하고 싶으면, 메소드에서 User_Data 객체에 접근 할 수 있도록 해주어야한다.

Function.prototype 메서드인 call() 이나 apply()을 쓰면 코드에 this을 사용할 때 원하는 객체을 지정해 줄수 있다. 첫번째 인자로 객체로 지정해주면 this로 접근 했을때, 지정해준 객체로 인식이 된다.

let User_Data = {
  name: "None",
  setName: function (firstName, lastName) {
    this.name = firstName + " " + lastName;
  },
};

function Get_User_Name(firstName, lastName, callback,obj) {
  callback.call(obj,firstName, lastName);
}

Get_User_Name('김', '무무', User_Data.setName,User_Data);

console.log(User_Data.name); // 김 무무
let User_Data = {
  name: "None",
  setName: function (firstName, lastName) {
    this.name = firstName + " " + lastName;
  },
};

function Get_User_Name(firstName, lastName, callback,obj) {
  callback.apply(obj,[firstName, lastName]);
}

Get_User_Name('김', '무무', User_Data.setName,User_Data);

console.log(User_Data.name); // 김 무무

this을 참조할 때,첫번째 인자이자 객체인 obj에 접근해 값을 수정해줘서 프로퍼티가 제대로 수정이 된다.


🧇 콜백 지옥

비동기 호출이 빈번한 소스코드에 경우 콜백 지옥이 발생 할 수 있다.
콜백 지옥은 함수의 매개변수로 넘겨지는 콜백 함수가 반복되어, 들여쓰기,가독성 및 관리가 감당하기 힘들어지는 현상이다.

function increase(number,callback){
  setTimeout(() =>{
     const result =  number+10;
        if(callback){
            callback(result);
        }
    },1000);
}
increase(1,result=>{
    console.log(result);
})
// 아래는 콜백지옥...
console.log("작업시작");
increase(0,result=>{
    console.log(result);
    increase(result,result=>{
        console.log(result);
        increase(result,result=>{
            console.log(result);
            increase(result,result=>{
                console.log(result);
                increase(result,result=>{
                    console.log(result);
                    increase(result,result=>{
                        console.log(result);
                        increase(result,result=>{
                            console.log(result);
                            console.log('작업완료');
                        })
                    })
                })
            })
        })
    })
})

보기만 해도 어지럽다. 그러면 이런 반복을 줄이고, 가독성을 늘릴 려면 어떻게 해야할까.
비동기 관련 객체,메소드를 사용하면 이러한 코드을 최적화 할수 있다.

profile
노는게 좋아

0개의 댓글