JS는 싱글스레드 언어인데, 비동기 처리를 어떻게 할까??

CHAN·2023년 10월 26일
0

CS

목록 보기
8/14
post-thumbnail

동기, 비동기.. 개발공부를 하면 중요한 개념이라고 생각한다...

Synchronous(동기)

  • ‘동시에 일어나는 또는 발생하는’의 뜻으로 컴퓨터 공학에서는 현재 작업의 응답과 다음 작업의 말한다. 즉, 컴퓨터 공학에서 동기는 현재 작업의 응답과 다음 작업의 요청이 동시에 일어나는 것이다. 중요한 것은 서로에 영향을 준다을 주고 작업을 한다고 생각하는게 좋다.

Asynchronous(비동기)

  • ‘동시에 발생하지 않는’의 뜻으로 컴퓨터 공학에서 비동기는 현재 작업의 응답과 다른 작업의 요청이 동시에 일어나지 않는 것이다. 중요한 것은 서로에게 영향을 주지 않고 병렬적으로 처리된다고 생각하는게 좋다.

비슷한 말이 있다는 것을 알고있나?

Blocking

  • 블로킹은 저지 현상이라는 의미를 가지고 있다. 이를 조금 더 길게 풀어보자면 행위자가 취한 행위 자체가 또는 그 행위로 인해 다른 무엇이 막혀버린, 제한된 상태라고 할 수 있는데, 이걸 컴퓨터 공학의 측면에서 보면 다른 함수가 작업을 하지 못하도록 제어권을 계속 가지고 있는 것이다.
  • 메소드를 실행시킨과 동시에 반환 값이 기대되는 경우를 동기라고 표현하고 동시에라는 말은 실행되었을때 값이 반환되기 전까지는 blocking되어 있다는 것을 의미하게 된다.
  • Thread 관점으로 본다면, 요청한 작업을 마칠 때까지 계속 대기하며 return 값을 받을 때까지 한 Thread를 계속 사용 / 대기

Non- Blocking

  • blocking과 반대의 개념을 가지고 있으며, 호출된 함수가 자신의 할일을 모두 마치지 않더라도 제어권을 리턴해주는 것이다. 즉, 호출된 함수가 자신이 할 일을 채 마치지 않았더라도 바로 제어권을 건내주어 호출한 함수가 다른 일을 진행할 수 있도록 해준다.
  • Thread 관점으로 본다면, 하나의 Thread가 여러 개의 I/O를 처리 가능하다.

동기, 비동기, block, non-block이 헷갈릴 수 있다.

어째 보면 동기가 block이고, 비동기가 non-block처럼 보일 수 있다. 하지만 따지고 보면 동기/비동기, blocking/non-blocking 두 그룹의 차이는 관심사가 다르다.

  • blocking / non-blocking의 경우
    • 호출되는 함수가 바로 return하느냐 마느냐에 관심사가 있다.
    • 호출된 함수가 바로 return해서 호출한 함수에게 제어권을 넘겨주고…. 여기서 제어권을 넘겨준다~ 이래 생각하면 안되고 호출을 원했던 함수가 다시 제어권을 받는것을 생각, 즉, 결국에 는 안넘겨줌 ㅋ, 호출한 함수가 다른 일을 할 수 있는 기회를 주면 non-blocking, 호출된 함수가 자신의 작업을 모두 마칠 때까지 호출한 함수에게 제어권을 넘겨주지 않고 대기하게 만든다면 blocking이다.
  • 동기 / 비동기의 경우
    • 호출되는 함수의 작업 완료 여부를 누가 신경쓰느냐가 관심사이다. 다른 말로 반환과 요청의 시간이 같냐 다르냐.
    • 호출되는 함수에게 callback을 전달해서 호출되는 함수의 작업이 완료되면 호출되는 함수가 전달받은 callback을 실행시키고, 호출한 함수는 작업 완료 여부를 신경쓰지 않다면 비동기이다. 호출하는 함수가 호출되는 함수의 작업 완료 후, return을 기다리거나 호출되는 함수로 부터 바로 return 받더라도 작업 완료 여부를 호출한 함수 스스로 확인하며 신경 쓴다면 동기이다.
    • 일반적으로 동기에는 callback이 없다. 그래서 동기-논블로킹 방식에는 계속 확인을 하는 것이다.

너는 싱글스레드인데, 비동기 작업을 하지 못하냐??

