자바스크립트 비동기 처리와 콜백 함수

Kzero·2020년 7월 14일
0

Javascript

목록 보기
1/3

비동기 처리

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

예를들어, 웹 어플리케이션에서 서버 쪽 데이터가 필요할 때는 Ajax 기법을 사용하여 서버의 API를 호출함으로써 데이터를 수신합니다. 이렇게 서버의 API를 사용해야 할 때는 네트워크 송수신 과정에서 시간이 걸리기 때문에 작업이 즉시 처리되는 것이 아니라, 응답을 받을 때까지 기다렸다가 전달받은 응답데이터를 처리합니다. 이 과정에서 해당 작업을 비동기적으로 처리하게 됩니다.

비동기 처리 사례 1

제이쿼리의 ajax입니다.

function fetchData() {
  let result;
  $.get('https://jsonplaceholder.typicode.com/todos/1', function(response){
    result = response;
  })
  return result;
}

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

여기서 $.get()이 ajax 통신을 하는 부분입니다. 지정된 URL(https://jsonplaceholder.typicode.com/todos/1)에 데이터 요청을 하고 받아온 데이터가 response에 담기고 result = response; 코드로 받아온 데이터를 result에 저장합니다.

그럼 이제 fetchData()를 호출 하면 값이 나와야 하는데 undefined이 출력됩니다. 왜 그럴까요?

이유는 $.get()로 데이터를 요청하고 받아올 때까지 기다리지 않고 다음 코드인 return result;를 실행했기 때문에 undefined이 출력됩니다.

이렇게 특정 로직의 실행이 끝날 때까지 기다려주지 않고 다음 코드를 실행하는 것이 비동기 처리입니다.

비동기 처리 사례 2

setTimeout()은 Web API의 한 종류입니다. 코드를 바로 실행하지 않고 지정한 시간만큼 기다렸다가 로직을 실행합니다

// #1
console.log('1');

// #2
setTimeout(function() {
  console.log('2');
},3000)

// #3
console.log('3');

비동기 처리를 모르는 사람이 보면 위의 코드는 '1' -> 3초후 '2' -> '3' 순으로 출력된다고 생각할 수 있습니다.

하지만, 실제 결과값은 '1' -> '3' -> 3초 후 '2'가 출력됩니다.

setTimeout()는 비동기 방식으로 실행되기 때문에 3초를 기다렸다가 다음 코드를 수행하는 것이 아니라 일단 setTimeout()을 실행하고 나서 바로 다음 코드인 console.log(3);으로 넘어갔습니다. 따라서, '1', '3'을 먼저 출력하고 3초가 지나면 ‘2’가 출력됩니다.

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

위에서의 비동기 처리 방식으로 인한 문제들을 해결할 수 있는 방법은 바로 콜백함수를 사용하는 것입니다.

위의 비동기 처리 사례 1의 코드를 콜백함수를 이용하여 수정해 보았습니다.

function fetchData(callback) {
    $.get('https://jsonplaceholder.typicode.com/todos/1', function(response){
      callback(response); // 서버에서 받아온 데이터(response)를 콜백함수에 넘겨줍니다. 
    });
}

fetchData(function(receivedData) { // $.get()의 response값이 receivedData에 전달됨
  console.log(receivedData); 
  // Object {userId: 1, id: 1, title: "delectus aut autem", completed: false}
})

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

콜백함수의 문제점 (콜백지옥)

1초에 걸쳐서 10, 20, 30, 40 과 같은 형태로 여러 번 순차적으로 처리하고 싶다면 콜백함수를 중첩해서 사용 할 수 있습니다.

function increase(number, callback) {
  setTimeout(() => {
    const result = number + 10;
    if(callback) {
      callback(result);
    }
  },1000)
}

console.log('시작!')
increase(0, first => {
  console.log(first);
  increase(first, second => {
    console.log(second);
    increase(second, third => {
      console.log(third);
      increase(third,  fourth => {
        console.log(fourth);
        console.log('끝!');
      })
    })
  })
})

결과로 아래와 같이 출력됩니다.

  • 시작!
  • 10
  • 20
  • 30
  • 40
  • 끝!

이러한 코드는 가독성도 떨어지고 로직을 변경하기도 어렵습니다.
이와 같은 구조를 콜백지옥(Callback Hell) 이라고 합니다.
웬만하면 지양해야하는 코드입니다.

콜백지옥을 해결하는 방법

일반적으로 콜백 지옥을 해결하는 방법에는 PromiseAsync & Await를 사용하는 방법이 있습니다.

참고

profile
개발 공부 노트

0개의 댓글