#TIL JS 동기/비동기 정리

송정석·2022년 3월 12일
0

동기와 비동기🤔

  1. 동기(synchronous: 동시에 일어나는)
  • 동기는 말 그대로 동시에 일어난다는 뜻이다. 요청과 그 결과가 동시에 일어난다는 약속인데. 바로 요청을 하면 시간이 얼마나 걸리던지 요청한 자리에서 결과가 주어져야 한다.

  • 요청한 결과가 한자리에서 동시에 일어남

  • A노드와 B노드 사이의 작업 처리 단위(transaction)을 동시에 맞추겠다.

  1. 비동기(Asynchronous: 동시에 일어나지 않는)
  • 비동기는 동시에 일어나지 않는다는 의미다. 요청한 결과는 동시에 일어나지 않을거라는 약속이다.

  • 요청한 그 자리에서 결과가 주어지지 않음

  • 노드 사이의 작업 처리 단위를 동시에 맞추지 않아도 된다.

  1. 동기와 비동기는 상황에 따라 각각 장단점이 존재
  • 동기방식은 설계가 매우 간단하고 직관적이지만 결과가 주어질 때까지 아무것도 못하고 대기해야 하는 단점이 있다.

  • 비동기 방식은 동기보다 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있는 장점이 있다.

3-1.동기방식의 예(A가 B에게 10,000원을 송금)

  1. A의 계좌는 현재 10,000원을 출금할 생각이다.

  2. A의 계좌가 B의 계좌로 방금 인출한 10,000원을 송금한다.

  3. B의 계좌는 10,000원을 받았다는 것을 인지하고, A의 계좌에 10,000원을 받았다고 전송한다.

  4. A,B 계좌 각각 차감과 증가가 발생한다.

순서를 보면 A의 계좌와 B의 계좌는 서로 요청과 응답을 확인한 후 같은 일을 동시에 진행했다.

"계좌이체"같은 작업은 동기방식으로 처리해야 A에게 보냈는데 B에게 못받는 상황이 없을 것이다.

반대로 비동기 방식은 위의 예제처럼 노드사이의 작업 처리 단위를 동시에 맞추지 않아도 된다.

3-2.비동기방식의 예(시험날의 학생과 선생)

1.학생은 받은 시험지를 푼다.

2.시험문제를 모두 푼 학생은 선생에게 자신이 푼 시험지를 건낸다.

3.선생은 학생으로 부터 받은 시험지를 채점한다.

4.채점이 다 된 시험지를 학생에게 전송한다.

5.학생은 선생이 전송한 시험지를 받아 자신의 시험 결과를 확인한다.

학생과 선생은 시험지라는 연결고리가 있지만 시험지에 행하는 행위(목적)은 서로 다르다. 학생은 시험지를 푸는 역할을 하는 반면 선생은 시험지를 채점하는 역할을 한다. 서로의 행위(목적)은 다르기때문의 둘의 작업 처리기간은 일치하지 않고, 일치하지 않아도 된다.


동기와 비동기는 어떤 작업 혹은 그와 연관된 작업을 처리하고자 하는 시각의 차이다.

동기는 추구하는 행위(목적)이 동시에 이루어지고, 비동기는 추구하는 행위(목적)이 다를 수도 있고, 동시에 이루어지지도 않는다.


😱Callback

Callback함수는 특정 함수에 매개변수로 전달된 함수를 의미한다. 그 콜백함수는 함수를 전달받은 함수안에서 호출된다.

function Callback(callback){
    console.log('콜백 함수');
    callback();
}
Callback(function(){
    console.log('콜백 받는곳');
})

Callback함수에서 Callback을 받지 않는다면 함수의 과정이 끝나기도 전에 다음 프로세스를 진행하게 되는 경우가 있다.
Callback 함수는 가독성이 좋지않다.

function Callback(callback){
    function Callback2(callback){
        function Callback3(callback){
            console.log('무한콜백');
        }
    }
}

이것이 무한콜백이다. 가독성도 떨어지고 실수 위험도 커지게 된다. 그래서 ES7에서는 promise를 ES8에서는 async, await를 지원한다.

Promise😇

promise는 기본적으로 Callback이 하는일과 같다. 차이점은 promise는 작업이 끝난 후 실행할 함수를 제공하는 것이 아니라 promise자체 메소드인 .then()을 호출한다.

function add10(a) {
  return new Promise(resolve => setTimeout(() => resolve(a + 10), 100));
} //Promise사용 시 작업이 끝났음을 알려주는 resolve를 인자로 받아들임.
add10(10)
  .then(add10)
  .then(add10)
  .then(add10)
  .then((res) => console.log(res))

Promise는 .then()과 같은 메소드를 연속적으로 사용이 가능한 이점을 가지고 있다. 따라서 callback을 사용했을 때와는 다르게 코드를 작성하고 이해하기가 한결 쉬워졌다

Promise에서의 예외 처리

add10(10)
  .then((res) => {
        throw 'test error';
    })
  .catch((err) => console.log(err));

promise에서는 작업이 실패했을
경우 자동으로 .catch()메소드를 호출되게 한다.
기존 try-catch를 이용해서도 예외처리가 가능하지만 자바스크립트에서는 promise의 catch를 사용하라는 warning message를 출력함.

🌈async/await

Node.js 7.6버전부터 구현된 기능이며 Async/Await를 사용하면 promise에 비해 보다 쉽게 비동기적인 상황을 표현할 수 있다.

async function f1() {
  const a = await add10(10);
  const b = await add10(a);
  console.log(a, b)
}
f1();

Async와 Await을 사용하려면 우선 사용할 함수 앞에 async라는 키워드를 붙여 사용해야 하며 선언된 async 함수 안에서만 await 키워드를 사용할 수 있다.