자바스크립트의 인터프리터가 싱글 스레드를 가진다는 것이고, 자바스크립트의 런타임은 결국 웹엔진에서 구동이 된다. 그리고 그 웹 엔진은 Web APIs, Event Queue, Event Loop로 구성이 되어있다. 이것들이 자바스크립트를 비동기로 처리하도록 도와주는 것이다.


자바스크립트 그 자체의 엔진

Memory Heap과 Call Stack이 있다. 전자는 메모리 할당이 일어나는 곳이며, 후자는 코드가 실행될때 쌓이는 스택이라 생각하면된다. 그리고 Call Stack은 하나만 존재하기 때문에 실행중인것이 끝나기 전까지는 다른 일들이 실행되지 않는다. 즉, 자바스크립트 자체는 비동기를 지원하지 않는다.


자바스크립트가 실행되는 웹 엔진

Web APIs, Callback queue, event loop가 주 메인 역할이다.

Web APIs

  • 돔 조작, 이벤트 처리(이벤트 핸들러를 등록하고 사용자 상호 작용에 대응하는 기능을 제공)등을 한다

Callback queue

  • asycn/await 와 같은 비동기 호출, setTimeout()등의 task, 브라우저 렌더링
  • 사실 Callback queue에도 여러 종류가 있다. 아래 적힌 것보다 더 많다…
    • 마이크로태스크 큐(Microtask Queue)
      • Promise와 관련된 비동기 작업을 처리
    • 태스크 큐(Task Queue)
      • 비동기 작업의 콜백 함수를 저장하는 큐로, 주로 setTimeout, 이벤트 핸들러, HTTP 요청 완료와 같은 비동기 작업의 콜백을 관리
    • 애니메이션 프레임 큐(Animation Frame Queue)
      • requestAnimationFrame 함수를 통해 예약된 애니메이션 및 그래픽 업데이트 콜백을 관리
    • 서비스 워커 큐(Service Worker Queue)
      • 서비스 워커 큐는 웹 애플리케이션의 백그라운드에서 동작하는 서비스 워커와 관련된 작업을 처리
    • 우선순위는 사실 일반적으로, 마이크로태스크 큐(Microtask Queue), 애니메이션 프레임 큐(Animation Frame Queue), 태스크 큐(Task Queue) 를 제외하고는 큐의 특성과 실행 환경에 따라 달라질 수 있다.

Event Loop

  • 이벤트 loop가 중간 역할을 다 수행한다고 생각하면 된다.
  • JavaScript 프로그램이 시작할 때 초기화 한다. 이 초기화 단계에서 콜 스택을 생성하고, 여러 큐(Queues)를 설정한다.
  • 다양한 큐를 모니터링하며, 큐에서 작업을 꺼내와 콜 스택으로 이동하여 실행
  • 블로킹 작업이 콜 스택에서 실행 중이면, 이벤트 루프는 다음 작업을 처리하기 위해 기다린다. (역시 블로킹이 갑이다.)
  • 이벤트 루프는 무한 루프를 돌면서 계속해서 콜 스택이 비어 있을 때 큐의 작업을 처리하고 실행을 조절하는 반복작업을 지속한다.
  • 이렇게 이벤트 루프는 콜 스택, 다양한 큐, 그리고 비동기 및 동기 작업 간의 상호작용을 관리하여 JavaScript 코드가 비동기 작업을 효과적으로 처리하도록 해준다!

이해를 돕기 위해 전체적인 그림을 한 번 보자

정리하면 자바스크립트에서 비동기 작업은 보통 호출 스택에서 비동기 함수가 호출된 후 Web API로 이동하고, 작업이 완료되면 해당 콜백 함수가 콜백 큐에 추가된다. 그 후 이벤트 루프가 호출 스택이 비어있을 때 콜백 큐의 함수를 실행한다.

단, 이벤트 루프의 동작은 환경에 따라 다를 수 있으며, promise 비동기/대기 패턴 등의 요소도 동작을 영향을 줄 수 있으므로 구체적인 상황에 따라 다를 수 있다.


눈으로 확인해보자(실습)

Start, End는 동기코드로 실행이 되었고, Promise, setTimeout의 경우에는 비동기처리가 되었는데 Promise는 Microtask 큐, setTimeout은 Task 큐에서 실행이 되기 때문에 우선순위 처리로 인하여 Promise Callback이 먼저 콘솔로 찍히게 되었다.


마무리

개념을 공부하며, 실습을 진행하니, 자바스크립트의 비동기 처리방식을 더 잘 이해할 수 있었다.

참고영상
https://www.youtube.com/watch?v=8aGhZQkoFbQ&t=1208s
profile
크게 보는 습관

0개의 댓글