무회blog

일반적인 비동기 프로그래밍 개념 본문

js

일반적인 비동기 프로그래밍 개념

최무회 2020. 4. 14. 09:18

비동기?

 

일반적으로 주어진 프로그램의 코드는 한 번에 하나의 일만 발생하면서 바로 실행됩니다. 함수가 다른 함수의 결과에 의존하는 경우 다른 함수가 완료되어 리턴 될 때까지 기다려야하며, 그 때까지 전체 프로그램은 본질적으로 사용자 관점에서 중지됩니다.

예를 들어, Mac 사용자는 때때로 회전하는 무지개 색 커서 (또는 "비치 볼"이라고도 함)로 이것을 경험합니다. 이 커서는 운영 체제에서 "사용중인 현재 프로그램을 중지하고 무언가가 완료 될 때까지 기다려야하는데 시간이 너무 오래 걸리므로 무슨 일이 일어나고 있는지 궁금 할 것입니다."

이것은 실망스러운 경험이며 컴퓨터 처리 능력을 잘 사용하지 못합니다. 특히 컴퓨터에 여러 개의 프로세서 코어가있는 시대에는 더욱 그렇습니다. 다른 작업이 다른 프로세서 코어에서 작동하도록하고 언제 완료되었는지 알려 주면 무언가를 기다리는 것이 의미가 없습니다. 이를 통해 비동기 프로그래밍 의 기초가되는 다른 작업을 수행 할 수 있습니다 . 이러한 작업을 비동기 적으로 실행할 수있는 API를 제공하는 것은 사용중인 프로그래밍 환경 (웹 개발의 경우 웹 브라우저)에 달려 있습니다.

차단 코드

비동기 기술은 특히 웹 프로그래밍에서 매우 유용합니다. 웹 응용 프로그램이 브라우저에서 실행되고 브라우저로 제어를 반환하지 않고 집중적 인 코드 덩어리를 실행하면 브라우저가 정지 된 것처럼 보일 수 있습니다. 이것을 차단 이라고합니다 . 웹 앱이 프로세서 제어를 반환 할 때까지 브라우저는 사용자 입력을 계속 처리하고 다른 작업을 수행 할 수 없습니다.

차단이라는 의미를 보여주는 몇 가지 예를 살펴 보겠습니다.

우리에서 간단한 sync.html의 예 ( 이 라이브 실행을 참조하십시오 , 우리는 클릭 할 때 너무 버튼에 클릭 이벤트 리스너를 추가), 그것은 시간이 많이 걸리는 작업을 실행 (계산 천만 날짜는 콘솔에 마지막 하나를 기록) DOM에 단락을 추가합니다.

const btn = document.querySelector('button'); btn.addEventListener('click', () => { let myDate; for(let i = 0; i < 10000000; i++) { let date = new Date(); myDate = date } console.log(myDate); let pElem = document.createElement('p'); pElem.textContent = 'This is a newly-added paragraph.'; document.body.appendChild(pElem); });

예제를 실행할 때 JavaScript 콘솔을 연 다음 버튼을 클릭하면 날짜 계산이 완료되고 콘솔 메시지가 기록 될 때까지 단락이 표시되지 않습니다. 코드는 소스에 표시된 순서대로 실행되며, 이전 작업이 완료 될 때까지 이후 작업이 실행되지 않습니다.

참고 : 이전 예제는 매우 비현실적입니다. 실제 웹 앱에서 천만 날짜를 계산하지 않을 것입니다! 그러나 기본 아이디어를 제공하는 역할을합니다.

우리의 두 번째 예에서는 간단한 동기화-UI-blocking.html ( 가 살고 참조 ), 우리는 당신이 진짜 페이지에 걸쳐 올 수도 있다는 약간 더 현실적인 뭔가를 시뮬레이션 할 수 있습니다. UI 렌더링과의 사용자 상호 작용을 차단합니다. 이 예제에는 두 개의 버튼이 있습니다.

  • 클릭하면 사용 가능한 <canvas>백만 개의 파란색 원으로 채워지는 "캔버스 채우기"단추 .
  • 클릭하면 경고 메시지가 표시되는 "경고를 위해 클릭하십시오"단추.

function expensiveOperation() { for(let i = 0; i < 1000000; i++) { ctx.fillStyle = 'rgba(0,0,255, 0.2)'; ctx.beginPath(); ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false); ctx.fill() } } fillBtn.addEventListener('click', expensiveOperation); alertBtn.addEventListener('click', () => alert('You clicked me!') );

첫 번째 단추를 클릭 한 다음 두 번째 단추를 빠르게 클릭하면 원 렌더링이 완료 될 때까지 경고가 표시되지 않습니다. 첫 번째 작업은 실행이 끝날 때까지 두 번째 작업을 차단합니다.

참고 : 좋습니다. 우리의 경우에는 추악하고 차단 효과를 속이고 있지만 이것은 실제 앱 개발자가 항상 완화하기 위해 싸우는 일반적인 문제입니다.

왜 이런거야? 대답은 일반적으로 말해서 JavaScript가 단일 스레드 이기 때문 입니다. 이 시점에서 스레드 개념을 소개해야 합니다 .


스레드는 기본적으로 프로그램이 작업을 완료하는 데 사용할 수있는 하나의 과정이다. 각 스레드는 한 번에 하나의 작업 만 수행 할 수 있습니다.

Task A --> Task B --> Task C

