javascript - 비동기 처리와 콜백 함수

김형석·2022년 8월 7일
0

개념공부 스터디

목록 보기
16/27

비동기 처리

자바스크립트의 비동기 처리란 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성을 의미한다.

비동기 처리의 첫 번째 사례

비동기 처리의 가장 흔한 사례는 제이쿼리의 ajax이다. 제이쿼리로 실제 웹서비스를 개발할 때 ajax 통신을 빼놓을 수 가 없다. 보통 화면에 표시할 이미지나 데이터를 서버에서 불러와 표시해야 하는데 이때 ajax 통신으로 해당 데이터를 서버로부터 가져올 수 있기 때문이다.

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

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

여기서 $.get()이 ajax 통신을 하는 부분이다. https://domain.com 에다가 HTTP GET 요청을 날려 1번 상품(product) 정보를 요청하는 코드이다. 쉽게 말하면 지정된 URL에 '데이터를 하나 보내주세요'라는 요청을 날리는 것과 같다.

그렇게 서버에서 받아온 데이터는 response 인자에 담긴다. 그리고 tableData = response; 코드로 받아온 데이터를 tableData 라는 변수에 저장한다. 그럼 이제 getData()를 호출하면 어떻게 될까? 받아온 데이터가 뭐든 일단 뭔가 찍혀야한다. 근데 결과는 맨 아래에서 보는 것처럼 undefined이다. 왜 그럴까?

그 이유는 $.get()로 데이터를 요청하고 받아올 때까지 기다려주지 않고 다음 코드인 return tableData;를 실행했기 때문이다. 따라서 getData()이 결과 값은 초기 값을 설정하지 않은 tableData의 값 undefined를 출력한다.

이렇게 특정 로직의 실행이 끝날 때까지 기다려주지 않고 나머지 코드를 먼저 실행하는 것이 비동기 처리이다. 자바스크립트에서 비동기 처리가 필요한 이유를 생각해보면, 화면에서 서버로 데이터를 요청했을 때 서버가 언제 그 요청에 대한 응답을 줄지도 모르는데 마냥 다른 코드를 실행 안 하고 기다릴 순 없기 때문이다.

비동기 처리의 두 번째 사례

또 다른 비동기 처리 사례는 setTimeout()이다. setTimeout()은 Web API의 한 종류이다. 코드를 바로 실행하지 않고 지정한 시간만큼 기다렸다가 로직을 실행한다.

// #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() 역시 비동기 방식으로 실행되기 때문에 3초를 기다렸다가 다음 코드를 수행하는 것이 아니라 일단 setTimeout()을 실행하고 나서 바로 다음 코드인 console.log('Hello Again')으로 넘어간다.

콜백 함수로 비동기 처리 방식의 문제점 해결하기

앞에서 자바스크립트 비동기 처리 방ㅅ기에 의해 야기될 수 있는 문제점들을 보았다. 이러한 문제들을 어떻게 해결할 수 있을까? 바로 콜백(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);
});

위와 같은 코딩 패턴으로도 콜백 지옥을 해결할 수 있지만 Promise나 Async를 이용하면 더 편하게 구현할 수 있다.

출처 : 캡핀판교

profile
블로그 이사 : https://hengxi.tistory.com

0개의 댓글