하루에 한 문제

CallBack 함수란? 본문

Dev/JavaScript

CallBack 함수란?

dkwjdi 2021. 4. 2. 01:45

우선 간단하게 설명해보자면

 

전자레인지에 핫바를 돌린다고 해보자.

대부분은 전자레인지에 핫바를 넣어넣고 다른일을 하다가 전자레인지가 시간이 다되면 띵 하는 소리를 듣고 핫바를 꺼낼것이다.

 

즉, 어떤 일을 다른 객체에게 시켜놓고, 그 일이 끝날때까지 멍하니 기다리는게 아니라 그 객체가 나에게 다시 알려줄때 까지 내 할일을 하는것이다!

 

따라서 Non-Block이며, 비동기방식의 함수로 사용된다는 것을 알 수 있다.

 

 

비동기 함수의 예

setTimeout()은 코드를 바로 실행하지 않고 지정한 시간만큼 기다렸다가 로직을 실행한다. 

// #1
console.log('Hello');
// #2
setTimeout(function() {
	console.log('Bye');
}, 3000);
// #3
console.log('Hello Again');

출력이 어떻게 나올까??? 비동기에 대한 개념이 없다면

1. Hello

2. 3초 있다가 Bye

3. Hello Again

이라고 생각하기 쉽다.

 

하지만 결과는

1. Hello

2. Hello Again

3. 3초 있다가 Bye

으로 나오게 된다!! 즉.. setTimeout()은 비동기로 처리된다!

 

아 그런데 갑자기 생각난건데 위의 setTimeout은 여러가지 방법으로 사용할 수 있다

setTimeout(() => { console.log("hello") }, 2000);

setTimeout(function () {
     console.log("hello")
}, 2000);


function hello() {
    console.log("hello");
}

setTimeout(hello, 2000);

 

ajax, axios 등 비동기 통신을 하다 보면 비동기때문에 머리아픈 경우가 많다.

function getData() {
	var tableData;
	$.get('https://domain.com/products/1', function(response) {
		tableData = response;
	});
	return tableData;
}

console.log(getData()); // undefined

 

https://domain.com 에다가 HTTP GET 요청을 날려 1번 상품(product) 정보를 요청하고 결과를 response에 담고

tableData = response; 를 통해 결과를 tableData에 담는다!

 

이 함수를 console.log()를 통해 출력하면 어떻게 될까?? 뭐가 찍힐까???

답은 undefined가 찍힌다!!!!

이유는 $.get()으로 데이터를 요청하고 받을 때 까지 기다리지 않고 console.log()를 실행해버리기 때문이다...

이런 문제점을 어떻게 해결할 수 있을까??

 

 

CallBack함수로 해결가능하다.

 

대표적인 콜백함수의 예로는 자바스크립트에서의 이벤트 핸들러 처리이다!

window.onload = function () {
    alert("hello")
}

  • window.onload이벤트 헨들러는 웹 페이지의 로딩이 끝나는 시점에 이벤트가 발생한다.
  • 익명 함수가 콜백함수로 등록된 것을 볼 수 있다.

 

또 다른 예를 보면 함수안에 매개변수로 넣어서 사용하는 형태가 있다.

mul = function (a, b, callback) {
    let result = a * b;
    callback(result);
}

mul(5, 5, function (res){
    console.log(res);
})

먼저 mul이라는 함수를 선언하고, a,b,callback을 받는다.

여기서 callback은 다른이름으로 바꿔도 상관없다.

 

이때 밑에서 mul(5,5,function(res){......}) 를 호출하게 되면

위의 함수로 가서 5*5를 한 뒤 callback의 변수로 보내게 된다.

 

그럼 위의 ajax코드를 한번 콜백함수로 작성해보자!

function getData(callbackFunc) {
	$.get('https://domain.com/products/1', function(response) {
		callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
	});
}

getData(function(tableData) {
	console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});

이렇게 콜백 함수를 사용하면 특정 로직이 끝났을 때 원하는 동작을 실행시킬 수 있다는 말~

 

 

콜백 지옥(Callback hell)

콜백 지옥은 비동기 처리 로직을 위해 콜백 함수를 연속해서 발생하는 문제다. 

$.get('url', function(response) {
	parseValue(response, function(id) {
		auth(id, function(result) {
			display(result, function(text) {
				console.log(text);
			});
		});
	});
});

웹 서비스를 개발하다 보면 서버에서 데이터를 받아와 화면에 표시하기까지 인코딩, 사용자 인증 등을 처리해야 하는 경우가 많다. 만약 이 모든 과정을 비동기로 처리해야 한다고 하면 위와 같이 콜백 안에 콜백을 계속 무는 형식으로 코딩을 하게 되는데.. 이러한 코드 구조는 가독성도 떨어지고 로직을 변경하기도 어렵다!! 

 

그럼 콜백 지옥을 해결하기 위해서는 ???

일반적으로 콜백 지옥을 해결하는 방법에는 Promise나 Async를 사용하는 방법이 있다. 만약 코딩 패턴으로만 콜백 지옥을 해결하려면 아래와 같이 각 콜백 함수를 자알 분리하면된다 ㅎ

function parseValueDone(id) {
	auth(id, authDone);
}
function authDone(result) {
	display(result, displayDone);
}
function displayDone(text) {
	console.log(text);
}
$.get('url', function(response) {
	parseValue(response, parseValueDone);
});

위 코드는 앞의 콜백 지옥 예시를 개선한 코드다. 중첩해서 선언했던 콜백 익명 함수를 각각의 함수로 구분함으로써 정리를 하였다.

1. ajax 통신으로 받은 데이터를 이용해 parseValue() 메서드를 실행

2. response가 id가 전달되고 auth() 메서드가 실행

3. auth() 메서드로 인증을 거치고 나면 콜백 함수 authDone()이 실행

4, 인증 결과 값인 result로 display()를 호출하면 마지막으로 displayDone() 메서드가 수행되면서 text가 콘솔에 출력

 

 

이어서 async promise.....

 

 

 

참고

medium.com/@oasis9217/%EB%B2%88%EC%97%AD-javascript-%EB%8F%84%EB%8C%80%EC%B2%B4-%EC%BD%9C%EB%B0%B1%EC%9D%B4-%EB%AD%94%EB%8D%B0-65bb82556c56

joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/

www.hanumoka.net/2018/10/24/javascript-20181024-javascript-callback/

dalkomit.tistory.com/65

'Dev > JavaScript' 카테고리의 다른 글

함수정의  (0) 2021.04.07
자바스크립트 데이터 타입  (0) 2021.04.06
익명함수 & 즉시 실행 함수 & 내부함수  (0) 2021.04.04
호이스팅  (0) 2021.04.04
var, let, const  (0) 2021.04.04
Comments