각 작업은 순차적으로 실행됩니다. 다음 작업을 시작하기 전에 작업을 완료해야합니다.

앞에서 언급했듯이 많은 컴퓨터에는 이제 여러 개의 코어가 있으므로 한 번에 여러 작업을 수행 할 수 있습니다. 여러 스레드를 지원할 수있는 프로그래밍 언어는 여러 코어를 사용하여 여러 작업을 동시에 완료 할 수 있습니다.

Thread 1: Task A --> Task B Thread 2: Task C --> Task D

자바 스크립트는 단일 스레드입니다

JavaScript는 전통적으로 단일 스레드입니다. 코어가 여러 개인 경우에도 메인 스레드 라는 단일 스레드에서만 작업을 실행할 수 있습니다. 위의 예제는 다음과 같이 실행됩니다.

Main thread: Render circles to canvas --> Display alert()

얼마 후, JavaScript는 그러한 문제를 해결하는 데 도움이되는 몇 가지 도구를 얻었습니다. 웹 워커를 사용하면 JavaScript 처리 중 일부를 워커라고하는 별도의 스레드로 보낼 수 있으므로 여러 JavaScript 청크를 동시에 실행할 수 있습니다. 일반적으로 작업자를 사용하여 주 스레드에서 값 비싼 프로세스를 실행하여 사용자 상호 작용이 차단되지 않도록합니다.

Main thread: Task A --> Task C Worker thread: Expensive task B

이를 염두에두고 브라우저의 JavaScript 콘솔을 다시 연 상태 에서 simple-sync-worker.html ( 실시간으로 실행 참조)을 살펴보십시오 . 이것은 별도의 작업자 스레드에서 천만 날짜를 계산하는 이전 예제를 다시 작성한 것입니다. 이제 버튼을 클릭하면 날짜 계산이 끝나기 전에 브라우저가 단락을 표시 할 수 있습니다. 첫 번째 작업은 더 이상 두 번째 작업을 차단하지 않습니다.


비동기 코드

웹 워커는 매우 유용하지만 한계가 있습니다. 중요한 것은 DOM 에 액세스 할 수 없다는 것입니다. 작업자가 UI를 업데이트하기 위해 직접 작업을 수행하도록 할 수는 없습니다. 작업자 내부에 백만 개의 파란색 원을 렌더링 할 수 없었습니다. 기본적으로 숫자 처리 만 할 수 있습니다.

두 번째 문제는 작업자에서 실행되는 코드가 차단되지 않지만 여전히 기본적으로 동기화된다는 것입니다. 함수가 여러 이전 프로세스의 결과에 의존 할 때 문제가됩니다. 다음 스레드 다이어그램을 고려하십시오.

Main thread: Task A --> Task B

이 경우 작업 A가 서버에서 이미지를 가져 오는 것과 같은 작업을하고 작업 B가 필터를 적용하는 것과 같은 작업을 이미지에서 수행한다고 가정 해 보겠습니다. 작업 A 실행을 시작한 다음 즉시 작업 B를 실행하려고하면 이미지를 아직 사용할 수 없으므로 오류가 발생합니다.

Main thread: Task A --> Task B --> |Task D| Worker thread: Task C -----------> | |

이 경우 작업 D가 작업 B와 작업 C의 결과를 모두 사용한다고 가정 해 봅시다. 이러한 결과를 동시에 사용할 수 있다고 보장 할 수 있다면 문제가되지는 않지만 그럴 가능성은 없습니다. 입력 중 하나를 아직 사용할 수 없을 때 작업 D가 실행을 시도하면 오류가 발생합니다.

이러한 문제를 해결하기 위해 브라우저를 통해 특정 작업을 비동기 적으로 실행할 수 있습니다. Promises 와 같은 기능 을 사용하면 작업 실행 (예 : 서버에서 이미지 가져 오기)을 설정 한 다음 다른 작업을 실행하기 전에 결과가 반환 될 때까지 기다릴 수 있습니다.

Main thread: Task A Task B Promise: |__async operation__|

작업이 다른 곳에서 발생하므로 비동기 작업이 처리되는 동안 주 스레드가 차단되지 않습니다.

다음 기사에서 비동기 코드를 작성하는 방법을 살펴 보겠습니다. 신나는 물건? 계속 읽으세요!


결론

현대적인 소프트웨어 설계는 프로그램이 한 번에 하나 이상의 작업을 수행 할 수 있도록 비동기식 프로그래밍을 사용하는 것에 따라 점점 더 발전하고 있습니다. 새롭고 더 강력한 API를 사용함에 따라 작업을 수행하는 유일한 방법이 비동기 적으로 수행되는 경우가 더 많습니다. 비동기 코드를 작성하기가 어려웠습니다. 여전히 익숙해 지지만 훨씬 쉬워졌습니다. 이 모듈의 나머지 부분에서는 비동기 코드가 중요한 이유와 위에서 설명한 일부 문제를 피하는 코드를 디자인하는 방법에 대해 자세히 설명합니다.

 

 

출처: 

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Concepts

 

General asynchronous programming concepts

In this article we'll run through a number of important concepts relating to asynchronous programming, and how this looks in web browsers and JavaScript. You should understand these concepts before working through the other articles in the module.

developer.mozilla.org

 

'js' 카테고리의 다른 글

html 요소 좌표,(상대좌표, 절대좌표) 값 구하기 ,getBoundingClientRect  (0) 2022.06.22
codeLink _001  (0) 2020.04.14
Comments