비동기처리 / 콜백 함수
비동기처리(Asynchronous)
정의
- 특정 코드의 연산이
끝날 때까지 코드의 실행을 멈추지 않고
다음 코드를 먼저 실행하는 자바스크립트의 특성이다.
작업 처리 단위(transaction)
를 동시에 맞추지 않아도 된다.
- javascript의 가장 흔한 비동기처리로는
JQeury의 ajax
가 있다.
- 프론트에 보여지는 데이터 혹은 이미지는
서버
에서 불러오게 된다. 프론트에서 필요한 것들을 불러올 때 바로 ajax
통신을 사용해서 불러오게 된다.
동기처리와의 차이점
동기처리 (synchronous)
- 요청과 그 결과가 동시에 일어난다.
작업 처리 단위(transaction)
를 동시에 맞춘다.
- 즉,
시간이 얼마가 걸리던
요청이 오게 되면 이에 대한 결과를 낸 후에 다음 단계로
나아가는 것이다.
- 동기처리의 예시로는
은행의 송금 시스템
을 생각하면 될 것 같다.
- 은행 어플을 통해 내가 친구에게 송금을 하는 데 다른 작업 처리할 것이 있다고 송금되는 과정을 멈추면 안될 것이다.
- 비동기처리의 예시로는
시험 날의 학생과 선생님
을 생각하면 될 것 같다.
- 학생이 시험지를 다 풀고 건넨 뒤 선생님이 시험지를 채점할 것이다.
- 학생은 시험지가 채점이 전부 끝난 뒤에야 시험지를 확인할 수 있다.
- 학생을 프론트앤드, 선생님을 백앤드로 생각해보면 백앤드에서 학생이 원하는 데이터에 대한 처리가 이루어져야 프론트앤드에서 해당 데이터를 사용자에게 반환할 수 있는 것이다.
동기처리와 비동기처리의 장단점
예시 1
- 이전에 flask를 할 때 사용했던 jquery의 ajax 코드를 한 번 살펴보도록 하자.
function dollar_won() {
$.ajax({
type: "GET",
url: "http://spartacodingclub.shop/sparta_api/rate",
data: {},
success: function (response) {
let rate = response['rate']
$('#rating').text(rate)
}
})
}
- 위의 코드는 현재 환율 정보를 불러오는 함수이다.
$.ajax
를 통해 ajax 통신을 하게 된다.
- 어떤 method로 정보를 가져올 것인지
- 어떤 url에서 정보를 가져올 것인지
- 어떤 data를 가져올 것인지
- 현재는 GET 타입이므로 굳이 가져올 데이터를 작성하지 않았다.
- 만약 ajax 통신이 성공한다면 어떻게 할 것인지
- 통신에 성공한다면
response
에 데이터들을 입력하고
- response의
rate
에 담겨있는 정보를 rate 변수에 저장하며
rating
을 id 값으로 갖고 있는 프론트의 요소에 text 값으로 rate에 담겨있는 값을 반영시켜준다.
- 만약 로직의 실행이 끝나지 않았다면 어떤 값을 반환할까?
- 그런데 생각을 해보면 프론트앤드의 html에 정보를 반영하게 될 때, 해당 함수에서 에러가 나거나 반환값이 없다해서 다른 값들에 값이 들어가지 않고 해당 response가 해결될 때까지 기다리지 않는다.
- 해당 로직에서 문제가 생긴다면 해당 로직만 내버려두고 나머지 부분에 대한 데이터 처리는 신속하게 잘 이루어지는 것을 볼 수 있었다.
예시 2
- 참고 블로그 : setTimeout()
setTimeout()
함수는 코드를 바로 실행하지 않고 지정한 시간만큼 기다렸다가
해당 함수 안에 선언되어 있는 코드를 실행하는 함수이다.
- 간단한 예시는 아래와 같다.
console.log('손흥민은 이번에');
setTimeout(function() {
console.log('아시아인 최초로 받았다.');
}, 3000);
console.log('EPL 골든부츠를');
- 아래 코드를 devtool의 콘솔에서 실행해 보았다.
- 비동기로 인해 3초의 대기시간동안
undefined
가 생긴 것을 볼 수 있다.그 후 setTimeout()
함수 안에 존재하는 console.log('아시아인 최초로 받았다.')
가 찍힌 것을 볼 수 있다.
필요성
- 여기서 우리는
비동기처리
의 필요성을 볼 수 있다.
- 프론트에서 서버로 데이터를 요청했을 때 서버가 언제 그 요청에 대한 응답을 줄지도 모르는데 마냥 다른 코드를 실행 안 하고 기다릴 순 없지 않은가?
비동기처리
는 완료가 되지 않는 코드들에 대해 데이터를 반환받기 전까지 대기
하도록 조치하고 다음 부분으로 넘어가 실행하게 한다.
- 만약 동기처리였다면 순서에 따라 코드가 실행 완료될 때까지 기다려 서비스에 많은 영향을 줄 것이다.
콜백 함수(Callback)
정의
- 이름 그대로
나중에 콜(호출)이 되는
함수이다.
- 코드를 통해 명시적으로 호출하는 함수가 아니라
단지 함수를 동록
하기만 하고, 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출
하는 함수이다.
- 즉, 어떤 특이한 형태가 있는 함수가 아니라
호출방식
에 의해 구분되는 함수이다.
- javascript의 비동기적 메커니즘 중 오래된 녀석이다.
예시
- 위에서 예시로 들었던 환율 정보를 불러오는 함수에 콜백함수를 더해보도록 하겠다.
- 만약 환율정보를 불러오는데 시간이 좀 걸린다고 가정하겠다.
function dollar_won() {
$.ajax({
type: "GET",
url: "http://spartacodingclub.shop/sparta_api/rate",
data: {},
success: function (response) {
callback(response);
let rate = response['rate']
$('#rating').text(rate)
}
})
}
- 현재 콜백함수의 기능을 정하지는 않았지만, 만약 해당 함수에
alert
등을 넣어서 사용자가 멍하니 앉아 값이 나올 때까지 기다리는 동안(물론 동기처리보다는 덜하겠지만) 어떤 과정이 처리되고 있는지 알람창
을 띄우게 된다면 사용자는 이것을 꺼야하므로 일부러 시간을 지연
시킬 수 있을 것이다.
문제점
콜백지옥
- 비동기 처리 로직을 위해
콜백 함수를 연속해서 사용할 때 발생
하는 문제$.get('url', function(response) {
callback1(response, function(id) {
callback2(id, function(result) {
callback3(result, function(text) {
console.log(text);
});
});
});
});
Promise
또는 async await
등으로 해결할 수 있다.
- 또는 각 콜백 함수들을 분리해주는 방법을 통해 해결할 수 있다.
function callback1Done(id) {
callback2(id, authDone);
}
function callback2Done(result) {
callback3(result, displayDone);
}
function callback3Done(text) {
console.log(text);
}
$.get('url', function(response) {
callback1(response, callback1Done);
});