diff --git a/5-network/01-fetch/article.md b/5-network/01-fetch/article.md index a18c8bf6b4..3f6f3a9d49 100644 --- a/5-network/01-fetch/article.md +++ b/5-network/01-fetch/article.md @@ -27,11 +27,7 @@ let promise = fetch(url, [options]) - **`url`** -- 접근하고자 하는 URL - **`options`** -- 선택 매개변수, method나 header 등을 지정할 수 있음 -<<<<<<< HEAD `options`에 아무것도 넘기지 않으면 요청은 `GET` 메서드로 진행되어 `url`로부터 콘텐츠가 다운로드 됩니다. -======= -Without `options`, this is a simple GET request, downloading the contents of the `url`. ->>>>>>> upstream/master `fetch()`를 호출하면 브라우저는 네트워크 요청을 보내고 프라미스가 반환됩니다. 반환되는 프라미스는 `fetch()`를 호출하는 코드에서 사용됩니다. @@ -65,21 +61,12 @@ if (response.ok) { // HTTP 상태 코드가 200~299일 경우 `response` 에는 프라미스를 기반으로 하는 다양한 메서드가 있습니다. 이 메서드들을 사용하면 다양한 형태의 응답 본문을 처리할 수 있습니다. -<<<<<<< HEAD - **`response.text()`** -- 응답을 읽고 텍스트를 반환합니다, - **`response.json()`** -- 응답을 JSON 형태로 파싱합니다, - **`response.formData()`** -- 응답을 `FormData` 객체 형태로 반환합니다. `FormData`에 대한 자세한 내용은 [다음 챕터](info:formdata)에서 다루겠습니다. - **`response.blob()`** -- 응답을 [Blob](info:blob)(타입이 있는 바이너리 데이터) 형태로 반환합니다. - **`response.arrayBuffer()`** -- 응답을 [ArrayBuffer](info:arraybuffer-binary-arrays)(바이너리 데이터를 로우 레벨 형식으로 표현한 것) 형태로 반환합니다. - 이 외에도 `response.body`가 있는데, [ReadableStream](https://streams.spec.whatwg.org/#rs-class) 객체인 `response.body`를 사용하면 응답 본문을 청크 단위로 읽을 수 있습니다. 자세한 용례는 곧 살펴보겠습니다. -======= -- **`response.text()`** -- read the response and return as text, -- **`response.json()`** -- parse the response as JSON, -- **`response.formData()`** -- return the response as `FormData` object (explained in the [next chapter](info:formdata)), -- **`response.blob()`** -- return the response as [Blob](info:blob) (binary data with type), -- **`response.arrayBuffer()`** -- return the response as [ArrayBuffer](info:arraybuffer-binary-arrays) (low-level representation of binary data), -- additionally, `response.body` is a [ReadableStream](https://streams.spec.whatwg.org/#rs-class) object, it allows you to read the body chunk-by-chunk, we'll see an example later. ->>>>>>> upstream/master 지금까지 배운 내용을 토대로 GitHub에서 마지막 커밋을 JSON 객체 형태로 받아봅시다. @@ -205,21 +192,12 @@ let response = fetch(protectedUrl, { `GET` 이외의 요청을 보내려면 추가 옵션을 사용해야 합니다. -<<<<<<< HEAD - **`method`** -- HTTP 메서드(예: `POST`) - **`body`** -- 요청 본문으로 다음 항목 중 하나이어야 합니다. - 문자열(예: JSON 문자열) - `FormData`객체 -- `form/multipart` 형태로 데이터를 전송하기 위해 쓰입니다. - `Blob`나 `BufferSource` -- 바이너리 데이터 전송을 위해 쓰입니다. - [URLSearchParams](info:url) -- 데이터를 `x-www-form-urlencoded` 형태로 보내기 위해 쓰이는데, 요즘엔 잘 사용하지 않습니다. -======= -- **`method`** -- HTTP-method, e.g. `POST`, -- **`body`** -- the request body, one of: - - a string (e.g. JSON-encoded), - - `FormData` object, to submit the data as `multipart/form-data`, - - `Blob`/`BufferSource` to send binary data, - - [URLSearchParams](info:url), to submit the data in `x-www-form-urlencoded` encoding, rarely used. ->>>>>>> upstream/master 대부분은 JSON을 요청 본문에 실어 보내게 됩니다. @@ -318,7 +296,6 @@ fetch(url, options) .then(result => /* 결과 처리 */) ``` -<<<<<<< HEAD 응답 객체의 프로퍼티는 다음과 같습니다. - `response.status` -- 응답의 HTTP 코드 - `response.ok` -- 응답 상태가 200과 299 사이에 있는 경우 `true` @@ -330,19 +307,6 @@ fetch(url, options) - **`response.formData()`** -- 응답을 `FormData` 객체 형태로 반환(form/multipart 인코딩에 대한 내용은 다음 챕터에서 다룸) - **`response.blob()`** -- 응답을 [Blob](info:blob)(타입이 있는 바이너리 데이터) 형태로 반환 - **`response.arrayBuffer()`** -- 응답을 [ArrayBuffer](info:arraybuffer-binary-arrays)(바이너리 데이터를 로우 레벨로 표현한 것) 형태로 반환 -======= -Response properties: -- `response.status` -- HTTP code of the response, -- `response.ok` -- `true` if the status is 200-299. -- `response.headers` -- Map-like object with HTTP headers. - -Methods to get response body: -- **`response.text()`** -- return the response as text, -- **`response.json()`** -- parse the response as JSON object, -- **`response.formData()`** -- return the response as `FormData` object (`multipart/form-data` encoding, see the next chapter), -- **`response.blob()`** -- return the response as [Blob](info:blob) (binary data with type), -- **`response.arrayBuffer()`** -- return the response as [ArrayBuffer](info:arraybuffer-binary-arrays) (low-level binary data), ->>>>>>> upstream/master 지금까지 배운 `fetch` 옵션은 다음과 같습니다. - `method` -- HTTP 메서드 diff --git a/5-network/02-formdata/article.md b/5-network/02-formdata/article.md index 197b77b8d2..a90d225ae8 100644 --- a/5-network/02-formdata/article.md +++ b/5-network/02-formdata/article.md @@ -47,11 +47,7 @@ HTML에 `form` 요소가 있는 경우, 위와 같은 코드를 작성하면 해 ``` -<<<<<<< HEAD -요청을 받아 처리하는 서버 측 코드는 튜토리얼 범위를 넘어서서 추가하진 않았는데, 서버는 POST 요청을 받아 '저장 성공'이라는 응답을 보내준다고 정도만 알고 계시면 됩니다. -======= -In this example, the server code is not presented, as it's beyond our scope. The server accepts the POST request and replies "User saved". ->>>>>>> upstream/master +이 예시에서 요청을 받아 처리하는 서버 코드는 튜토리얼 범위를 벗어나므로 제시하지 않습니다. 서버는 POST 요청을 받고 "저장 성공"이라고 응답을 보내준다는 정도만 알고 계시면 됩니다. ## FormData 메서드 @@ -172,11 +168,7 @@ formData.append("image", imageBlob, "image.png"); [FormData](https://xhr.spec.whatwg.org/#interface-formdata) 객체는 `fetch` 등의 네트워크 메서드를 통해 HTML 폼을 보내는데 사용됩니다. -<<<<<<< HEAD `FormData` 객체는 HTML 폼(`form`)을 직접 넘겨 `new FormData(form)`으로 만들 수도 있고, HTML 폼 없이 다음과 같은 메서드로 필드를 추가해 만들 수도 있습니다. -======= -We can either create `new FormData(form)` from an HTML form, or create an object without a form at all, and then append fields with methods: ->>>>>>> upstream/master - `formData.append(name, value)` - `formData.append(name, blob, fileName)` diff --git a/5-network/04-fetch-abort/article.md b/5-network/04-fetch-abort/article.md index a138531407..0ed70d88e7 100644 --- a/5-network/04-fetch-abort/article.md +++ b/5-network/04-fetch-abort/article.md @@ -1,87 +1,60 @@ -# Fetch: Abort +# Fetch: 요청 중단하기 -As we know, `fetch` returns a promise. And JavaScript generally has no concept of "aborting" a promise. So how can we cancel an ongoing `fetch`? E.g. if the user actions on our site indicate that the `fetch` isn't needed any more. +`fetch`는 프라미스를 반환합니다. 그런데 자바스크립트에는 일반적으로 프라미스를 '중단'한다는 개념이 없습니다. 그렇다면 진행 중인 `fetch`는 어떻게 취소할 수 있을까요? 예를 들어 사이트에서 사용자 행동을 보고 더 이상 `fetch`가 필요 없다고 판단한 경우처럼 말이죠. -There's a special built-in object for such purposes: `AbortController`. It can be used to abort not only `fetch`, but other asynchronous tasks as well. +이런 목적을 위해 만들어진 특별한 내장 객체가 있습니다. 바로 `AbortController`입니다. `AbortController`를 사용하면 `fetch`뿐만 아니라 다른 비동기 작업도 중단할 수 있습니다. -The usage is very straightforward: +사용법은 아주 간단합니다. -## The AbortController object +## AbortController 객체 -Create a controller: +컨트롤러를 하나 만듭니다. ```js let controller = new AbortController(); ``` -A controller is an extremely simple object. +컨트롤러는 아주 단순한 객체입니다. -- It has a single method `abort()`, -<<<<<<< HEAD -- And a single property `signal` that allows to set event liseners on it. -======= -- And a single property `signal` that allows to set event listeners on it. ->>>>>>> upstream/master +- 메서드는 `abort()` 하나뿐입니다. +- 이벤트 리스너를 설정할 수 있는 프로퍼티도 `signal` 하나뿐입니다. -When `abort()` is called: -- `controller.signal` emits the `"abort"` event. -- `controller.signal.aborted` property becomes `true`. +`abort()`가 호출되면 다음 일이 일어납니다. +- `controller.signal`에서 `"abort"` 이벤트가 발생합니다. +- `controller.signal.aborted` 프로퍼티 값이 `true`가 됩니다. -<<<<<<< HEAD -Generally, we have two parties in the process: -1. The one that performs an cancelable operation, it sets a listener on `controller.signal`. -2. The one one that cancels: it calls `controller.abort()` when needed. -======= -Generally, we have two parties in the process: -1. The one that performs a cancelable operation, it sets a listener on `controller.signal`. -2. The one that cancels: it calls `controller.abort()` when needed. ->>>>>>> upstream/master +보통 이 과정에는 두 주체가 있습니다. +1. 취소 가능한 작업을 수행하는 쪽은 `controller.signal`에 리스너를 설정합니다. +2. 취소하는 쪽은 필요할 때 `controller.abort()`를 호출합니다. -Here's the full example (without `fetch` yet): +전체 예시를 살펴봅시다. 아직 `fetch`는 사용하지 않습니다. ```js run let controller = new AbortController(); let signal = controller.signal; -<<<<<<< HEAD -// The party that performs a cancelable operation -// gets "signal" object -======= -// The party that performs a cancelable operation -// gets the "signal" object ->>>>>>> upstream/master -// and sets the listener to trigger when controller.abort() is called -signal.addEventListener('abort', () => alert("abort!")); +// 취소 가능한 작업을 수행하는 쪽은 +// "signal" 객체를 받고, +// controller.abort()가 호출되었을 때 실행될 리스너를 설정합니다. +signal.addEventListener('abort', () => alert("중단!")); -// The other party, that cancels (at any point later): -controller.abort(); // abort! +// 취소하는 쪽은 나중에 언제든 다음을 호출합니다. +controller.abort(); // 중단! -// The event triggers and signal.aborted becomes true +// 이벤트가 발생하고 signal.aborted가 true가 됩니다. alert(signal.aborted); // true ``` -<<<<<<< HEAD -As we can see, `AbortController` is just a means to pass `abort` events when `abort()` is called on it. +예시에서 볼 수 있듯이 `AbortController`는 `abort()`가 호출되었을 때 `abort` 이벤트를 전달하는 수단입니다. -We could implement same kind of event listening in our code on our own, without `AbortController` object at all. +`AbortController` 객체 없이도 코드에서 이런 이벤트 리스닝 방식을 직접 구현할 수 있습니다. -But what's valuable is that `fetch` knows how to work with `AbortController` object, it's integrated with it. +하지만 중요한 점은 `fetch`가 `AbortController` 객체와 함께 동작하는 방법을 알고 있다는 것입니다. `fetch`와 `AbortController`는 통합되어 있습니다. -## Using with fetch +## fetch와 함께 사용하기 -To become able to cancel `fetch`, pass the `signal` property of an `AbortController` as a `fetch` option: -======= -As we can see, `AbortController` is just a mean to pass `abort` events when `abort()` is called on it. - -We could implement the same kind of event listening in our code on our own, without the `AbortController` object. - -But what's valuable is that `fetch` knows how to work with the `AbortController` object. It's integrated in it. - -## Using with fetch - -To be able to cancel `fetch`, pass the `signal` property of an `AbortController` as a `fetch` option: ->>>>>>> upstream/master +`fetch`를 취소할 수 있게 하려면 `AbortController`의 `signal` 프로퍼티를 `fetch` 옵션으로 넘기면 됩니다. ```js let controller = new AbortController(); @@ -90,26 +63,22 @@ fetch(url, { }); ``` -The `fetch` method knows how to work with `AbortController`. It will listen to `abort` events on `signal`. +`fetch` 메서드는 `AbortController`와 함께 동작하는 방법을 알고 있습니다. `fetch`는 `signal`의 `abort` 이벤트를 감지합니다. -<<<<<<< HEAD -Now, to to abort, call `controller.abort()`: -======= -Now, to abort, call `controller.abort()`: ->>>>>>> upstream/master +이제 중단하려면 `controller.abort()`를 호출하면 됩니다. ```js controller.abort(); ``` -We're done: `fetch` gets the event from `signal` and aborts the request. +이게 전부입니다. `fetch`가 `signal`로부터 이벤트를 받아 요청을 중단합니다. -When a fetch is aborted, its promise rejects with an error `AbortError`, so we should handle it, e.g. in `try..catch`. +`fetch`가 중단되면 해당 프라미스는 `AbortError` 에러와 함께 거부됩니다. 따라서 `try..catch` 등으로 이를 처리해야 합니다. -Here's the full example with `fetch` aborted after 1 second: +다음은 1초 후 `fetch`를 중단하는 전체 예시입니다. ```js run async -// abort in 1 second +// 1초 후 중단 let controller = new AbortController(); setTimeout(() => controller.abort(), 1000); @@ -118,71 +87,62 @@ try { signal: controller.signal }); } catch(err) { - if (err.name == 'AbortError') { // handle abort() - alert("Aborted!"); + if (err.name == 'AbortError') { // abort() 처리 + alert("중단되었습니다!"); } else { throw err; } } ``` -## AbortController is scalable +## AbortController는 확장성이 좋습니다 -<<<<<<< HEAD -`AbortController` is scalable, it allows to cancel multiple fetches at once. -======= -`AbortController` is scalable. It allows to cancel multiple fetches at once. ->>>>>>> upstream/master +`AbortController`는 확장성이 좋습니다. 여러 `fetch`를 한꺼번에 취소할 수 있습니다. -Here's a sketch of code that fetches many `urls` in parallel, and uses a single controller to abort them all: +다음은 여러 `url`을 병렬로 가져오고, 하나의 컨트롤러로 모든 요청을 중단하는 코드 예시입니다. ```js -let urls = [...]; // a list of urls to fetch in parallel +let urls = [...]; // 병렬로 가져올 url 목록 let controller = new AbortController(); -// an array of fetch promises +// fetch 프라미스 배열 let fetchJobs = urls.map(url => fetch(url, { signal: controller.signal })); let results = await Promise.all(fetchJobs); -// if controller.abort() is called from anywhere, -// it aborts all fetches +// 어디서든 controller.abort()가 호출되면 +// 모든 fetch가 중단됩니다. ``` -If we have our own asynchronous tasks, different from `fetch`, we can use a single `AbortController` to stop those, together with fetches. +`fetch`와는 다른 자체 비동기 작업이 있다면 하나의 `AbortController`를 사용해 해당 작업과 `fetch`를 함께 멈출 수 있습니다. -We just need to listen to its `abort` event in our tasks: +작업 안에서 `abort` 이벤트를 감지하기만 하면 됩니다. ```js let urls = [...]; let controller = new AbortController(); -let ourJob = new Promise((resolve, reject) => { // our task +let ourJob = new Promise((resolve, reject) => { // 자체 작업 ... controller.signal.addEventListener('abort', reject); }); -let fetchJobs = urls.map(url => fetch(url, { // fetches +let fetchJobs = urls.map(url => fetch(url, { // fetch 작업들 signal: controller.signal })); -// Wait for fetches and our task in parallel +// fetch 작업과 자체 작업을 병렬로 기다립니다. let results = await Promise.all([...fetchJobs, ourJob]); -// if controller.abort() is called from anywhere, -// it aborts all fetches and ourJob +// 어디서든 controller.abort()가 호출되면 +// 모든 fetch와 ourJob이 중단됩니다. ``` -## Summary +## 요약 -<<<<<<< HEAD -- `AbortController` is a simple object that generates `abort` event on it's `signal` property when `abort()` method is called (and also sets `signal.aborted` to `true`). -- `fetch` integrates with it: we pass `signal` property as the option, and then `fetch` listens to it, so it becomes possible to abort the `fetch`. -======= -- `AbortController` is a simple object that generates an `abort` event on its `signal` property when the `abort()` method is called (and also sets `signal.aborted` to `true`). -- `fetch` integrates with it: we pass the `signal` property as the option, and then `fetch` listens to it, so it's possible to abort the `fetch`. ->>>>>>> upstream/master -- We can use `AbortController` in our code. The "call `abort()`" -> "listen to `abort` event" interaction is simple and universal. We can use it even without `fetch`. +- `AbortController`는 `abort()` 메서드가 호출되면 `signal` 프로퍼티에서 `abort` 이벤트를 발생시키는 단순한 객체입니다. 이때 `signal.aborted`도 `true`로 설정됩니다. +- `fetch`는 `AbortController`와 통합되어 있습니다. `signal` 프로퍼티를 옵션으로 넘기면 `fetch`가 이를 감지하므로 `fetch`를 중단할 수 있습니다. +- `AbortController`는 일반 코드에서도 사용할 수 있습니다. `abort()` 호출과 `abort` 이벤트 감지로 이어지는 상호작용은 단순하고 범용적입니다. `fetch` 없이도 사용할 수 있습니다. diff --git a/5-network/05-fetch-crossorigin/article.md b/5-network/05-fetch-crossorigin/article.md index 7bddfaa91e..7864fabcf1 100644 --- a/5-network/05-fetch-crossorigin/article.md +++ b/5-network/05-fetch-crossorigin/article.md @@ -28,11 +28,7 @@ CORS는 악의를 가진 해커로부터 인터넷을 보호하기 위해 만들 **과거 수 년 동안, 한 사이트의 스크립트에서 다른 사이트에 있는 콘텐츠에 접근할 수 없다는 제약이 있었습니다.** -<<<<<<< HEAD 이런 간단하지만 강력한 규칙은 인터넷 보안을 위한 근간이었습니다. 보안 규칙 덕분에 해커가 만든 웹 사이트 `hacker.com`에서 `gmail.com`에 있는 메일 박스에 접근할 수 없던 것이죠. 사람들은 이런 제약 덕분에 안전하게 인터넷을 사용할 수 있었습니다. -======= -That simple, yet powerful rule was a foundation of the internet security. E.g. an evil script from website `hacker.com` could not access the user's mailbox at website `gmail.com`. People felt safe. ->>>>>>> upstream/master 그런데 이 당시의 자바스크립트는 네트워크 요청을 보낼 수 있을 만한 메서드를 지원하지 않았습니다. 자바스크립트는 웹 페이지를 꾸미기 위한 토이 랭귀지 수준이었죠. @@ -48,11 +44,7 @@ That simple, yet powerful rule was a foundation of the internet security. E.g. a */!* -<<<<<<< HEAD - -======= - ->>>>>>> upstream/master + *!*