동기 & 비동기 with 이벤트 루프🔄

YUZAMIN
Hello, World! I'm YUZAMIN, a diligently endeavoring frontend developer 🐤💦
동기 & 비동기 with 이벤트 루프🔄

동기와 비동기란?🤔

1. 동기⏩ & 비동기⏯

동기 (Synchronous) : “동시에 일어나는”

  • 동기란 ‘누군가에게 일을 부탁하고, 그 일이 끝날 때 까지 기다리는 것 ‘.
  • 즉, 요청과 그 결과가 한 자리에서 동시에 일어나는 것.
  • 한 작업이 실행되는 동안 다른 작업은 멈춰있는 상태를 유지하며 자신의 차례를 기다린다.
  • 서버에서 데이터를 가져와서 화면에 표시하는 작업을 수행할 때, 서버에 데이터를 요청하고 데이터가 응답될 때까지 이후 태스크들은 블로킹(Blocking, 작업 중단) 된다.

비동기 (Asynchronous) : “동시에 일어나지 않는”

  • 비동기란 ‘일을 맡긴 후 끝나면 알려달라고 부탁한 뒤 다른 할 일을 하는 것 ‘.
  • 즉, 요청과 결과가 동시에 일어나지 않는 것.
  • 서버에서 데이터를 가져와서 화면에 표시하는 작업을 수행할 때, 서버에 데이터를 요청한 이후 서버로부터 데이터가 응답될 때까지 대기하지 않고(Non-Blocking) 즉시 다음 작업을 수행한다.

2. 동기⏩ & 비동기⏯의 예시

  • 동기 처리의 예시⏩
1
2
3
4
5
6
7
console.log('HI')
console.log('Nice to meet you!')
console.log('Bye!')

// HI!
// Nice to meet you!
// Bye!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function func1() {
  console.log('func1')
  func2()
}
function func2() {
  console.log('func2')
  func3()
}
function func3() {
  console.log('func3')
}

func1()

// func1
// func2
// func3
  • 비동기 처리의 예시⏯
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function func1() {
  console.log('func1')
  func2()
}
function func2() {
  setTimeout(function () {
    console.log('func2')
  }, 0)
  func3()
}

function func3() {
  console.log('func3')
}

func1()

// func1
// func3
// func2

“함수 func1이 호출되면 함수 func1은 Call Stack에 쌓인다. 그리고 함수 func1은 함수 func2을 호출하므로 함수 func2가 Call Stack에 쌓이고 setTimeout이 호출된다. setTimeout의 콜백 함수는 즉시 실행되지 않고 지정 대기 시간만큼 기다리다가 대기 시간이 끝나면 이벤트 큐로 이동한 후 Call Stack이 비워졌을 때 Call Stack으로 이동되어 실행된다.”

자바스크립트의 동작 원리

0. 이벤트 루프🔄

단일 스레드 기반 언어

  • 프로세스: 운영체제에 의해 메모리 공간을 할당 받아 실행중인 프로그램
  • 스레드: 프로세스 내에서 실제로 작업을 수행하는 주체
  • 자바스크립트는 단일 스레드 기반 언어: 동시에 하나의 작업만을 수행할 수 있음 👈🏻 단일 호출 스택을 사용함!
  • 자바스크립트가 동시성(한번에 여러 작업을 할 수 있음)을 보장하는 방법? 👉🏻 “ 이벤트 루프 “를 사용한 비동기 방식

1. 자바스크립트의 동기적 처리 원리⏩

0)

1)

  • 전역 환경에서 실행되는 코드는 하나의 코드 블록으로써 가상의 익명 함수(이 그림에서는 main())로 감싸져있다고 함

  • printSquare() 함수가 인자로 4를 받은 채로 스택에 추가됨

2)

  • square() 함수도 n이라는 인자(여기서 n은 4가 될 것이다)를 받은 채로 스택에 추가됨
  • 같은 방식으로 multiply() 함수도 스택에 차례로 추가됨

3)

  • 스택 가장 상단부터 차례로 함수가 실행되면서 제거됨
  • square() 함수가 실행된 후, return된 값이 squared라는 변수에 들어가며, console.log()가 squared 변수를 받은 채로 스택에 추가됨
  • console에 squared를 출력한 후 스택에서 제거됨
  • 마지막으로 printSquare() 함수와 main()이 차례로 스택에서 제거됨

동기적 처리 원리

  1. 코드가 실행되면 순서대로 Call Stack에 실행할 함수가 쌓인다(push)
  2. 쌓인 반대 순서로 함수가 실행된다(LIFO)
  3. 실행이 된 함수는 Call Stack에서 제거된다(pop)

2. 자바스크립트의 비동기적 처리 원리⏯

1)

  • console.log(‘Hi’)가 스택에 추가된 후, console에 ‘Hi’를 출력 후 제거됨

2)

  • setTimeout() 함수는 브라우저에게 타이머 이벤트 요청한 뒤 스택에서 제거됨
  • setTimeout()이 품고 있는 callBack 함수는 web api에서 지정된 시간(5초)동안 대기 (비동기 작업 수행)

3)

  • 바로 다음 작업인 console.log(‘JSConfEU’)가 스택에 쌓이고, console에 ‘JSConfEU’를 출력한 뒤 스택에서 제거됨

4)

  • 비동기 작업(5초 대기)이 끝난 뒤, callBack 함수는 태스크 큐에 추가됨

5)

  • 이벤트 루프는 스택이 비어있으므로 해당 함수를 스택에 추가함

6)

  • callBack 함수 내의 console.log(‘there’)이 실행되고 스택이 비워짐

비동기적 처리 원리

  1. Call Stack에서 비동기 함수가 호출되면 Call Stack에 먼저 쌓였다가 Web API(혹은 백그라운드)로 이동한 후 해당 함수가 등록되고 Call Stack에서 사라진다.
  2. Web API(백그라운드)에서 비동기 함수의 이벤트가 발생하면, 해당 콜백 함수는Callback Queue에 push(이동) 된다.
  3. 이제 Call Stack이 비어있는지 이벤트 루프(Event Loop)가 확인을 하는데 만약 비어있으면, Call Stack에 Callback Queue에 있는 콜백 함수를 넘겨준다.(push)
  4. Call Stack에 들어온 함수는 실행이 되고 실행이 끝나면 Call Stack에서 사라진다.

참고1

참고2

참고3

참고4

참고5