You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/11-async/01-callbacks/article.md
+41-41Lines changed: 41 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
2
2
3
-
# 콜백 입문
3
+
# 콜백
4
4
5
5
```warn header="브라우저 메서드를 사용합니다."
6
6
콜백, 프라미스 등을 어떻게 사용하는지 보여드리기 위해 본 챕터에선 브라우저 전용 메서드를 사용할 예정입니다. 스크립트를 불러오고 완성된 문서에 간단한 조작을 하는 예시에서 특히 브라우저 메서드가 사용될 예정입니다.
@@ -10,36 +10,36 @@
10
10
독자를 위해 최대한 브라우저 메서드를 덜 쓰도록 하겠습니다.
11
11
```
12
12
13
-
자바스크립트 내 동작 상당수는 *비동기(asynchronous)*로 처리됩니다. 이는 지금 당장 동작을 시작해도 동작이 끝나는 시점은 나중이라는 것을 의미합니다.
13
+
자바스크립트 호스트 환경이 제공하는 여러 함수를 사용하면 *비동기(asynchronous)*동작을 스케줄링 할 수 있습니다. 원하는 때에 동작이 시작하도록 할 수 있죠.
14
14
15
-
`setTimeout`을 사용해 비동기 동작을 스케줄링하는 것이 대표적인 예시입니다.
15
+
`setTimeout`은 스케줄링에 사용되는 가장 대표적인 함수입니다.
16
16
17
-
비동기 동작에 대한 예시는 다양합니다. 스크립트나 모듈을 로딩(뒤에서 다루게 될 내용)하는 것 또한 비동기 동작입니다.
17
+
실무에서 맞닥뜨리는 비동기 동작은 아주 다양합니다. 스크립트나 모듈을 로딩하는 것 또한 비동기 동작입니다(이 예시는 뒤에서 구체적으로 다룰 예정입니다).
18
18
19
-
`src`에 있는 스크립트를 읽어오는 함수 `loadScript(src)`를 살펴봅시다.
19
+
`src`에 있는 스크립트를 읽어오는 함수 `loadScript(src)`를 예시로 비동기 동작 처리가 어떻게 일어나는지 살펴봅시다.
20
20
21
21
```js
22
22
functionloadScript(src) {
23
-
//creates a <script> tag and append it to the page
24
-
//this causes the script with given src to start loading and run when complete
23
+
// <script> 태그를 만들고 페이지에 태그를 추가합니다.
24
+
//태그가 페이지에 추가되면 src에 있는 스크립트를 로딩하고 실행합니다.
25
25
let script =document.createElement('script');
26
26
script.src= src;
27
27
document.head.append(script);
28
28
}
29
29
```
30
30
31
-
위 함수는`<script src="…">`를 동적으로 만들고 이를 문서에 추가합니다. 브라우저는 자동으로 태그에 있는 스크립트를 읽고 읽기가 끝나면 실행합니다.
31
+
함수 `loadScript(src)`는`<script src="…">`를 동적으로 만들고 이를 문서에 추가합니다. 브라우저는 자동으로 태그에 있는 스크립트를 불러오고, 로딩이 완료되면 스크립트를 실행합니다.
32
32
33
-
함수 사용법은 다음과 같습니다.
33
+
`loadScript(src)` 사용법은 다음과 같습니다.
34
34
35
35
```js
36
36
// 해당 경로에 위치한 스크립트를 불러오고 실행함
37
37
loadScript('/my/script.js');
38
38
```
39
39
40
-
스크립트 읽기가 지금 당장 시작되더라도 실행은 함수가 종료되고 난 후에야 실행되므로 스크립트는 '비동기적으로' 실행되었다고 할 수 있습니다.
40
+
그런데 이 때 스크립트는 '비동기적으로' 실행됩니다. 로딩은 지금 당장 시작되더라도 실행은 함수가 끝난 후에야 되기 때문입니다.
41
41
42
-
`loadScript(…)` 아래에 코드가 있더라도 이 코드들은 스크립트 로딩이 종료되는 걸 기다리지 않습니다.
42
+
따라서 `loadScript(…)` 아래에 있는 코드들은 스크립트 로딩이 종료되는 걸 기다리지 않습니다.
43
43
44
44
```js
45
45
loadScript('/my/script.js');
@@ -50,7 +50,7 @@ loadScript('/my/script.js');
50
50
51
51
스크립트 로딩이 끝나자마자 이 스크립트를 사용해 무언가를 해야만 한다고 가정해 봅시다. 스크립트 안에 다양한 함수가 정의되어 있고, 우리는 이 함수를 실행하길 원하는 상황입니다.
52
52
53
-
그런데 `loadScript(...)`를 호출하자마자 내부 함수를 호출하면, 원하는 대로 작동하지 않습니다.
53
+
그런데 `loadScript(...)`를 호출하자마자 내부 함수를 호출하면 원하는 대로 작동하지 않습니다.
54
54
55
55
```js
56
56
loadScript('/my/script.js'); // script.js엔 "function newFunction() {…}"이 있습니다.
@@ -60,9 +60,9 @@ newFunction(); // 함수가 존재하지 않는다는 에러가 발생합니다!
60
60
*/!*
61
61
```
62
62
63
-
브라우저는 당연히 스크립트를 읽어올 수 있는 시간을 충분히 확보하지 못합니다. 현재로서는 함수 `loadScript`에서 스크립트 로딩이 완료되었는지 알 수 있는 방법이 없습니다. 언젠간 스크립트가 로드되고 실행도 되겠지만, 그게 다입니다. 그런데, 스크립트 안의 함수나 변수를 사용하려면 스크립트 로딩이 끝났는지 여부를 알아야 합니다.
63
+
에러는 브라우저가 스크립트를 읽어올 수 있는 시간을 충분히 확보하지 못했기 때문에 발생합니다. 그런데 현재로서는 함수 `loadScript`에서 스크립트 로딩이 완료되었는지 알 방법이 없네요. 언젠간 스크립트가 로드되고 실행도 되겠지만, 그게 다입니다. 원하는 대로 스크립트 안의 함수나 변수를 사용하려면 스크립트 로딩이 끝났는지 여부를 알 수 있어야 합니다.
64
64
65
-
`loadScript`의 두 번째 인수로 스크립트 로딩이 끝난 후 실행될 함수인 `콜백(callback)` 함수를 추가해 봅시다(콜백은 나중에 호출할 함수를 의미합니다. - 옮긴이).
65
+
`loadScript`의 두 번째 인수로 스크립트 로딩이 끝난 후 실행될 함수인 `콜백(callback)` 함수를 추가해 봅시다(콜백 함수는 나중에 호출할 함수를 의미합니다. - 옮긴이).
66
66
67
67
```js
68
68
functionloadScript(src, *!*callback*/!*) {
@@ -77,7 +77,7 @@ function loadScript(src, *!*callback*/!*) {
77
77
}
78
78
```
79
79
80
-
이제 `loadScript`로 불러온 스크립트에 있는 새로운 함수를 호출하려면, 호출 코드를 콜백 함수 안에 작성해야만 합니다.
80
+
새롭게 불러온 스크립트에 있는 함수를 콜백 함수 안에서 호출하면 원하는 대로 외부 스크립트 안의 함수를 사용할 수 있습니다.
위와 같이 작성하면 됩니다. 모든 새로운 동작이 콜백 안에 위치하게 되었습니다. 수행하려는 동작이 단 몇 개뿐이라면 이렇게 작성해도 괜찮지만, 동작이 많은 경우는 이런 식으로 작성하는 게 좋지 않습니다. 다른 방식으로 코드를 작성하는 방법에 대해선 곧 알아보도록 하겠습니다.
154
+
위와 같이 모든 새로운 동작이 콜백 안에 위치하게 작성하면 됩니다. 그런데 이렇게 콜백 안에 콜백을 넣는 것은 수행하려는 동작이 단 몇 개뿐이라면 괜찮지만, 동작이 많은 경우엔 좋지 않습니다. 다른 방식으로 코드를 작성하는 방법은 곧 알아보도록 하겠습니다.
155
155
156
156
## 에러 핸들링
157
157
158
-
위 예시는 스크립트 로딩이 실패하는 경우 등의 에러를 고려하지 않고 작성되었습니다. 콜백 함수는 에러를 핸들링할 수 있어야 합니다.
158
+
지금까지 살펴본 예시들은 스크립트 로딩이 실패하는 경우 등의 에러를 고려하지 않고 작성되었습니다. 그런데 스크립트 로딩이 실패할 가능성은 언제나 있습니다. 물론 콜백 함수는 이런 에러를 핸들링할 수 있어야 하죠.
159
159
160
-
아래 `loadScript`는 로딩 에러를 추적할 수 있습니다.
160
+
`loadScript`에서 로딩 에러를 추적할 수 있게 기능을 개선해봅시다.
161
161
162
162
```js
163
163
functionloadScript(src, callback) {
@@ -166,16 +166,16 @@ function loadScript(src, callback) {
166
166
167
167
*!*
168
168
script.onload= () =>callback(null, script);
169
-
script.onerror= () =>callback(newError(`${src}를 불러오는 도중에 에러가 발생함`));
169
+
script.onerror= () =>callback(newError(`${src}를 불러오는 도중에 에러가 발생했습니다.`));
비동기로 처리해야 할 동작 각각을 독립적인 함수로 만들어 위와 같은 문제를 완화해 보도록 합시다. 아래와 같이 말이죠.
270
+
각 동작을 독립적인 함수로 만들어 위와 같은 문제를 완화해 보도록 합시다. 아래와 같이 말이죠.
271
271
272
272
```js
273
273
loadScript('1.js', step1);
@@ -299,12 +299,12 @@ function step3(error, script) {
299
299
};
300
300
```
301
301
302
-
새롭게 작성한 코드는 위에서 작성한 콜백 기반 스타일 코드와 동일하게 동작합니다. 다만, 각 동작을 분리해 최상위 레벨의 함수로 만들었기 때문에 깊은 중첩이 없습니다.
302
+
어떤가요? 새롭게 작성한 코드는 각 동작을 분리해 최상위 레벨의 함수로 만들었기 때문에 깊은 중첩이 없습니다. 그리고 콜백 기반 스타일 코드와 동일하게 동작하죠.
303
303
304
-
이렇게 작성해도 문제는 없습니다만, 코드가 찢어진 종잇조각 같아 보이네요. 읽는 것도 어렵습니다. 눈을 이리저리 움직이며 코드를 읽어야 하죠. 코드에 익숙지 않아 눈을 어디로 옮겨야 할지 모르면 더욱더 불편합니다.
304
+
그런데 이렇게 작성하면 동작상의 문제는 없지만, 코드가 찢어진 종잇조각 같아 보인다는 문제가 생깁니다. 읽는 것도 어려워지죠. 눈을 이리저리 움직이며 코드를 읽어야 합니다. 코드에 익숙지 않아 눈을 어디로 옮겨야 할지 모르면 더욱더 불편할 것입니다.
305
305
306
-
`step*`이라고 명명한 함수들은 '멸망의 피라미드'를 피하려는 용도만으로 만들었기 때문에 재사용도 할 수 없습니다. 연쇄 동작이 이뤄지는 코드 밖에선 아무도 이 함수를 재활용하지 않을 겁니다. 네임스페이스가 약간 복잡해졌습니다(namespace cluttering).
306
+
게다가 `step*`이라고 명명한 함수들은 '멸망의 피라미드'를 피하려는 용도만으로 만들었기 때문에 재사용이 불가능합니다. 그 누구도 연쇄 동작이 이뤄지는 코드 밖에선 함수들을 재활용하지 않을 겁니다. 네임스페이스가 약간 복잡해졌네요(namespace cluttering).
307
307
308
-
더 나은 무언가가 필요한 상황입니다.
308
+
지금쯤이면 더 나은 무언가가 필요하다는 생각이 강하게 들 겁니다.
309
309
310
-
운 좋게도, 멸망의 피라미드를 피할 수 있는 방법이 몇 가지 있습니다. 가장 좋은 방법 중 하나는 다음 챕터에서 설명할 '프라미스(promise)'를 사용하는 것입니다.
310
+
운 좋게도, 멸망의 피라미드를 피할 방법이 몇 가지 있습니다. 가장 좋은 방법 중 하나는 다음 챕터에서 설명할 '프라미스(promise)'를 사용하는 것입니다.
0 commit comments