diff --git a/files/ko/glossary/asynchronous/index.html b/files/ko/glossary/asynchronous/index.html new file mode 100644 index 00000000000000..09acbc2694070a --- /dev/null +++ b/files/ko/glossary/asynchronous/index.html @@ -0,0 +1,39 @@ +--- +title: 비동기 +slug: Glossary/Asynchronous +tags: + - Glossary + - Web + - WebMechanics + - asynchronous + - 용어집 + - 웹 + - 비동기 +--- +

비동기 두 개 이상의 객체나 이벤트가 동시에 존재하지 않거나 일어나지 않는 (혹은 여러 관련된 일이 이전 일이 끝나기를 기다릴 필요 없이 일어나는) 것을 말합니다. 컴퓨팅에서 "비동기"라는 단어는 크게 두 가지 맥락으로 사용됩니다.

+ +
+
네트워킹과 통신
+
+

비동기 통신이란 둘 이상의 참여자 사이에 메시지를 교환하는 방식으로, 수신하는 즉시 메시지를 처리하는 것이 아니라 각 참여자가 편할 때나 가능할 때 처리하는 것을 말합니다. 또한 문제가 발생하면 수신자가 정정을 요청하거나 상황에 맞는 처리를 한다는 이해 하에 확인(acknowledgement)을 기다리지 않고 메시지를 보낼 수 있습니다.

+ +

사람의 경우, 이메일이 비동기식 통신 방법입니다. 이메일을 보내면 받는 사람은 바로 읽고 답장을 보내는게 아니라, 편할 때 답장을 보냅니다. 양쪽이 서로 일정을 맞춰야 하는 것이 아니라, 원할 때 마다 메시지를 주고 받을 수 있습니다.

+ +

소프트웨어가 비동기적으로 통신할 때는, 프로그램이 다른 소프트웨어(예: 서버)에게 요청을 보내고 응답을 기다리는 동안 다른 작업을 계속 할 수 있습니다. 예를 들어 AJAX (Asynchronous JavaScript and {{Glossary("XML")}}) 기술(요즘은 일반적으로 "Ajax"라고 한 단어처럼 지칭하며, 현대 어플리케이션에서는 XML보다 {{Glossary("JSON")}}을 더 많이 사용하지만 그대로 "Ajax"라고 부릅니다)은 {{Glossary("HTTP")}}를 사용하여 서버에 비교적 작은 양의 데이터를 요청하면 결과가 즉시 반환되는 대신 사용 가능할 때 반환되는 매커니즘입니다.

+
+
소프트웨어 설계
+
+

비동기식 소프트웨어 설계는 기존 작업이 끝나기를 기다리지 않고 새로운 작업을 같이 실행할 수 있도록 하는 개념을 확장합니다. 보조 작업이 끝나면 합의된 매커니즘을 사용하여 원래 작업에 알림을 전송하여, 작업이 끝났고 결과(있는 경우)를 사용할 수 있음을 알립니다.

+ +

비동기 소프트웨어를 구현하는 데 사용되는 여러 가지 프로그래밍 기술이 있습니다. 알아보고 싶으시다면 비동기 JavaScript 문서를 참조하세요.

+
+
+ +

더 알아보기

+ +

기술 참고서

+ + diff --git a/files/ko/glossary/synchronous/index.html b/files/ko/glossary/synchronous/index.html new file mode 100644 index 00000000000000..f6732706480bb1 --- /dev/null +++ b/files/ko/glossary/synchronous/index.html @@ -0,0 +1,24 @@ +--- +title: 동기 +slug: Glossary/Synchronous +tags: + - Glossary + - Web + - WebMechanics + - 용어집 + - 웹 +--- +

동기는 통신에서 각 참여자가 실시간으로 즉시(혹은 최대한 즉시에 가깝게) 메시지를 받는(필요하다면 처리하고 응답을 보내는 것 까지) 것을 말합니다.

+ +

사람의 경우 전화를 예시로 들 수 있습니다. 전화를 받는 도중에는 상대방에게 바로 반응하곤 하니까요.

+ +

많은 프로그래밍 명령어는 동기적으로 동작합니다. 어떤 계산을 입력하면, 여러분이 그렇게 하지 않도록 프로그래밍 하지 않는 이상 환경은 즉시 결과를 반환합니다.

+ +

더 알아보기

+ +

기술 참고서

+ + diff --git a/files/ko/learn/javascript/asynchronous/concepts/index.html b/files/ko/learn/javascript/asynchronous/concepts/index.html index 443487fefbda8f..f5a396eb3212b9 100644 --- a/files/ko/learn/javascript/asynchronous/concepts/index.html +++ b/files/ko/learn/javascript/asynchronous/concepts/index.html @@ -1,48 +1,57 @@ --- -title: 일반적인 비동기 프로그래밍 개념 +title: 일반 비동기 프로그래밍 개념 slug: Learn/JavaScript/Asynchronous/Concepts tags: + - JavaScript + - Learn + - Promises + - Threads + - asynchronous + - blocking + - 자바스크립트 + - 프로미스 + - 스레드 - 비동기 - 비동기 프로그래밍 - - 자바스크립트 + - 블로킹 translation_of: Learn/JavaScript/Asynchronous/Concepts ---
{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}
-

이 문서에서는 비동기적 프로그래밍과 관련된 몇개의 개념들을 살펴볼 것입니다. 그리고 이것들이 웹브라우저와 자바스크립트에서 어떻게 보이는지도 살펴볼 것입니다. 이 모듈의 다른 문서들을 공부하기 전에, 이 문서에 나와있는 개념들을 먼저 학습하십시오.

+

이 문서에서는 비동기 프로그래밍과 관련된 여러 개념들을 살펴보고, 웹 브라우저와 JavaScript에서 어떻게 나타나는지 알아봅니다. 이 모듈의 다른 문서들을 보기 전에 이 문서의 개념들을 먼저 학습하세요.

- - + + - - + +
선행 조건:기초적인 컴퓨터 언어 능력,  Javascript에 대한 기초적인 이해가 필요합니다. 필요한 사전 지식:기본적인 컴퓨터 활용 능력, JavaScript 기초에 대한 이해. 
학습 목적: 비동기적 프로그래밍이 작동하는 기초적인 원리에 대해 이해하는 것입니다. 그리고 이 개념이 어떻게 웹브라우저와 자바스크립트에서 압도적인 지위를 차지하기 되었는지 알아봅니다. 학습 목표: 비동기 프로그래밍 개념을 이해하고, 웹 브라우저와 JavaScript에서 어떻게 나타나는지 안다.
-

'비동기적'(Asynchronous) 이란?

+

비동기란?

-

일반적으로, 프로그램의 코드는 순차적으로 진행됩니다. 한번에 한가지 사건만 발생하면서 말입니다. 만약 어떤 함수의 결과가 다른 함수에 영향을 받는다면, 그 함수는 다른 함수가 끝나고 값을 산출할 때까지 기다려야 합니다. 그리고 그 과정이 끝날 때 까지, 유저의 입장에서 보자면,  전체 프로그램이 모두 멈춘 것처럼 보입니다. 

+

일반적으로, 프로그램의 코드는 한번에 한가지 사건만 발생하면서 순차적으로 실행됩니다. 만약 어떤 함수의 결과가 다른 함수에 영향을 받는다면, 그 함수는 다른 함수가 끝나고 값을 돌려줄 때까지 기다려야 합니다. 그리고 그 과정이 끝날 때 까지, 유저의 입장에서는 프로그램 전체가 모두 멈춘 것처럼 보입니다. 

-

예를들면, 맥 유저라면 종종 회전하는 무지개색 커서(비치볼)를 본 적이 있을 것입니다. 이 커서는 오퍼레이팅 시스템이 이렇게 말하고 있는 것입니다. "당신이 지금 사용하고 있는 시스템은 지금 멈춰서서 뭔가가 끝나기를 기다려야만 합니다. 그리고 이 과정은 당신이 지금 무슨 일이 일어나고있는지 궁금해 할 만큼 오래 걸리고 있습니다."

+

예를 들면, 맥 유저라면 종종 회전하는 무지개색 커서(비치볼)를 본 적이 있을 것입니다. 이 커서는 운영체제가 "당신이 지금 사용하고 있는 프로그램은 지금 멈춰서 뭔가가 끝나기를 기다려야만 합니다. 그리고 당신이 지금 무슨 일이 일어나고있는지 궁금해 할 만큼 오래 걸리고 있습니다." 라고 말하는 방법입니다.

-

Multi-colored macOS beachball busy spinner

+

Multi-colored macOS beachball busy spinner

-

