💡깨달음💡/Javascript

동기와 비동기의 차이

과부하가즈아 2023. 10. 5. 19:53

동기(Synchronous)와 비동기(Asynchronous)

동기는 '직렬적'으로 작동하는 방식이고 비동기는 '병렬적'으로 작동하는 방식이다.

(즉, 비동기란 특정 코드가 끝날때 까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 것을 의미한다.)

왼쪽 차트는 '비동기'로 작동하는 방식이다. 한번에 여러 태스크가 동시에 병렬적으로 실행된다. 반면, 오른쪽 차트는 '동기'적으로 작동하는 방식이다. 하나의 태스크가 끝날 때 까지 기다렸다가 다음 태스크가 실행된다. 총 실행 시간으로 따지자면 '동기' 방식이 더 느리다.

동기적예시
console.log(1)
console.log(2)
console.log(3)​
비동기적예시
console.log(1);
setTimeout(function () {
  console.log(2);
}, 1000);
console.log(3);​

✔️비동기적 코드의 실행 결과는 동기적 코드가 전부 실행 되고나서 값을 반환한다.

첫번째 줄에서 console.log("1st");를 만나고 콘솔에 1st를 찍는다.
두번째 줄에서 setTimeout() 메소드를 만나서 해당 매소드가 비동기적 매소드이기 때문에 이를 처리하는 다른 프로그램에 맡긴다.
그러고 나서 곧바로 console.log("3rd")를 콘솔에 찍는다.
setTimeOut() 메소드를 처리하는 프로그램은 비동기적 API를 제외한 모든 코드가 실행 된 이후 결과를 콘솔에 찍는다.


동기는 디자인이 비동기보다 간단하고 직관적일수 있지만 결과가 주어질 때 까지 아무것도 못하고 대기해야하는 문제가 있다. 비동기는 동기보다 복잡하지만 결과가 주어지는데 시간이 걸려도 그 시간동안 다른 작업을 할 수 있어서 보다 효율적일 수 있다.

 

동기(synchronous)

동기식 처리 모델(Synchronous processing model)은 직렬적으로 태스크(task)를 수행한다.

즉, 태스크는 순차적으로 실행되며 어떤 작업이 수행 중이면 다음 태스크는 대기하게 된다.

 

예를 들어 서버에서 데이터를 가져와서 화면에 표시하는 태스크를 수행할 때, 서버에 데이터를 요청하고 데이터가 응답될 때까지 이후의 태스크들은 블로킹된다.

 

실제로 cpu가 느려지는 것은 아니지만 시스템의 전체적인 효율이 저하된다고 할 수 있다.


비동기(asynchronous)

비동기식 처리 모델(Asynchronous processing model 또는 Non-Blocking processing model)은 병렬적으로 태스크를 수행한다.

즉, 태스크가 종료되지 않은 상태라 하더라도 대기하지 않고 즉시 다음 태스크를 실행한다.

 

예를 들어 서버에서 데이터를 가져와서 화면에 표시하는 태스크를 수행할 때, 서버에 데이터를 요청한 이후 서버로부터 데이터가 응답될 때까지 대기하지 않고(Non-Blocking) 즉시 다음 태스크를 수행한다. 대기하지 않고 즉시 다음 태스크를 실행함으로써 자원을 보다 효율적으로 사용할 수 있다.

 

이후 서버로부터 데이터가 응답되면 이벤트가 발생하고 이벤트 핸들러가 데이터를 가지고 수행할 태스크를 계속해 수행한다. 자바스크립트의 대부분의 DOM 이벤트와 Timer 함수(setTimeout, setInterval), Ajax 요청은 비동기식 처리 모델로 동작한다.

 

자바스크립트에서 빈번하게 사용되는 비동기식 처리 모델은 요청을 병렬로 처리하여 다른 요청이 블로킹(blocking, 작업 중단)되지 않는 장점이 있다.

 

이때, 비동기 요청시 응답 후 처리할 '콜백 함수'를 함께 알려준다. 따라서 해당 태스크가 완료되었을 때, '콜백 함수'가 호출된다.

하지만 비동기 처리를 위해 콜백 패턴을 사용하면 처리 순서를 보장하기 위해 여러 개의 콜백 함수가 네스팅(nesting, 중첩)되어 복잡도가 높아지는 콜백 헬(Callback Hell)이 발생하는 단점이 있다. 콜백 헬은 가독성을 나쁘게 하며 실수를 유발하는 원인이 된다. 

function getName(callbackfunc) {
    setTimeout(() => {
        callbackfunc("mini");
    }, 1000);
}

function getAge(callbackfunc) {
    setTimeout(() => {
        callbackfunc(6);
    }, 1000);
}

function getAddress(callbackfunc) {
    setTimeout(() => {
        callbackfunc("Seoul");
    }, 1000);
}

// 더 많아지면 콜백지옥이 될 수 있다.
getName(function (name) {
  getAge((age) => {
    getAddress(function (address) {
      console.log(name, age, address);
    });
  });
});

// 3초뒤) mini 6 seoul

 

 

 

참고🖇️

What every programmer should know about Synchronous vs. Asynchronous Code(이미지)

https://poiemaweb.com/es6-promise

https://velog.io/@khy226/%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0%EB%9E%80-Promise-asyncawait-%EA%B0%9C%EB%85%90

https://velog.io/@daybreak/%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC