[비동기 프로그래밍] - 동기적 처리와 비동기적 처리

Donggu(oo)·2022년 12월 4일
0

JavaScript

목록 보기
42/49
post-thumbnail

1. 동기와 비동기의 차이


1) 동기(Synchronous)적 처리

  • 동기적 처리 방식은 직렬 형태로 작업을 수행한다.

  • 동기적 처리 방식은 태스크를 순서대로 하나씩 처리하므로 실행 순서가 보장된다는 장점이 있지만, 앞선 태스크가 종료할 때까지 이후 태스크들이 블로킹(blocking) 되므로 시간이 오래 걸린다는 단점이 있다.

// 출력 순서
// 1. '첫째(실행 후 즉시 출력)' -> 2. '둘째(실행 후 즉시 출력)' -> 3. '셋째(실행 후 즉시 출력)'
// -> 4. '네째(실행 후 즉시 출력)'

console.log('첫째');  // 동기

console.log('둘째');  // 동기

console.log('셋째');  // 동기

console.log('네째');  // 동기
  • 아래는 Promise를 사용하여 비동기적으로 실행되는 처리를 동기적(직렬, blocking)으로 실행되도록 한 예제다.
    (시간은 오래 걸리지만(6초) 순서가 보장된다)
// 출력 순서
// 1. 실행 후 3초 뒤 'A' 출력 -> 2. 'A'가 출력 되고 2초 뒤 'B' 출력 ->
// 3. 'B'가 출력 되고 1초 뒤 'C' 출력 

const data1 = () => new Promise(resolve => setTimeout(() => resolve('A'), 3000));
const data2 = () => new Promise(resolve => setTimeout(() => resolve('B'), 2000));
const data3 = () => new Promise(resolve => setTimeout(() => resolve('C'), 1000));

data1()
  .then(data => {
    console.log(data)
    return data2()
  })
  .then(data => {
    console.log(data)
    return data3()
  })
  .then(data => {
    console.log(data)
  })  // A -> B -> C

// 위와 같은 결과가 나오지만 콜백 헬의 형태를 띄고 있다.
// data1()
//   .then(data => {
//     console.log(data)
//     data2().then(data => {
//       console.log(data)
//       data3().then(data => {
//         console.log(data)
//       })
//     })
//   })

2) 비동기(Asynchronous)적 처리

  • 비동기적 처리 방식은 병렬 형태로 작업을 수행한다.

  • 비동기적 처리 방식은 현재 실행 중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하므로 블로킹이 발생하지 않는(non-blocking)다는 장점이 있지만, 태스크의 실행 순서가 보장되지 않는 단점이 있다.

// 출력 순서
// 1. '첫째(실행 후 즉시 출력)' -> 2. '셋째(실행 후 즉시 출력)' -> 3. '네째(실행 후 3초 뒤 출력)'
// -> 4. '둘째(실행 후 5초 뒤 출력)'

console.log('첫째');  // 동기

setTimeout(() => console.log("둘째"), 5000);  // 비동기

console.log('셋째');  // 동기

setTimeout(() => console.log('넷째'), 3000)  // 비동기
  • 아래는 Promise를 사용하여 비동기적으로 실행되는 처리를 비동기적(병렬, non-blocking)으로 실행되도록 한 예제다.
    (시간은 짧게 걸리지만(3초) 순서가 보장되지 않는다)
// 출력 순서
// 1. 실행 후 1초 뒤 'C' 출력 -> 2. 'C'가 출력 되고 2초 뒤 'B' 출력 ->
// 3. 'B'가 출력 되고 3초 뒤 'A' 출력 

const data1 = () => new Promise(resolve => setTimeout(() => resolve('A'), 3000));
const data2 = () => new Promise(resolve => setTimeout(() => resolve('B'), 2000));
const data3 = () => new Promise(resolve => setTimeout(() => resolve('C'), 1000));

data1()
  .then(data => {
    console.log(data)
  })
data2()
  .then(data => {
    console.log(data)
  })
data3()
  .then(data => {
    console.log(data)
  })  // C -> B -> A

2. 비동기 처리를 위한 콜백 패턴의 단점


  • 자바스크립트는 비동기 처리를 위한 하나의 패턴으로 콜백 함수를 사용한다. 하지만 전통적인 콜백 패턴은 콜백 헬로 인해 가독성이 나쁘고 비동기 처리 중 발생한 에러의 처리가 곤란하며 여러 개의 비동기 처리를 한 번에 처리하는 데도 한계가 있다.

1) 콜백 헬(Callback Hell)


  • 콜벡 헬이란 콜백 함수를 통해 비동기 처리 결과에 대한 후속 처리를 수행하는 비동기 함수가 비동기 처리 결과를 가지고 또다시 비동기 함수를 호출해야 한다면 콜백 함수 호출이 중첩되어 복잡도가 높아지는 현상을 말한다.

  • 콜백 헬은 비동기적인 작업을 동기적인 순서로 실행하려고 했을 때 발생한다. (비동기 작업을 동기적으로 처리할 때 콜백 함수를 사용한다.)

// 출력 순서
// 1. 실행 후 3초 뒤 '첫째' 출력 -> 2. '첫째'가 출력 되고 2초 뒤 '둘째' 출력 ->
// 3. '둘째'가 출력 되고 4초 뒤 '셋째' 출력 -> 4. '셋째'가 출력 되고 1초 뒤 '네째' 출력

setTimeout(function () {
    console.log('첫째');
    setTimeout(function () {
        console.log('둘째');
        setTimeout(function () {
            console.log('셋째');
            setTimeout(function () {
                console.log('네째');
            }, 1000);
        }, 4000);
    }, 2000);
}, 3000)

1) 에러 처리(Error Handling)

  • 비동기 처리를 위한 콜백 패턴의 문제점들 중 가장 큰 문제점은 에러 처리가 곤란하다는 것이다.
const getDataFromFile = function (filePath, callback) {
  setTimeout(function (err, data) {
    if (data) {  // 정상 처리 시
      callback(null, data)
    } else {  // 에러 발생 시
      callback(err, null)
    }
  })
};

getDataFromFile(function (err, data) {
  console.log(data)
});

0개의 댓글