이것은 당황스러운 경험이며, 특히 요즘과 같이 컴퓨터가 여러개 프로세서를 돌리는 시대에는 컴퓨터 성능을 효율적으로 쓰지 못하는 처사입니다. 당신이 다른 코어 프로세서에 다른 작업들을 움직이게 하고 작업이 완료되면 알려줄 수 있을 때, 무언가를 기다리는 것은 의미가 없습니다 .그 동안 다른 작업을 수행할 수 있고, 이것이 비동기 프로그래밍의 기본입니다. 이러한 작업을 비동기적으로 실행할 수 있는 API를 제공하는 것은 당신이 사용하고 있는 프로그래밍 환경(웹 개발의 경우 웹브라우저) 에 달려 있습니다.

+

이는 답답한 경험이며 컴퓨터 처리 능력의 좋은 활용법이 아닙니다. 특히 컴퓨터에 여러 프로세서 코어가 있는 시대에서요. 다른 작업을 다른 프로세서 코어에 시키고 작업이 끝났을 때 알 수 있는데도 가만히 앉아서 기다리는건 의미가 없습니다. 이를 활용하면 여러분이 어떤 작업이 실행되는 동안 다른 작업을 할 수 있는데, 이것이 비동기 프로그래밍의 기초입니다. 작업을 비동기적으로 실행할 수 있는 API를 제공하는 것은 여러분이 사용하고 있는 프로그래밍 환경(웹 개발의 경우 웹 브라우저)의 역할입니다.

-

Blocking code

+

블로킹 코드

-

비동기 기법은 특히 웹 프로그래밍에 매우 유용합니다. 웹 앱이 브라우저에서 특정 코드를 실행하느라 브라우저에게 제어권을 돌려주지 않으면 브라우저는 마치 정지된 것처럼 보일 수 있습니다. 이러한 현상을 blocking 이라고 부릅니다. 자세히 정의하자면, 사용자의 입력을 처리하느라 웹 앱이 프로세서에 대한 제어권을 브라우저에게 반환하지 않는 현상 입니다..

+

비동기 기법은 특히 웹 프로그래밍에서 매우 유용합니다. 웹 앱이 브라우저에서 많은 코드를 실행하느라 브라우저에게 제어권을 돌려주지 않으면 브라우저는 마치 정지된 것처럼 보일 수 있습니다. 이를 블로킹이라고 하며, 웹 앱이 프로세서 제어권을 반환하기 전까지 브라우저가 사용자 입력을 처리하거나 다른 작업을 수행하는 것이 차단되는 현상입니다.

-

Blocking의 몇 가지 예를 살펴보겠습니다.

+

블로킹의 몇 가지 예를 살펴봅시다.

-

여기 simple-sync.html 예시가 있습니다. (see it running live), 하나의 버튼에 클릭 이벤트리스너를 지정하여 시간이 오래 걸리는 처리를 하도록하였습니다. (날짜를 천만번 계산하고 마지막에 콘솔에 날짜를 출력합니다.) 그리고 처리가 끝나면 페이지에 간단한 문장을 한 줄 출력합니다. :

+

이 simple-sync.html 예시에서 (동작하는 예시는 여기에서 확인하세요), 버튼에 클릭 이벤트 처리기를 추가해서 클릭할 때 마다 시간이 오래 걸리는 처리(날짜를 천만번 계산하고 마지막 날짜를 콘솔에 출력합니다)를 하고 DOM에 문단을 하나 추가합니다.