await은 함수의 작업이 끝나고 결과값을 반환할 때까지 대기하게 되며 결과 값이 리턴된다면 다음 작업으로 넘어가게 됩니다.

Async/Await의 예외 처리

async function f2() {
  const a = await add10(10).then(res => res);
  const b = await add10(a).catch(err => err);
  console.log(a, b)
}
f2();

위의 코드에선 add10()이 promise를 리턴하니까 promise가 지원하는 메소드를 사용이 가능하다. 그래서.catch()를 이용하여 예외처리를 할 수 있다.

async function f3() {
  try {
    const a = await add10(10)
    const b = await add10(a)
    console.log(a, b)
  } catch(err) {
    console.log(err)
  }
}
f3();

이렇게 기존방식인 try-catch도 사용이 가능하다.

자바스크립트의 엔진 구성🧐

자바스크립트 엔진은 크게 두 부분으로 구성된다.

메모리 힙(Memory Heap) : 메모리 할당이 이루어지는 곳

콜 스택(Call Stack) : 코드가 실행되면서 스택 프레임이 쌓이는 곳
위와 같이 구성된다. 하지만 브라우저에는 거의 모든 자바스크립트 개발자가 사용하는 API가 있다. 예를 들면setTimeout과 같은 것들을 말한다. 그런데 이것들은 엔진이 제공하는 것이 아니다.

브라우저가 제공하는 웹 API가 DOM, AJAX,setTimeout 등을 지원한다.

🌏Event Loop

Callback Queue는 Call Stack이 비면 Call Stack으로 작업을 하나씩 보낸다고 나와있다.

Call Stack이 비었는지 확인하고 Callback Queue에 먼저 들어온 작업을 하나씩 Call Stack으로 옮겨주는 일을 하는 것이 Event Loop이다.

Web API🧱

  1. API란?
    API는 Application Programming Interface의 약자로 응용 프로그램에서 사용할수 있도록, 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만드는 인터페이스를 뜻한다.

    주로 파일 제어, 창 제어, 화상 처리, 문자 제어 등 자신이 원하는 기능을 제어할 수 있도록 하는 인터페이스를 제공한다. 따라서 원하는 기능을 제어하는 API를 직접 만들 수도 있다.

  1. WEB API란?
    웹 서버 또는 웹 브라우저를 위한 애플리케이션 프로그래밍 인터페이스이다. HTTP 서비스이고 다양한 클라이언트에서 접근이 가능하도록 설계되어있다. Web 환경을 통해 제공되는 데이터 CRUD인터페이스를 제공한다.

🔨Call back Queue

Callback Queue란 Call Stack이 비면 해야할 작업들을 담고 있는 queue이다.

Call Stack에 작업을 보내기 전에 대기하는 큐라고 볼 수 있다.

자바스크립트에서 비동기로 실행되는 함수들(예를들면 setTimeout)이 Call Stack에 들어갔다가 webAPIs에서 실행 후 Callback Queue에 들어오는 것이다.

Call Stack📂

자바스크립트는 하나의 호출 스택을 사용한다. 이는 하나의 함수가 실행되면 그 함수가 끝날 때까지 다른 함수는 실행할 수 없음을 의미한다.

함수를 호출하면 순차적으로 함수를 Call Stack에 담아 처리한다.

Call Stack에 함수가 들어오면(push) 실행하고 끝날 때 pop하여 Call Stack에서 나간다.

만약 a라는 함수가 b라는 함수를 호출한다면 a는 Call Stack에 들어가고 그 위에 b라는 함수가 쌓여 b를 실행한 뒤 종료되면 b가 pop되고 a가 종료되면 pop되어 Call Stack이 비게 된다.

💻Call stack 처리 과정

아래는 예시 코드

console.log('Hi');
setTimeout(function cb1() { 
    console.log('cb1');
}, 5000);
console.log('Bye');

  1. 브라우저 콘솔이 깨끗하고 CallStack이 비어있음.
  2. console.log('Hi') CallStack에 추가된다.
  3. console.log('Hi') 실행된다.
  4. console.log('Hi') CallStack에서 제거된다.
  5. setTimeout(function cb1() { ... }) CallStack에 추가된다.
  6. setTimeout(function cb1() { ... }) 실행되고 브라우저는 Web API의 일부로 타이머를 생성한다. 그리고 카운트 다운을 처리 를 시작한다.
  7. setTimeout(function cb1() { ... })자체가 완료되고 CallStack에서 제거 된다.
  8. console.log('Bye') CallStack에 추가된다.
  9. console.log('Bye') 실행된다.
  10. console.log('Bye') CallStack에서 제거된다.
  11. 최소 5000ms 후에 타이머가 완료되고 cb1 Callback 대기열에 푸시한다.
  12. EventLoop 는 cb1을 Callback Queue에서 가져와 CallStack으로 푸시한다.
  13. cb1실행되어 console.log('cb1') CallStack에 추가된다.
  14. console.log('cb1')가 실행된다.
  15. console.log('cb1') CallStack에서 제거된다.
  16. cb1 CallStack에서 제거된다.

📚참조📚
https://www.youtube.com/watch?v=zi-IG6VHBh8&ab_channel=%EA%B0%80%EC%9E%A5%EC%89%AC%EC%9A%B4%EC%9B%B9%EA%B0%9C%EB%B0%9CwithBoaz
https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5
https://koras02.tistory.com/87
https://hees-dev.tistory.com/38?category=856226
https://velog.io/@lsj8367/Javascript-%EB%8F%99%EA%B8%B0%EC%99%80-%EB%B9%84%EB%8F%99%EA%B8%B0%EB%B0%A9%EC%8B%9D%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90

profile
Foot print

0개의 댓글