-
const btn = document.querySelector('button');
+
const btn = document.querySelector('button');
 btn.addEventListener('click', () => {
   let myDate;
   for(let i = 0; i < 10000000; i++) {
@@ -59,18 +68,18 @@ 

Blocking code

이 예제를 실행할 때 JavaScript 콘솔을 열고 버튼을 클릭하면, 콘솔에 메시지가 출력되기 전 까지 페이지에 문장이 나타나지 않는다는 것을 알 수 있습니다. 코드는 위에서 아래로 순차적으로 실행되며, 아래쪽 코드는 위쪽 코드의 처리가 끝날 때 까지 실행되지 않습니다.

-
-

Note: 앞의 예제는 매우 비현실적입니다. 실제 웹 앱에서 날짜를 천만번 계산할 일은 없습니다. 실제로 보여주기 위해 극단적인 예시를 들었을 뿐입니다..

+
+

Note: 앞의 예제는 매우 비현실적입니다. 실제 웹 앱에서 날짜를 천만번 계산할 일은 없습니다. 여러분께 보여드리기 위해 극단적인 예시를 들었을 뿐입니다.

-

두 번째 예제를 살펴보겠습니다. simple-sync-ui-blocking.html (see it live),  페이지에 UI가 모두 표시되기 전 까지 사용자의 입력을 막는 좀 더 현실적인 예시입니다. 이번 예시에는 두 가지 버튼을 사용합니다. :

+

두 번째 예제 simple-sync-ui-blocking.html 에서는 (동작하는 예시는 여기에서 확인하세요), 실제 페이지에서 만나볼 법 한 조금 더 현실적인 예시를 만나볼 수 있습니다. 이번에는 두 가지 버튼을 사용합니다.

    -
  • "Fill canvas" 버튼을 클릭하면 {{htmlelement("canvas")}} 태그에 100만개의 파란색 원을 채웁니다. (실행하면 원이 너무 많아서 원이 아니라 배경이 그냥 파란색으로 채워집니다.)
  • +
  • "Fill canvas" 버튼을 클릭하면 {{htmlelement("canvas")}}에 100만개의 파란색 원을 채웁니다.
  • "Click me for alert" 버튼은 사용자에게 메시지를 출력합니다.
-
function expensiveOperation() {
+
function expensiveOperation() {
   for(let i = 0; i < 1000000; i++) {
     ctx.fillStyle = 'rgba(0,0,255, 0.2)';
     ctx.beginPath();
@@ -85,75 +94,75 @@ 

Blocking code

alert('You clicked me!') );
-

첫 번째 버튼을 클릭한 후 두 번째 버튼을 바로 클릭하면 경고 박스가 나타나지 않는 것을 확인할 수 있습니다. 첫 번째 버튼은 이벤트가 끝나기 전 까지 다음 작동을 막아버립니다.

+

첫 번째 버튼을 클릭한 후 두 번째 버튼을 빠르게 클릭하면, 경고 박스가 바로 나타나지 않고 원이 다 그려진 다음 나타납니다. 첫 번째 작업은 끝나기 전까지 두 번째 작업을 막아버립니다.

-
-

Note: OK, in our case, it is ugly and we are faking the blocking effect, but this is a common problem that developers of real apps fight to mitigate all the time.

+
+

Note: 네, 이번 예제 코드는 예쁘지 않고 블로킹 효과를 일부러 만들어내고 있습니다. 하지만 이것이 실제 앱 개발자들이 항상 완화하기 위해 싸우고 있는 흔한 문제입니다.

-

왜 이런 현상이 발생할까요? 답은 자바스크립트는 기본적으로 single threaded이기 때문입니다. 이 시점에서 threads의 개념을 소개할 필요가 있겠군요

+

왜 이런 현상이 발생할까요? 답은 JavaScript는 기본적으로 싱글 스레드이기 때문입니다. 이 시점에서 스레드의 개념을 소개할 필요가 있겠네요.

-

Threads

+

스레드

-

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

+

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

-
Task A --> Task B --> Task C
+
작업 A --> 작업 B --> 작업 C
-

위의 예시처럼 각 작업은 순차적으로 실행되며, 다음 작업을 시작하려면 앞의 작업이 완료되어야 합니다.

+

각 작업은 순차적으로 실행되며, 다음 작업을 시작하려면 앞의 작업이 완료되어야 합니다.

-

앞서 말했듯이, 많은 컴퓨터들이 현재 여러 개의 CPU코어를 가지고 있기 때문에, 한 번에 여러가지 일을 수행할 수 있습니다. Multiple thread를 지원하는 프로그래밍 언어는 멀티코어 컴퓨터의 CPU를 사용하여 여러 작업을 동시에 처리할 수 있습니다. :

+

앞서 말씀드렸듯이, 많은 컴퓨터들이 현재 여러 개의 CPU코어를 가지고 있기 때문에, 한 번에 여러가지 일을 수행할 수 있습니다. 멀티 스레드를 지원하는 프로그래밍 언어는 CPU의 여러 코어를 사용하여 여러 작업을 동시에 처리할 수 있습니다.

-
Thread 1: Task A --> Task B
-Thread 2: Task C --> Task D
+
스레드 1: 작업 A --> 작업 B
+스레드 2: 작업 C --> 작업 D
-

JavaScript is single threaded

+

JavaScript는 싱글 스레드다

-

자바스크립트는 전통적으로 싱글 thread입니다. 컴퓨터가 여러 개의 CPU를 가지고 있어도 main thread라 불리는 단일 thread에서만 작업을 실행할 수 있습니다. 위의 예시는 아래처럼 실행됩니다. :

+

자바스크립트는 전통적으로 싱글 스레드입니다. CPU가 여러 개의 코어를 가지고 있어도 메인 스레드라 하는 하나의 스레드에서만 작업을 실행할 수 있습니다. 위의 예시는 아래처럼 실행됩니다.

-
Main thread: Render circles to canvas --> Display alert()
+
메인 스레드: 캔버스에 원을 그림 --> alert() 표시
-

JavaScript는 이러한 문제를 해결하기 위해 몇 가지 툴을 도입했습니다. Web workers는 여러 개의 JavaScript 청크를 동시에 실행할 수 있도록 worker라고 불리는 별도의 스레드로 보낼 수 있습니다. 따라서 시간이 오래 걸리는 처리는 woker를 사용해 처리하면 blocking 발생을 막을 수 있습니다..

+

시간이 지나 JavaScript에는 이런 문제를 해결하기 위한 몇 가지 도구가 생겼습니다. 웹 워커는 JavaScript 연산 일부를 워커라고 하는 별도의 스레드로 보내서 여러 JavaScript 코드를 동시에 실행할 수 있게 해줍니다. 일반적으로 시간이 오래 걸리는 연산을 워커를 사용해 처리하여 메인 스레드가 사용자 상호작용을 중단하지 않도록 합니다.

-
  Main thread: Task A --> Task C
-Worker thread: Expensive task B
+
메인 스레드: 작업 A --> 작업 C
+워커 스레드: 시간이 오래 걸리는 작업 B
-

위의 내용을 잘 기억하시고 다음 예제를 살펴보세요. simple-sync-worker.html (see it running live), JavaScript 콘솔을 함께 열어주세요. 이전 예시는 날짜를 천만 번 계산하고 페이지에 문장을 출력했지만, 이번엔 천만번 계산 전 문장을 페이지에 출력해줍니다. 더이상 첫 번째 작업이 두 번째 작업을 차단하지 않습니다.

+

위의 내용을 잘 기억하시고 다음 예제 simple-sync-worker.html (동작하는 예시는 여기에서 확인하세요)를 열어서, JavaScript 콘솔도 함께 열어주세요. 이전 예시는 날짜를 천만 번 계산하고 페이지에 문장을 출력했지만, 이번엔 워커를 사용하여 날짜를 계산합니다. 코드는 여기에서 확인하실 수 있습니다. worker.js. 버튼을 클릭하면, 브라우저가 날짜 계산 천만번이 끝나기 전에 문단을 표시합니다. 워커가 계산을 끝마치면 마지막 날짜 계산 결과를 콘솔에 출력합니다. 더이상 첫 번째 작업이 두 번째 작업을 차단하지 않는 것을 확인하실 수 있습니다.

-

Asynchronous code

+

비동기 코드

-

Web worker는 꽤 유용하지만 이들도 한계가 있습니다. 주요한 내용은 Web worker는 {{Glossary("DOM")}} 에 접근할 수 없습니다. — UI를 업데이트하도록 worker에게 어떠한 지시도 직접 할 수 없습니다. 두 번째 예시에서 worker는 100만개의 파란색 원을 만들 수 없습니다. 단순히 숫자만 계산합니다.

+

웹 워커는 꽤 유용하지만 한계가 있습니다. 가장 큰 한 가지는 웹 워커는 {{Glossary("DOM")}} 에 접근할 수 없다는 것입니다 — 워커가 UI를 직접 업데이트를 하는게 불가능합니다. 두 번째 예시를 워커로 다시 작성한다면 워커에서는 100만개의 파란색 원을 그릴 수 없습니다. 단순히 숫자만 계산할 수 있습니다.

-

두 번째 문제는 worker에서 실행되는 코드는 차단되지 않지만 동기적으로 실행된다는 것 입니다. 이러한 문제는 함수를 사용할 때 발생합니다. 어떤 함수가 일의 처리를 위해 이전의 여러 프로세스의 결과를 return 받아야 할 경우 입니다. 동기적으로 실행되면 함수 실행에 필요한 매개변수를 받아올 수 없는 경우가 생기므로 함수는 사용자가 원하는 기능을 제대로 실행할 수 없습니다.

+

두 번째로 워커에서 실행되는 코드는 블로킹하지는 않지만 동기적으로 실행된다는 것 입니다. 이는 어떤 함수가 여러 다른 함수의 실행 결과에 의존하는 경우 문제가 됩니다. 다음 스레드 다이어그램을 봅시다.

-
Main thread: Task A --> Task B
+
메인 스레드: 작업 A --> 작업 B
-

이 예시에서 Task A는 서버로부터 이미지를 가져오고 Task B는 그 이미지에 필터를 적용하는 것과 같은 작업을 수행한다고 가정합니다. Task A를 실행하고 결과를 반환할 시간도 없이 Task B를 실행해버리면 에러가 발생할 것 입니다. 왜냐햐면 Task A에서 이미지를 완전히 가져온 상태가 아니기 때문이죠.

+

이 예시에서 작업 A는 서버로부터 이미지를 가져오는 작업을, 작업 B는 그 이미지에 필터를 적용하는 것과 같은 추가적인 작업을 수행한다고 생각합시다. 작업 A를 실행하고 결과를 반환할 시간도 없이 작업 B를 실행하려고 하면 에러가 발생할 것 입니다. 작업 A가 아직 이미지를 다 가져오지 않았기 때문입니다.

-
  Main thread: Task A --> Task B --> |Task D|
-Worker thread: Task C -----------> |      |
+
메인 스레드: 작업 A --> 작업 B --> |작업 D|
+워커 스레드: 작업 C -----------> |      |
-

이번 예시에선 Task D가 Task B와 Task C의 결과를 모두 사용한다고 가정합니다. Task B와 Task C가 동시에 아주 빠르게 결과를 반환하면 매우 이상적이겠지만, 현실은 그렇지 않습니다. Task D가 사용될 때 Task B, Task C 둘 중 어느 값이라도 입력이 되지 않을경우 에러가 발생합니다.

+

이번 예시에선 작업 D가 작업 B와 작업 C의 결과를 모두 사용한다고 생각합시다. 작업 B와 작업 C의 결과를 항상 동시에 사용할 수 있다면 이상적이겠지만, 현실은 그렇지 않습니다. 작업 D가 실행될 때 작업 B, 작업 C 둘 중 어느 작업 하나라도 끝나지 않았을 경우 에러가 발생할 것입니다.

-

이러한 문제를 해결하기 위해 브라우저를 통해 특정 작업을 비동기적으로 실행할 수 있습니다. 바로 Promises 를 사용하는것 입니다. 아래 예시처럼 Task A가 서버에서 이미지를 가져오는 동안 Task B를 기다리게 할 수 있습니다. :

+

이러한 문제를 해결하기 위해 브라우저를 통해 특정 작업을 비동기적으로 실행할 수 있습니다. 프로미스를 사용하면 아래 예시처럼 작업 A가 서버에서 이미지를 가져오는 동안 작업 B를 기다리게 할 수 있습니다.

-
Main thread: Task A                   Task B
-    Promise:      |__async operation__|
+
메인 스레드: 작업 A                 작업 B
+   프로미스:       |__비동기 작업__|
-

위의 작업은 다른 곳에서 처리가 되므로, 비동기 작업이 진행되는 동안 main thread가 차단되지 않습니다.

+

위의 작업은 다른 곳에서 처리되므로, 비동기 작업이 진행되는 동안 메인 스레드가 블로킹되지 않습니다.

-

이번 문서에서 다룬 내용은 매우 중요한 내용입니다. 다음 문서에선 비동기 코드를 어떻게 쓸 수 있는지 살펴볼 계획이므로 끝까지 읽어주시면 좋겠습니다.

+

다음 문서에서는 비동기 코드를 어떻게 작성할 수 있는지 알아봅시다. 즐겁지 않나요? 계속 읽어보세요!

-

결론

+

결론

-

현대의 소프트웨어 설계는 프로그램이 한 번에 두 가지 이상의 일을 할 수 있도록 비동기 프로그래밍을 중심으로 돌아가고 있습니다. 보다 새롭고 강력한 API를 이용하면서, 비동기로 작업해야만 하는 사례가 많아질 것입니다. 예전에는 비동기 코드를 쓰기가 힘들었습니다. 여전히 아직 어렵지만, 훨씬 쉬워졌습니다. 이 모듈의 나머지 부분에서는 비동기 코드가 왜 중요한지, 위에서 설명한 일부 문제들을 방지하는 코드 설계 방법에 대해 자세히 알아봅시다.

+

현대의 소프트웨어 설계는 프로그램이 한 번에 하나보다 더 많은 일을 할 수 있도록 비동기 프로그래밍을 중심으로 돌아가고 있습니다. 새롭고 강력한 API를 이용하다 보면 비동기로 작업해야만 하는 사례를 많이 만나게 될 것입니다. 예전에는 비동기 코드를 쓰기가 힘들었습니다. 하지만 지금은 익숙해지는데 시간이 조금 걸릴 뿐 훨씬 쉬워졌습니다. 이 모듈의 나머지 부분에서는 비동기 코드가 왜 중요한지, 위에서 설명한 문제들 중 일부를 방지하는 코드 설계는 어떻게 하는지 자세히 알아봅시다.

-

이번 module 에서는..

+

이 모듈의 내용

diff --git a/files/ko/learn/javascript/asynchronous/index.html b/files/ko/learn/javascript/asynchronous/index.html index bcf2abdd454334..32d9b04d2538ec 100644 --- a/files/ko/learn/javascript/asynchronous/index.html +++ b/files/ko/learn/javascript/asynchronous/index.html @@ -1,5 +1,5 @@ --- -title: Asynchronous JavaScript +title: 비동기 JavaScript slug: Learn/JavaScript/Asynchronous tags: - Beginner @@ -7,7 +7,6 @@ - Guide - JavaScript - Landing - - NeedsTranslation - Promises - TopicStub - async @@ -21,39 +20,39 @@ ---
{{LearnSidebar}}
-

In this module we take a look at {{Glossary("asynchronous")}} {{Glossary("JavaScript")}}, why it is important, and how it can be used to effectively handle potential blocking operations such as fetching resources from a server.

+

이 모듈에서 우리는 {{Glossary("asynchronous")}} {{Glossary("JavaScript")}}를 살펴보고, 이것이 왜 중요한지, 또 리소스를 서버에서 가져오는 것과 같은 잠재적 블로킹 작업을 어떻게 효율적으로 처리할 수 있는지 배웁니다.

-

Prerequisites

+

필요한 사전 지식

-

Asynchronous JavaScript is a fairly advanced topic, and you are advised to work through JavaScript first steps and JavaScript building blocks modules before attempting this.

+

비동기 JavaScript는 상당히 고급 주제이며, 이 모듈을 보기에 앞서 JavaScript first stepsJavaScript building blocks 모듈을 먼저 보고 오시기를 권장합니다.

-

If you are not familiar with the concept of asynchronous programming, you should definitely start with the General asynchronous programming concepts article in this module. If you are, then you can probably skip to the Introducing asynchronous JavaScript module.

+

비동기 프로그래밍의 개념에 익숙하지 않으시다면, 이 모듈의 일반 비동기 프로그래밍 개념 부터 시작해보세요. 익숙하시다면, Introducing asynchronous JavaScript 모듈로 건너뛰어도 괜찮습니다.

-

Note: If you are working on a computer/tablet/other device where you don't have the ability to create your own files, you can try out (most of) the code examples in an online coding program such as JSBin or Thimble.

+

Note: 만약 여러분의 파일을 직접 만들 수 없는 컴퓨터/태블릿/기타 기기 환경에서 작업하신다면, (대부분의) 코드 예제들을 JSBin 혹은 Thimble과 같은 온라인 코딩 프로그램에서 사용해 볼 수 있습니다.

-

Guides

+

가이드

-
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.

+

이 문서에서 우리는 비동기 방식 JavaScript와 관련된 여러 중요한 개념들을 배우고, 웹 브라우저와 JavaScript에서 어떻게 보이는지 알아봅니다. 이 모듈의 다른 문서를 보기 전에 이 문서에 나와있는 개념을 꼭 이해하고 넘어가야 합니다.

-
Introducing asynchronous JavaScript
-
In this article we briefly recap the problems associated with sychronous JavaScript, and take a first look at some of the different asynchronous JavaScript techniques you'll encounter, showing how they can help us solve such problems.
-
Cooperative asynchronous JavaScript: Timeouts and intervals
-
Here we look at the traditional methods JavaScript has available for running code asychronously after a set time period has elapsed, or at a regular interval (e.g. a set number of times per second), talk about what they are useful for, and look at their inherent issues.
-
Handling async operations gracefully with Promises
-
Promises are a comparatively new feature of the JavaScript language that allow you to defer further actions until after the previous action has completed, or respond to its failure. This is really useful for setting up a sequence of operations to work correctly. This article shows you how promises work, where you'll see them in use in WebAPIs, and how to write your own.
-
Making asynchronous programming easier with async and await
-
Promises can be somewhat complex to set up and understand, and so modern browsers have implemented async functions and the await operator — the former allows standard functions to implicitly behave asynchronously with promises, whereas the latter can be used inside async functions to wait for promises before the function continues, making chaining of promises easier. This article explains async/await.
-
Choosing the right approach
-
To finish this module off, we'll consider the different coding techniques and features we've discussed throughout, looking at which ones you should use when, with recommendations and reminders of common pitfalls where appropriate.
+
비동기 JavaScript 입문
+
이 문서에서 우리는 동기 방식 JavaScript와 관련된 여러 문제점들을 간단히 돌아보고, 이를 해결할 수 있게 도와주는 여러 비동기 방식 JavaScript 기술을 만나봅니다.
+
협력하는 비동기 JavaScript: 타임아웃과 인터벌
+
여기에서 우리는 JavaScript에서 코드를 일정 시간이 지난 다음에 실행하거나, 일정한 간격(예: 초당 몇 회)으로 실행할 수 있는 기존 방법을 살펴보고, 이 방법이 어디에 유용한지, 내재된 문제는 무엇이 있는지 살펴봅니다.
+
프로미스와 함께하는 우아한 비동기 프로그래밍
+
프로미스는 JavaScript 언어의 비교적 최신 기능으로써 어떤 동작이 끝날 때까지 기다렸다가 다음 동작을 실행하거나, 이전 동작이 실패했을 때 대응할 수 있는 방법을 제공합니다. 이는 일련의 작업을 올바르게 작동하도록 설정하는 데 굉장히 유용합니다. 이 문서에서는 프로미스가 어떻게 동작하는지, WebAPI에서 어디에 사용하고 있는지, 여러분의 프로미스를 어떻게 만들 수 있는지 보여줍니다.
+
비동기 프로그래밍을 쉽게 만드는 async와 await
+
프로미스는 설정하고 이해하는 데 복잡할 수 있어, 현대 브라우저들은 async 함수와 await 연산자를 구현했습니다 — 전자는 일반적인 함수를 암시적으로 프로미스와 함께 비동기적으로 동작하도록 만들고, 후자는 async 함수 안에서 함수가 진행되기 전에 프로미스를 기다리도록 하여, 쉽게 여러 프로미스를 체이닝할 수 있도록 합니다. 이 문서는 async/await을 설명합니다.
+
올바른 접근 방식 선택하기
+
이 모듈을 마무리하기 위해, 우리는 지금까지 얘기한 여러 코딩 기법과 기능들을 살펴보고, 어떤 기능을 어떨 때 사용해야 하는지 권장 사항과 사용할 때의 주의 사항을 살펴봅니다.
-

See also

+

같이 보기

diff --git a/files/ko/learn/javascript/asynchronous/introducing/index.html b/files/ko/learn/javascript/asynchronous/introducing/index.html index a63eb661589ed7..d16e1c78f489a6 100644 --- a/files/ko/learn/javascript/asynchronous/introducing/index.html +++ b/files/ko/learn/javascript/asynchronous/introducing/index.html @@ -1,36 +1,57 @@ --- -title: Introducing asynchronous JavaScript +title: 비동기 JavaScript 입문 slug: Learn/JavaScript/Asynchronous/Introducing translation_of: Learn/JavaScript/Asynchronous/Introducing +tags: + - Beginner + - CodingScripting + - Guide + - Introducing + - JavaScript + - Learn + - Promises + - async + - asynchronous + - await + - callbacks + - 가이드 + - 입문 + - 자바스크립트 + - 학습 + - 프로미스 + - 어싱크 + - 비동기 + - 어웨이트 + - 콜백 ---
{{LearnSidebar}}
{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}
-

이 문서에선 JavaScript의 동기식 처리와 관련된 문제를 간략하게 요약하고, 앞으로 접하게 될 다른 비동기 기술들을 살펴보며, 어떻게 우리에게 도움이 될 수 있는지 살펴봅니다.

+

이 문서에선 JavaScript의 동기식 처리와 관련된 문제를 간략하게 돌아보고, 앞으로 접하게 될 다른 비동기 기술들을 살펴보며, 어떻게 우리에게 도움이 될 수 있는지 살펴봅니다.

- - + + - +
준비:Basic computer literacy, a reasonable understanding of JavaScript fundamentals.필요한 사전 지식:기본적인 컴퓨터 활용 능력, JavaScript 기초에 대한 이해.
목표:학습 목표: -

비동기 자바스크립트에 대해 더 알기 위해, 동기 스크립트와 어떤 부분이 다른지 그리고 사용 사례를 알 수 있다.

+

비동기식 JavaScript와 좀 더 친숙해지고, 동기식 JavaScript와 어떻게 다르며 어떤 사용처가 있는지 안다.

-

Synchronous JavaScript

+

동기식 JavaScript

-

{{Glossary("asynchronous")}} JavaScript가 무엇인지 이해하려면, 우리는 {{Glossary("synchronous")}} JavaScript가 무엇인지 알아야 합니다. 이 문서에선 이전 문서에서 본 정보의 일부를 요약하겠습니다.

+

{{Glossary("asynchronous")}} JavaScript가 무엇인지 이해하려면, 먼저 {{Glossary("synchronous")}} JavaScript가 무엇인지 알아야 합니다. 이 부분에선 이전 문서에서 배웠던 내용을 복습해봅시다.

-

이전의 학습 모듈에서 살펴본 많은 기능들은 동기식 입니다. — 약간의 코드를 실행하면, 브라우저가 할 수 있는 한 빠르게 결과를 보여줍니다. 다음 예제를 살펴볼까요 (see it live here, and see the source):

+

이전의 학습 모듈에서 살펴본 대다수의 기능들은 동기식입니다. 코드를 실행하면, 브라우저가 할 수 있는 한 빠르게 결과를 보여줍니다. 간단한 예제를 살펴봅시다 (동작하는 예제는 여기에서, 소스는 여기에서 볼 수 있습니다).

-
const btn = document.querySelector('button');
+
const btn = document.querySelector('button');
 btn.addEventListener('click', () => {
   alert('You clicked me!');
 
@@ -40,55 +61,55 @@ 

Synchronous JavaScript

});
-

이 블럭에서 코드는 위에서 아래로 차례대로 실행됩니다. :

+

이 블록에서 코드는 위에서 아래로 차례대로 실행됩니다.

    -
  1. DOM에 미리 정의된 {{htmlelement("button")}} element 를 참조합니다.
  2. -
  3. click 이벤트 리스너를 만들어 버튼이 클릭됐을 때 아래 기능을 차례로 실행합니다. : +
  4. DOM에 미리 정의된 {{htmlelement("button")}} 요소의 참조를 가져옵니다.
  5. +
  6. click 이벤트 수신기를 버튼에 추가해 버튼을 클릭하면 아래 기능을 차례로 실행합니다.
      -
    1. alert() 메시지가 나타납니다.
    2. -
    3. 메시지가 사라지면 {{htmlelement("p")}} element를 만듭니다.
    4. -
    5. 그리고 text content를 만듭니다.
    6. -
    7. 마지막으로 docuent body에 문장을 추가합니다.
    8. +
    9. alert() 메시지가 나타납니다.
    10. +
    11. alert가 사라지면 {{htmlelement("p")}} 요소를 만듭니다.
    12. +
    13. 만든 문단 요소에 내용 문자열을 넣습니다.
    14. +
    15. 마지막으로 문서 body에 문단을 추가합니다.
-

각 작업이 처리되는 동안 렌더링은 일시 중지됩니다. 앞에서 말한 문서와 같이, JavaScript 는 single threaded이기 때문입니다. 한 번에 한 작업만, 하나의 main thread에서 처리될 수 있습니다. 그리고 다른 작업은 앞선 작업이 끝나야 수행됩니다.

+

각 작업이 처리되는 동안 다른 일은 일어나지 못합니다. 렌더링 과정은 잠시 중단됩니다. 이전 문서에서 얘기했듯이, JavaScript는 싱글 스레드이기 때문입니다. 한 번에 한 작업만, 하나의 메인 스레드에서 처리될 수 있습니다. 다른 작업은 앞선 작업이 끝나야 수행됩니다.

-

따라서 앞의 예제는 사용자가 OK 버튼을 누를 때까지 문장이 나타나지 않습니다. :

+

따라서 앞의 예제는 사용자가 alert의 확인 버튼을 누를 때까지 문장이 나타나지 않습니다. 아래에서 직접 확인해보세요.

-

{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}

+

{{EmbedLiveSample('Synchronous_JavaScript', '100%', '110px')}}

-
-

Note: 기억해두세요. alert() 는 동기 블럭을 설명하는데 아주 유용하지만, 실제 어플리케이션에서 사용하기엔 아주 끔찍합니다.

+
+

Note: alert()는 동기식의 블로킹 작업을 설명하는데 아주 유용하지만, 실제 어플리케이션에서는 사용하기에는 끔찍한 선택지라는걸 기억해주세요.

-

Asynchronous JavaScript

+

비동기식 JavaScript

-

앞서 설명된 이유들 (e.g. related to blocking) 때문에 많은 웹 API기능은 현재 비동기 코드를 사용하여 실행되고 있습니다. 특히 외부 디바이스에서 어떤 종류의 리소스에 액세스 하거나 가져오는 기능들에 많이 사용합니다. 예를 들어 네트워크에서 파일을 가져오거나, 데이터베이스에 접속해 특정 데이터를 가져오는 일, 웹 캠에서 비디오 스트림에 엑세스 하거나, 디스플레이를 VR 헤드셋으로 브로드캐스팅 하는것 입니다.

+

앞서 설명된 이유들 (블로킹과 관련된) 때문에 지금의 많은 웹 API 기능은 비동기 코드로 실행되고 있습니다. 특히 외부 기기에서 어떤 종류의 리소스에 접근하거나 가져오는 기능들에 많이 사용합니다. 예를 들어 네트워크에서 파일을 가져오거나, 데이터베이스에 접근해 특정 데이터를 가져오는 일, 웹캠에서 비디오 스트림에 접근하거나, 화면을 VR 헤드셋으로 보내는 일 등이 있습니다.

-

동기적 코드를 사용하여 작업을 처리하는데 왜 이렇게 어려울까요? 다음 예제를 살펴보겠습니다. 서버에서 이미지를 가져오면 네트워크 환경, 다운로드 속도 등의 영향을 받아 이미지를 즉시 확인할 수 없습니다. 이 말은 아래 코드가 (pseudocode) 실행되지 않는다는 의미 입니다. :

+

이런 작업들을 동기식 코드를 사용하여 처리하는 것은 왜 어려운 일일까요? 다음 예제를 살펴보겠습니다. 서버에서 이미지를 가져온다고 할 때, 이미지는 코드를 호출해도 바로 사용할 수 없습니다. 이는 아래(의사 코드)처럼 작성하면 제대로 동작하지 않는다는 의미입니다.

-
let response = fetch('myImage.png');
+
let response = fetch('myImage.png');
 let blob = response.blob();
-// display your image blob in the UI somehow
+// 이미지 blob을 UI 어디에선가 표시하는 코드
-

왜냐하면 앞서 설명했듯이 이미지를 다운로드 받는데 얼마나 걸릴지 모르기 때문입니다. 그래서 두 번째 줄을 실행하면 에러가 발생할 것 입니다. (이미지의 크키가 아주 작다면 에러가 발생하지 않을 수도 있습니다. 반대로 이미지의 크기가 크면 매번 발생할 것 입니다.) 왜냐하면 response 가 아직 제공되지 않았기 때문입니다. 따라서 개발자는 response 가 반환되기 전 까지 기다리게 처리를 해야합니다.

+

왜냐하면 이미지를 다운로드 받는 데 얼마나 걸릴지 모르기 때문입니다. 그래서 두 번째 줄을 실행하면 에러가 발생합니다(이미지의 크기가 아주 작다면 에러가 발생하지 않을 수도 있습니다. 반대로 이미지의 크기가 크면 매번 발생할 것 입니다). 왜냐하면 response 가 아직 반환되지 않았기 때문입니다. 따라서 개발자는 response 가 반환되기 전까지 기다리도록 처리해야 합니다.

-

JavaScript에서 볼 수 있는 비동기 스타일은 두 가지 유형이 있습니다, 예전 방식인 callbacks 그리고 새로운 방식인 promise-style 코드 입니다. 이제부터 차례대로 살펴보겠습니다.

+

JavaScript 코드에서 볼 수 있는 비동기 처리 방식은 크게 두 가지 유형이 있습니다. 예전 방식인 콜백과 새로운 방식인 프로미스입니다. 이제부터 차례대로 살펴보겠습니다.

-

Async callbacks

+

비동기 콜백

-

Async callbacks은 백그라운드에서 코드 실행을 시작할 함수를 호출할 때 인수로 지정된 함수입니다. 백그라운드 코드 실행이 끝나면 callback 함수를 호출하여 작업이 완료됐음을 알리거나, 다음 작업을 실행하게 할 수 있습니다. callbacks을 사용하는 것은 지금은 약간 구식이지만, 여전히 다른 곳에서 사용이 되고있음을 확인할 수 있습니다.

+

비동기 콜백은 백그라운드에서 코드 실행을 시작할 함수를 호출할 때 매개변수로 지정된 함수입니다. 백그라운드 코드 실행이 끝나면 콜백 함수를 호출하여 작업이 완료됐음을 알리거나, 프로그래머의 관심이 필요한 다른 일이 일어났다고 알려줄 수 있습니다. 요즘 콜백을 사용하는 건 약간 옛날 방식이지만, 예전에 만들어졌으나 아직 범용적으로 쓰이고 있는 여러 API에서 볼 수 있습니다.

-

Async callback 의 예시는 {{domxref("EventTarget.addEventListener", "addEventListener()")}} 'click' 옆의 두 번째 매개변수 입니다. :

+

비동기 콜백의 예시 중 하나는 {{domxref("EventTarget.addEventListener", "addEventListener()")}}의 두 번째 매개변수 입니다.

-
btn.addEventListener('click', () => {
+
btn.addEventListener('click', () => {
   alert('You clicked me!');
 
   let pElem = document.createElement('p');
@@ -96,13 +117,13 @@ 

Async callbacks

document.body.appendChild(pElem); });
-

첫 번째 매개 변수는 이벤트 리스너 유형이며, 두 번째 매개 변수는 이벤트가 실행 될 때 호출되는 콜백 함수입니다.

+

첫 번째 매개변수는 이벤트 리스너 유형이며, 두 번째 매개변수는 이벤트가 발생할 때 호출되는 콜백 함수입니다.

-

callback 함수를 다른 함수의 인수로 전달할 때, 함수의 참조를 인수로 전달할 뿐이지 즉시 실행되지 않고, 함수의 body에서 “called back”됩니다. 정의된 함수는 때가 되면 callback 함수를 실행하는 역할을 합니다.

+

콜백 함수를 다른 함수의 매개변수로 전달할 때, 함수의 참조를 매개변수로 전달할 뿐입니다. 콜백 함수는 바로 실행되지는 않고, 다른 함수의 본문에서 비동기적으로 “called back” (이름대로 나중에 호출)됩니다. 콜백 함수를 담고 있는 함수는 때가 되면 콜백 함수를 실행할 책임이 있습니다.

-

XMLHttpRequest API (run it live, and see the source)를 불러오는 예제를 통해 callback 함수를 쉽게 사용해봅시다. :

+

콜백을 사용한 함수는 여러분도 쉽게 만드실 수 있습니다. XMLHttpRequest API (동작하는 예제는 여기에서, 소스는 여기에서 확인하세요)로 리소스를 불러오는 예제를 확인해봅시다.

-
function loadAsset(url, type, callback) {
+
function loadAsset(url, type, callback) {
   let xhr = new XMLHttpRequest();
   xhr.open('GET', url);
   xhr.responseType = type;
@@ -124,25 +145,25 @@ 

Async callbacks

loadAsset('coffee.jpg', 'blob', displayImage);
-

displayImage()함수는 Object URL로 전달되는 Blob을 전달받아, URL이 나탸내는 이미지를 만들어 <body>에 그립니다. 그러나, 우리는 loadAsset() 함수를 만들고 "url", "type" 그리고 "callback"을 매개변수로 받습니다. XMLHttpRequest (줄여서 "XHR") 를 사용하여 전달받은 URL에서 리소스를 가져온 다음 callback으로 응답을 전달하여 작업을 수행합니다. 이 경우 callback은 callback 함수로 넘어가기 전, 리소스 다운로드를 완료하기 위해 XHR 요청이 진행되는 동안 대기합니다. (onload 이벤트 핸들러 사용)

+

blob을 받아 객체 URL로 만들고, 이미지에 넣어 <body>에 추가해 화면에 그리는 displayImage()함수를 만들었습니다. 그런 다음 콜백 함수와 불러올 url, 콘텐츠 타입을 매개변수로 받는 loadAsset() 함수를 만들어봅시다. XMLHttpRequest (줄여서 "XHR") 를 사용하여 URL에서 리소스를 가져온 다음 응답을 콜백으로 전달하여 다른 작업을 수행합니다. 이 경우 콜백은 XHR 호출이 리소스 다운로드를 완료할 때 까지 대기합니다. (onload 이벤트 처리기 사용)

-

Callbacks은 다재다능 합니다. 함수가 실행되는 순서, 함수간에 어떤 데이터가 전달되는지를 제어할 수 있습니다. 또한 상황에 따라 다른 함수로 데이터를 전달할 수 있습니다. 따라서 응답받은 데이터에 따라 (processJSON(), displayText()등) 어떤 작업을 수행할지 지정할 수 있습니다.

+

콜백은 다재다능 합니다. 콜백은 함수가 실행되는 순서와 함수간에 전달되는 데이터를 제어할 수 있을 뿐 아니라, 데이터를 상황에 따라 다른 함수로 전달할 수 있게 해줍니다. 응답받은 데이터가 json이라면 processJSON(), 단순 문자열이라면 displayText() 를 호출하는 등 유연하게 작업을 처리할 수 있습니다.

-

모든 callback이 비동기인 것은 아니라는 것에 유의하세요 예를 들어 {{jsxref("Array.prototype.forEach()")}} 를 사용하여 배열의 항목을 탐색할 때가 있습니다. (see it live, and the source):

+

모든 콜백이 비동기인건 아니라는 점에 유의하세요. 동기적으로 실행되는 콜백도 있습니다. 예를 들어 {{jsxref("Array.prototype.forEach()")}} 를 사용하여 배열의 항목을 탐색하는 경우입니다 (동작하는 예제는 여기에서, 소스는 여기에서 확인하세요).

-
const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
+
const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
 
 gods.forEach(function (eachName, index){
   console.log(index + '. ' + eachName);
 });
-

이 예제에선 그리스 신들의 배열을 탐색하여 인덱스 넘버와 그 값을 콘솔에 출력합니다. forEach() 매개변수는 callback 함수이며, callback 함수는 배열 이름과 인덱스 총 두 개의 매개변수가 있습니다. 그러나, 여기선 비동기로 처리되지 않고 즉시 실행됩니다..

+

이 예제에선 그리스 신들의 이름을 저장한 배열을 순회하며 인덱스 숫자와 요소 값을 콘솔에 출력합니다. forEach()는 매개변수로 콜백 함수를 받으며, 콜백 함수는 배열의 이름 값에 대한 참조와 인덱스, 두 개의 매개변수를 받습니다. 그러나 여기선 비동기로 처리되지 않고 즉시 실행됩니다.

-

Promises

+

프로미스

-

Promises 모던 Web APIs에서 보게 될 새로운 코드 스타일 입니다. 좋은 예는 fetch() API 입니다. fetch()는 {{domxref("XMLHttpRequest")}}보다 좀 더 현대적인 버전 입니다. 아래 Fetching data from the server 예제에서 빠르게 살펴볼까요?  :

+

프로미스는 현대 Web API에서 자주 보게 될 새로운 비동기 코드 스타일입니다. 프로미스의 좋은 예시로는 fetch() API가 있는데요, fetch()는 {{domxref("XMLHttpRequest")}}의 좀 더 현대적이고 효율적인 버전입니다. 아래 Fetching data from the server 예제에서 빠르게 살펴봅시다.

-
fetch('products.json').then(function(response) {
+
fetch('products.json').then(function(response) {
   return response.json();
 }).then(function(json) {
   products = json;
@@ -151,45 +172,45 @@ 

Promises

  console.log('Fetch problem: ' + err.message); });
-
-

Note: You can find the finished version on GitHub (see the source here, and also see it running live).

+
+

Note: GitHub에서 완성된 예제를 보실 수 있습니다 (소스는 여기에서, 동작하는 예제는 여기에서 확인하세요).

-

fetch() 는 단일 매개변수만 전달받습니다. — 네트워크에서 가지고 오고 싶은 리소스의 URL — 그리고 promise로 응답합니다. promise 는 비동기 작업이 성공 했는지 혹은 실패했는지를 나타내는 하나의 오브젝트 입니다. 즉 성공/실패 의 분기점이 되는 중간의 상태라고 표현할 수 있죠. 왜 promise라는 이름이 붙었는지 잠깐 살펴보자면.. "내가 할수 있는 한 빨리 너의 요청의 응답을 가지고 돌아간다고 약속(promise)할게" 라는 브라우저의 표현방식 이어서 그렇습니다.

+

fetch() 는 하나의 매개변수(네트워크에서 가지고 오고 싶은 리소스의 URL)를 받아 프로미스를 반환합니다. 프로미스는 비동기 작업의 완료 또는 실패를 나타내는 객체입니다. 말하자면 작업의 중간 상태를 나타냅니다. 이는 "가능한 한 빨리 답변을 준다고 약속(promise)할게" 라고 브라우저가 말하는 방식이며, 그래서 "약속"이라는 이름이 붙었습니다.

-

이 개념에 익숙해 지기 위해서는 연습이 필요합니다.; 마치 {{interwiki("wikipedia", "Schrödinger's cat")}}(슈뢰딩거의 고양이) 처럼 느껴질 수 있습니다. 위의 예제에서도 발생 가능한 결과 중 아직 아무것도 발생하지 않았기 때문에, 미래에 어떤 시점에서 fetch()작업이 끝났을때 어떤 작업을 수행 시키기 위해 두 가지 작업이 필요합니다. 예제에선 fetch() 마지막에 세 개의 코드 블럭이 더 있는데 이를 살펴보겠습니다. :

+

이 개념에 익숙해지기 위해서 연습이 필요할 수 있습니다. 약간 {{interwiki("wikipedia", "Schrödinger's cat")}}(슈뢰딩거의 고양이)를 보는듯한 느낌을 받으실겁니다. 발생 가능한 결과 중 아직 아무것도 발생하지 않았기 때문에, fetch 작업은 브라우저가 작업을 끝마치는 것을 기다리고 있습니다. fetch() 뒤에 세 개의 코드 블럭이 체이닝되어 있는데 이를 살펴봅시다.

    -
  • 두 개의 then() 블럭: 두 함수 모두 이전 작업이 성공했을때 수행할 작업을 나타내는 callback 함수 입니다. 그리고 각 callback함수는 인수로 이전 작업의 성공 결과를 전달받습니다. 따라서 성공했을때의 코드를 callback 함수 안에 작성하면 됩니다. 각 .then() 블럭은 서로 다른 promise를 반환합니다. 이 말은 .then() 을 여러개 사용하여 연쇄적으로 작업을 수행하게 할 수 있음을 말합니다. 따라서 여러 비동기 작업을 차례대로 수행할 수 있습니다.
  • -
  • catch() 블럭은 .then() 이 하나라도 실패하면 동작합니다. — 이는 동기 방식의 try...catch 블럭과 유사합니다. error 오브젝트는 catch()블럭 안에서 사용할 수 있으며, 발생한 오류를 보고하는 용도로 사용할 수 있습니다. 그러나 try...catch 는 나중에 배울 async/await에서는 동작하지만, promise와 함께 동작할 수 없음을 알아두세요.
  • +
  • 두 개의 then() 블록: 두 블록 모두 이전 작업이 성공했을 때 수행할 콜백 함수를 담고 있으며, 각 콜백은 매개변수로 이전의 성공한 작업 결과를 전달받으므로, 이 결과를 가지고 다른 작업을 수행할 수 있습니다. 각 .then() 블록은 새로운 프로미스를 반환합니다. 즉 각각의 프로미스에 따로 .then() 을 여러 개 체이닝하여 비동기 작업들을 순서대로(하나가 끝나면 다음 하나를) 실행할 수 있습니다.
  • +
  • 마지막의 catch() 블록은 .then() 이 하나라도 실패하면 동작합니다. 이는 동기 방식의 try...catch 블록과 비슷합니다. catch()블럭 안에서는 error 객체를 사용할 수 있으며, 발생한 오류를 알아보는 용도로 사용합니다. try...catch 는 프로미스와 함께 동작하지 않지만, 나중에 배울 async/await에서는 동작한다는 점에 유의하세요.
-
-

Note: You'll learn a lot more about promises later on in the module, so don't worry if you don't understand them fully yet.

+
+

Note: 이 모듈의 뒷부분에 프로미스의 더 많은 부분을 배웁니다. 지금 이해하지 못하셨더라도 걱정하지 마세요.

-

The event queue

+

이벤트 큐

-

promise와 같은 비동기 작업은 event queue에 들어갑니다. 그리고 main thread가 끝난 후 실행되어 후속 JavaScript 코드가 차단되는것을 방지합니다. queued 작업은 가능한 빨리 완료되어 JavaScript 환경으로 결과를 반환해줍니다.

+

프로미스같은 비동기 작업들은 이벤트 큐에 들어갑니다. 이 작업들은 메인 스레드 작업이 끝난 후 실행되어 후속 JavaScript 코드가 차단되는것을 방지합니다. 큐에 들어간 작업은 최대한 빨리 처리되어 JavaScript 환경으로 결과를 반환해줍니다.

-

Promises vs callbacks

+

프로미스 vs 콜백

-

Promises 는 old-style callbacks과 유사한 점이 있습니다. 기본적으로 callback을 함수로 전달하는 것이 아닌 callback함수를 장착하고 있는 returned된 오브젝트 입니다.

+

프로미스는 옛날 방식 콜백과 비슷한 점이 있습니다. 프로미스는 본질적으로 함수에 콜백을 직접 넘기는 대신 반환된 객체에 여러분이 콜백을 직접 연결하는 것에 불과합니다.

-

그러나 Promise는 비동기 작업을 처리함에 있어서 old-style callbacks 보다 더 많은 이점을 가지고 있습니다. :

+

그러나 프로미스는 비동기 작업을 처리하기 위해 만들어졌고, 옛날 방식 콜백보다 장점이 많습니다.

    -
  • 여러 개의 연쇄 비동기 작업을 할 때 앞서 본 예제처럼 .then() 을 사용하여 결과값을 다음 작업으로 넘길 수 있습니다. callbacks으로 이를 사용하려면 더 어렵습니다. 또한 "파멸의 피라미드" (callback hell로 잘 알려진)을 종종 마주칠 수 있습니다.
  • -
  • Promise callbacks은 event queue에 배치되는 엄격한 순서로 호출됩니다.
  • -
  • 에러 처리가 더 간결해집니다. — 모든 에러를 코드 블럭의 마지막 부분에 있는 단 한개의 .catch() 블럭으로 처리할 수 있습니다. 이 방법은 피라미드의 각 단계에서 에러를 핸들링하는 것 보다 더 간단합니다..
  • -
  • 구식 callback은 써드파티 라이브러리에 전달될 때 함수가 어떻게 실행되어야 하는 방법을 상실하는 반면 Promise는 그렇지 않습니다.
  • +
  • 여러 비동기 작업을 체이닝할 때 앞서 본 예제처럼 .then() 을 사용하여 결과값을 다음 작업으로 넘길 수 있습니다. 콜백으로 같은 작업을 하고자 하면 더 어려워지는데요, "파멸의 피라미드" (콜백 지옥로 잘 알려져 있습니다)로 귀결되는 모습을 자주 볼 수 있습니다.
  • +
  • 프로미스 콜백은 항상 엄격하게 이벤트 큐에 배치된 순서대로 호출됩니다.
  • +
  • 에러 처리가 훨씬 수월합니다. 모든 에러를 코드 블럭의 마지막 부분에 있는 단 하나의 .catch() 블록으로 처리할 수 있습니다. 이 방법은 "피라미드"의 각 단계에서 에러를 핸들링하는 것 보다 훨씬 간단합니다.
  • +
  • 프로미스는 제어의 반전(inversion of control)이 일어나지 않습니다. 옛날 방식 콜백은 서드 파티 라이브러리에 전달될 때 함수가 실행되는 방법에 대한 완전한 제어를 잃어버리는 반면에, 프로미스는 그렇지 않습니다.
-

The nature of asynchronous code

+

비동기 코드의 특성

-

코드 실행 순서를 완전히 알지 못할 때 발생하는 현상과 비동기 코드를 동기 코드처럼 취급하려고 하는 문제를 살펴보면서 비동기 코드의 특성을 더 살펴봅시다 아래 예제는 이전에 봤던 예제와 유사합니다. (see it live, and the source). 한가지 다른 점은 코드가 실행순서를 보여주기 위해 {{domxref("console.log()")}} 를 추가했습니다.

+

비동기 코드의 특성을 설명하는 예시를 살펴봅시다. 이 예제는 코드의 실행 순서를 완벽하게 파악하지 못하여 비동기 방식 코드를 동기 방식 코드처럼 다루려고 했을 때 나타나는 문제를 담고 있습니다. 아래 예제는 이전에 봤던 예제와 유사합니다. (동작하는 예제는 여기에서, 소스는 여기에서 확인하세요). 한가지 다른 점은 코드가 실행순서를 보여주기 위해 {{domxref("console.log()")}} 를 추가했습니다.

-
console.log ('Starting');
+
console.log ('Starting');
 let image;
 
 fetch('coffee.jpg').then((response) => {
@@ -206,11 +227,11 @@ 

The nature of asynchronous code

console.log ('All done!');
-

브라우저는 코드를 실행하기 시작할 것이고, 맨 처음 나타난 (Starting) 글씨가 써진 console.log() 후 image 변수를 만들 것 입니다.

+

브라우저가 코드를 실행하기 시작하면, Starting이 적힌 console.log() 문을 만나 실행하고, image 변수를 만들 것 입니다.

-

다음으로 fetch() block 으로 이동하여 코드를 실행하려고 할 것 입니다. fetch() 덕분에 blocking없이 비동기 적으로 코드가 실행되겠죠. 블럭 내에서 promise와 관련된 작업이 끝나면 다음 작업으로 이어질 것 입니다. 그리고 마지막으로 (All done!) 가 적혀있는 console.log() 에서 메시지를 출력할 것 입니다.

+

그 뒤에 다음 줄로 이동하여 fetch() 블록을 실행하려고 하지만, fetch() 는 블로킹 없이 비동기적으로 실행되기 때문에 프로미스와 관련된 작업들을 지나쳐 아래쪽의 코드를 이어서 실행할 겁니다. 그래서 마지막의 console.log()(All done!)를 만나 메시지를 콘솔에 출력합니다.

-

fetch() 블럭 작업이 작업을 완전히 끝내고 마지막 .then() 블럭에 도달해야 console.log() 의 (It worked :)) 메시지가 나타납니다. 그래서 메시지의 순서는 코드에 적혀있는 대로 차례대로 나타나는게 아니라 순서가 약간 바뀌어서 나타납니다 :

+

fetch() 블록 작업이 완전히 끝나고 .then() 블록에 결과를 전달해야만 console.log() 의 메시지(It worked :))가 나타납니다. 결국 메시지의 순서는 여러분의 처음 생각과는 다르게 순서가 바뀌어서 나타납니다.

  • Starting
  • @@ -218,64 +239,64 @@

    The nature of asynchronous code

  • It worked :)
-

이 예가 어렵다면 아래의 다른 예를 살펴보세요 :

+

이 예시가 헷갈린다면 다음의 간략한 예제를 살펴보세요.

-
console.log("registering click handler");
+
console.log("클릭 처리기를 등록합니다");
 
 button.addEventListener('click', () => {
-  console.log("get click");
+  console.log("클릭함");
 });
 
-console.log("all done");
+console.log("끝");
-

이전 예제와 매우 유사한 예제 입니다. — 첫 번째와 세 번째console.log() 메시지는 콘솔창에 바로 출력됩니다. 그러나 두 번째 메시지는 누군가가 버튼을 클릭하기 전엔 콘솔에 표시되지 않죠. 위의 예제의 차이라면 두 번쩨 메시지가 어떻게 잠시 blocking이 되는지 입니다. 첫 예제는 Promise 체이닝 때문에 발생하지만 두 번째 메시지는 클릭 이벤트를 대기하느라고 발생합니다.

+

이전 예제와 매우 비슷한 동작을 합니다. 첫 번째와 세 번째console.log() 메시지는 콘솔창에 바로 출력되지만, 두 번째 메시지는 누군가가 버튼을 클릭하기 전엔 콘솔에 표시되지 않습니다. 이전 예제와의 차이는 두 번쩨 메시지가 블로킹되는 이유인데, 첫 예제는 리소스를 가져오고 화면에 표시하는 프로미스 체이닝 작업을 기다리느라 발생하지만, 이번 예제는 클릭 이벤트를 기다리느라 발생합니다.

-

less trivial 코드 예제에서 이러한 설정을 문제를 유발할 수 있습니다. — 비동기 코드 블럭에서 반환된 결과를 동기화 코드 블럭에 사용할 수 없습니다. 위의 에시에서 image 변수가 그 예시 입니다. 브라우저가 동기화 코드 블럭을 처리하기 전에 비동기 코드 블럭 작업이 완료됨을 보장할 수 없습니다.

+

다시 처음 'coffee.jpg'를 불러오는 코드 예제를 기준으로 설명드리면, 이런 방식(비동기 방식 코드가 끝날 것이라 가정하고 동기 코드를 작성하는 방식)의 코드는 문제가 될 수 있습니다. 비동기 방식 코드 블록에서 반환된 결과를 동기 방식 코드 블록에서 사용할 수 없기 때문입니다. 브라우저는 동기 방식 코드 블록을 처리하기 전에 비동기 코드 블록 작업이 끝날 것이라 보장하지 않습니다.

-

어떤 의미인지 확인을 하려면 our example을 컴퓨터에 복사한 후 마지막 console.log() 를 아래처럼 고쳐보세요:

+

어떤 의미인지 확인하려면 이 예제를 컴퓨터에 복사한 후 마지막 console.log() 를 아래처럼 고쳐보세요.

-
console.log ('All done! ' + image.src + 'displayed.');
+
console.log ('All done! ' + image.src + 'displayed.');
-

고치고 나면 콘솔창에서 아래와 같은 에러가 뜨는것을 확인할 수 있습니다. :

+

고치고 나면 콘솔창에서 아래와 같은 에러가 뜨는것을 확인할 수 있습니다.

TypeError: image is undefined; can't access its "src" property
-

브라우저가 마지막 console.log() 를 처리할 때, fetch() 블럭이 완료되지 않아 image 변수에 결과가 반환되지 않았기 때문입니다.

+

이는 브라우저가 마지막 console.log() 문을 실행하려고 할 때, fetch() 블록의 작업이 끝나지 않아 image 변수에 값이 할당되지 않았기 때문입니다.

-
-

Note: For security reasons, you can't fetch() files from your local filesystem (or run other such operations locally); to run the above example locally you'll have to run the example through a local webserver.

+
+

Note: 보안상의 이유로, fetch()로 로컬 파일시스템의 파일을 불러오는 것(또는 로컬에서 다른 작업을 실행하는 것)은 불가능합니다. 위 예시를 로컬에서 실행하려면 로컬 웹서버를 통해 실행해야 합니다.

-

Active learning: make it all async!

+

Active learning: 모두 비동기로 만들자!

-

위의 fetch() 예시에서 마지막console.log()도 순서대로 나타나도록 고칠 수 있습니다. 마지막 console.log() 도 비동기로 작동시키면 됩니다. 마지막 .then() 블럭의 마지막에 다시 작성하거나, 새로운 블럭을 만들면 콘솔에 순서대로 나타날 것 입니다. 지금 바로 고쳐보세요!

+

위의 문제 있는 fetch() 예시에서 모든 console.log()가 순서대로 나타나도록 고칠 수 있습니다. 세 번째 console.log() 도 비동기로 작동시키면 됩니다. 두 번째 .then() 블록의 뒤에 새로운 .then() 블록을 만들어 집어넣거나, 두 번째 .then() 블록 안에 집어넣으면 콘솔에 순서대로 나타날 것 입니다. 지금 바로 고쳐보세요!

-
-

Note: If you get stuck, you can find an answer here (see it running live also). You can also find a lot more information on promises in our Graceful asynchronous programming with Promises guide, later on in the module.

+
+

Note: 막혔다면, 여기에서 정답을 확인할 수 있습니다 (동작하는 예시는 여기에서 확인하세요). 프로미스에 대한 더 자세한 정보는 이 모듈 뒷편의 프로미스와 함께하는 우아한 비동기 프로그래밍 가이드에서 확인할 수 있습니다.

-

Conclusion

+

결론

-

In its most basic form, JavaScript is a synchronous, blocking, single-threaded language, in which only one operation can be in progress at a time. But web browsers define functions and APIs that allow us to register functions that should not be executed synchronously, and should instead be invoked asynchronously when some kind of event occurs (the passage of time, the user's interaction with the mouse, or the arrival of data over the network, for example). This means that you can let your code do several things at the same time without stopping or blocking your main thread.

+

가장 기본적인 형태의 JavaScript는 한 번에 한 가지 작업만 진행할 수 있는 동기식, 블로킹, 싱글 스레드 언어입니다. 하지만 웹 브라우저는 동기적으로 실행해서는 안되는 함수를 위해, 어떤 이벤트(시간의 흐름, 사용자가 마우스로 상호작용, 네트워크에서 데이터가 도착함 등)가 일어났을 때 비동기적으로 호출할 수 있도록 함수와 API를 정의하고 있습니다. 이는 메인 스레드를 멈추거나 블로킹하지 않고도 한 번에 여러 코드를 실행할 수 있다는 것을 의미합니다.

-

Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.

+

코드를 동기적으로 실행할지 비동기적으로 실행할지는 하려는 작업이 무엇인지에 달려있습니다.

-

There are times when we want things to load and happen right away. For example when applying some user-defined styles to a webpage you'll want the styles to be applied as soon as possible.

+

불러와 적용하는 것이 바로 일어나기를 바랄 때도 있을겁니다. 예를 들어 웹 페이지에 사용자 정의 스타일을 적용할 때는 스타일이 가능한 한 빨리 적용되기를 바랄겁니다.

-

If we're running an operation that takes time however, like querying a database and using the results to populate templates, it is better to push this off the main thread and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.

+

그러나 데이터베이스를 질의한 결과를 템플릿을 만드는 데 사용한다던가 하는 등의 시간이 걸리는 작업을 할 때는 메인 스레드에서 작업하기 보다는 비동기적으로 작업하는 게 좋을 것 입니다. 시간이 지날수록 동기 방식보다 비동기 방식을 선택하는게 나은 경우를 고르는 안목이 생기게 될 것 입니다.

{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}

-

In this module

+

이 모듈의 내용