Skip to content

4 Binary - 03 Blob 번역 #1004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 78 additions & 78 deletions 4-binary/03-blob/article.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
# Blob

`ArrayBuffer` and views are a part of ECMA standard, a part of JavaScript.
`ArrayBuffer`와 뷰는 ECMA 표준의 일부이며 자바스크립트의 일부입니다.

In the browser, there are additional higher-level objects, described in [File API](https://www.w3.org/TR/FileAPI/), in particular `Blob`.
브라우저에는 `Blob` 같이 [File API](https://www.w3.org/TR/FileAPI/)에 설명된 상위 수준 객체가 추가로 존재합니다.

`Blob` consists of an optional string `type` (a MIME-type usually), plus `blobParts` -- a sequence of other `Blob` objects, strings and `BufferSource`.
`Blob`은 선택사항인 문자열 `type`(보통 MIME형)과 `blobParts`로 구성됩니다. `blobParts`는 다른 `Blob` 객체, 문자열, `BufferSource`의 나열로 이루어집니다.

![](blob.svg)

The constructor syntax is:
생성자 문법은 다음과 같습니다.

```js
new Blob(blobParts, options);
```

- **`blobParts`** is an array of `Blob`/`BufferSource`/`String` values.
- **`options`** optional object:
- **`type`** -- `Blob` type, usually MIME-type, e.g. `image/png`,
- **`endings`** -- whether to transform end-of-line to make the `Blob` correspond to current OS newlines (`\r\n` or `\n`). By default `"transparent"` (do nothing), but also can be `"native"` (transform).
- **`blobParts`** `Blob`/`BufferSource`/`String` 값의 배열입니다.
- **`options`** 선택사항 객체
- **`type`** -- `Blob`형으로 보통 MIME형, 예) `image/png`,
- **`endings`** -- `Blob` 생성 시 현재 OS 줄 바꿈(`\r\n` or `\n`)에 맞추어 줄의 끝을 변환할지 여부. 기본값은 `"transparent"`(아무것도 하지 않음)이나`"native"`(변환함)도 가능합니다.

For example:
예를 들면,

```js
// create Blob from a string
// Blob을 문자열로부터 생성합니다
let blob = new Blob(["<html>…</html>"], {type: 'text/html'});
// please note: the first argument must be an array [...]
// 주의 : 첫 번째 인수는 배열 [...]이어야 합니다.
```

```js
Expand All @@ -35,34 +35,34 @@ let blob = new Blob([hello, ' ', 'world'], {type: 'text/plain'});
```


We can extract `Blob` slices with:
`Blob`은 다음과 같이 잘라내어 추출할 수 있습니다.

```js
blob.slice([byteStart], [byteEnd], [contentType]);
```

- **`byteStart`** -- the starting byte, by default 0.
- **`byteEnd`** -- the last byte (exclusive, by default till the end).
- **`contentType`** -- the `type` of the new blob, by default the same as the source.
- **`byteStart`** -- 시작 바이트로 기본값은 0.
- **`byteEnd`** -- 끝 바이트(지정한 값 이전 값까지 포함하며(exclusive) 기본값은 끝까지).
- **`contentType`** -- 새 blob의 `type`으로 기본값은 원본과 같음.

The arguments are similar to `array.slice`, negative numbers are allowed too.
인수는 `array.slice`와 비슷하며 음수도 허용됩니다.

```smart header="`Blob` objects are immutable"
We can't change data directly in a `Blob`, but we can slice parts of a `Blob`, create new `Blob` objects from them, mix them into a new `Blob` and so on.
```smart header="`Blob` 객체는 불변입니다"
`Blob` 안에서 직접 데이터를 변경할 수는 없지만 `Blob` 일부를 잘라내어 새 `Blob` 객체를 생성하거나 새 `Blob`으로 합쳐 넣는 작업 등이 가능합니다.

This behavior is similar to JavaScript strings: we can't change a character in a string, but we can make a new corrected string.
이런 동작 방식은 JavaScript 문자열과 비슷합니다. 문자열 안의 문자는 변경할 수 없지만 수정된 문자열을 새로 만들 수 있습니다.
```

## Blob as URL
## Blob을 URL로 사용하기

A Blob can be easily used as an URL for `<a>`, `<img>` or other tags, to show its contents.
Blob을 손쉽게 `<a>`, `<img>` 등 태그의 URL로 사용하여 내용을 보여줄 수 있습니다.

Thanks to `type`, we can also download/upload `Blob` objects, and the `type` naturally becomes `Content-Type` in network requests.
`type` 덕분에 `Blob` 객체를 다운로드/업로드할 수 있으며 `type`은 자연스럽게 네트워크 요청 시 `Content-Type`이 됩니다.

Let's start with a simple example. By clicking on a link you download a dynamically-generated `Blob` with `hello world` contents as a file:
간단한 예제로 시작해 봅시다. 링크를 클릭하면 `Blob`이 동적 생성되며 `hello world` 내용을 가진 파일로 다운로드됩니다.

```html run
<!-- download attribute forces the browser to download instead of navigating -->
<!-- download 속성은 브라우저가 탐색 대신 다운로드하도록 강제합니다 -->
<a download="hello.txt" href='#' id="link">Download</a>

<script>
Expand All @@ -72,9 +72,9 @@ link.href = URL.createObjectURL(blob);
</script>
```

We can also create a link dynamically in JavaScript and simulate a click by `link.click()`, then download starts automatically.
자바스크립트로 링크를 동적 생성하고 `link.click()`으로 클릭처럼 동작하게 하여 다운로드를 자동으로 시작할 수도 있습니다.

Here's the similar code that causes user to download the dynamicallly created `Blob`, without any HTML:
다음은 HTML 없이 동적 생성된 `Blob`을 사용자가 다운로드하는 유사한 코드입니다.

```js run
let link = document.createElement('a');
Expand All @@ -89,51 +89,51 @@ link.click();
URL.revokeObjectURL(link.href);
```

`URL.createObjectURL` takes a `Blob` and creates a unique URL for it, in the form `blob:<origin>/<uuid>`.
`URL.createObjectURL``Blob`으로 `blob:<origin>/<uuid>` 형태의 고유 URL을 만듭니다.

That's what the value of `link.href` looks like:
이 형태를 `link.href` 값으로 사용합니다.

```
blob:https://javascript.info/1e67e00e-860d-40a5-89ae-6ab0cbee6273
```

For each URL generated by `URL.createObjectURL` the browser stores a URL -> `Blob` mapping internally. So such URLs are short, but allow to access the `Blob`.
`URL.createObjectURL`로 만든 URL마다 브라우저는 URL -> `Blob` 매핑을 내부적으로 저장하므로 짧은 URL로 `Blob`에 접근할 수 있게 됩니다.

A generated URL (and hence the link with it) is only valid within the current document, while it's open. And it allows to reference the `Blob` in `<img>`, `<a>`, basically any other object that expects an url.
생성된 URL(링크 포함)은 현재 열려있는 document 안에서만 유효하며 `<img>`, `<a>` 등 기본적으로 URL이 들어가는 모든 객체에서 `Blob`을 참조할 수 있습니다.

There's a side-effect though. While there's a mapping for a `Blob`, the `Blob` itself resides in the memory. The browser can't free it.
그러나 부작용이 있습니다. `Blob`으로 매핑이 있기 때문에 `Blob` 자체는 메모리에 존재합니다. 브라우저는 메모리를 해제하지 못합니다.

The mapping is automatically cleared on document unload, so `Blob` objects are freed then. But if an app is long-living, then that doesn't happen soon.
매핑은 document가 언로드될 때 자동으로 정리되고 `Blob` 객체도 그때 해제됩니다. 만약 앱이 오랫동안 살아있다면 곧바로 해제되지는 않습니다.

**So if we create a URL, that `Blob` will hang in memory, even if not needed any more.**
**따라서 URL을 생성하면 더는 필요하지 않더라도 `Blob`은 메모리에 계속 있게 됩니다.**

`URL.revokeObjectURL(url)` removes the reference from the internal mapping, thus allowing the `Blob` to be deleted (if there are no other references), and the memory to be freed.
`URL.revokeObjectURL(url)`은 내부 매핑에서 참조를 제거하므로 `Blob`이 삭제되고(다른 참조가 없는 경우) 메모리가 해제됩니다.

In the last example, we intend the `Blob` to be used only once, for instant downloading, so we call `URL.revokeObjectURL(link.href)` immediately.
마지막 예제에서는 즉시 다운로드에 `Blob`을 딱 한 번만 사용하기 위해 `URL.revokeObjectURL(link.href)`을 바로 호출합니다.

In the previous example with the clickable HTML-link, we don't call `URL.revokeObjectURL(link.href)`, because that would make the `Blob` url invalid. After the revocation, as the mapping is removed, the URL doesn't work any more.
클릭 가능한 HTML 링크가 있는 이전 예제에서는 `Blob` URL을 유효하게 두기 위해 `URL.revokeObjectURL(link.href)`을 호출하지 않았습니다. 폐기되어 매핑이 삭제되면 URL은 더이상 동작하지 않습니다.

## Blob to base64
## Blob에서 base64로

An alternative to `URL.createObjectURL` is to convert a `Blob` into a base64-encoded string.
`URL.createObjectURL` 대신 `Blob`을 base64 인코딩 문자열로 변환할 수 있습니다.

That encoding represents binary data as a string of ultra-safe "readable" characters with ASCII-codes from 0 to 64. And what's more important -- we can use this encoding in "data-urls".
이 인코딩은 이진 데이터를 0부터 64까지의 ASCII 코드로 구성된 매우 안전한 "읽을 수 있는" 문자열로 나타냅니다. 그리고 더 중요한 것은 이 인코딩을 "data-urls"에서 사용할 수 있다는 것입니다.

A [data url](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) has the form `data:[<mediatype>][;base64],<data>`. We can use such urls everywhere, on par with "regular" urls.
[data url](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) 형식은 `data:[<mediatype>][;base64],<data>`입니다. 이러한 URL은 '일반' URL과 동등하게 모든 곳에서 사용할 수 있습니다.

For instance, here's a smiley:
다음은 웃는 얼굴 예제입니다.

```html
<img src="data:image/png;base64,R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7">
```

The browser will decode the string and show the image: <img src="data:image/png;base64,R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7">
브라우저는 문자열을 디코딩하고 다음 이미지를 표시합니다. <img src="data:image/png;base64,R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMlWLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7">


To transform a `Blob` into base64, we'll use the built-in `FileReader` object. It can read data from Blobs in multiple formats. In the [next chapter](info:file) we'll cover it more in-depth.
`Blob`을 base64로 변환하기 위해 내장 객체 `FileReader`를 사용합니다. Blob에서 데이터를 여러 형식으로 읽을 수 있습니다. [다음 챕터](info:file)에서 더 자세히 다룹니다.

Here's the demo of downloading a blob, now via base-64:

다음은 이제 base-64를 통해 blob을 다운로드하는 데모입니다.
```js run
let link = document.createElement('a');
link.download = 'hello.txt';
Expand All @@ -142,79 +142,79 @@ let blob = new Blob(['Hello, world!'], {type: 'text/plain'});

*!*
let reader = new FileReader();
reader.readAsDataURL(blob); // converts the blob to base64 and calls onload
reader.readAsDataURL(blob); // blob을 base64로 변환하고 언로드를 호출
*/!*

reader.onload = function() {
link.href = reader.result; // data url
link.href = reader.result; // 데이터 URL
link.click();
};
```

Both ways of making an URL of a `Blob` are usable. But usually `URL.createObjectURL(blob)` is simpler and faster.
`Blob` URL을 만드는 두 가지 방법 모두 사용할 수 있지만 보통 `URL.createObjectURL(blob)`이 더 간단하고 빠릅니다.

```compare title-plus="URL.createObjectURL(blob)" title-minus="Blob to data url"
+ We need to revoke them if care about memory.
+ Direct access to blob, no "encoding/decoding"
- No need to revoke anything.
- Performance and memory losses on big `Blob` objects for encoding.
```compare title-plus="URL.createObjectURL(blob)" title-minus="Blob을 data URL로 사용하기"
+ 메모리를 관리해야 한다면 폐기 필요
+ 'encoding/decoding' 없이 Blob으로 직접 액세스
- 아무것도 폐기할 필요 없음
- 큰 `Blob` 객체를 인코딩하기 위하여 성능 및 메모리 손실
```

## Image to blob
## 이미지를 Blob으로 만들기

We can create a `Blob` of an image, an image part, or even make a page screenshot. That's handy to upload it somewhere.
이미지, 이미지의 일부, 심지어 페이지 스크린샷으로도 `Blob`을 만들 수 있습니다. 어딘가에 업로드할 때 편리합니다.

Image operations are done via `<canvas>` element:
이미지 작업은 `<canvas>` 요소를 통해 수행됩니다.

1. Draw an image (or its part) on canvas using [canvas.drawImage](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage).
2. Call canvas method [.toBlob(callback, format, quality)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) that creates a `Blob` and runs `callback` with it when done.
1. [canvas.drawImage](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage) 를 사용하여 캔버스에 이미지를(또는 그 일부를) 그립니다.
2. `Blob`을 실행하고 완료되면 `callback`을 실행하는 canvas 메소드 [.toBlob(callback, format, quality)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob)를 호출합니다.

In the example below, an image is just copied, but we could cut from it, or transform it on canvas prior to making a blob:
아래 예제는 단순히 이미지 복사만 하지만 Blob을 만들기 전에 Canvas에서 잘라내거나 변형시킬 수도 있습니다.

```js run
// take any image
// 아무 이미지나 가져옵니다
let img = document.querySelector('img');

// make <canvas> of the same size
// 동일 크기의 <canvas>를 만듭니다
let canvas = document.createElement('canvas');
canvas.width = img.clientWidth;
canvas.height = img.clientHeight;

let context = canvas.getContext('2d');

// copy image to it (this method allows to cut image)
// 이미지를 복사합니다(이 메소드로 이미지를 자를 수 있습니다).
context.drawImage(img, 0, 0);
// we can context.rotate(), and do many other things on canvas
// context.rotate() 등 많은 것을 canvas에서 할 수 있습니다

// toBlob is async opereation, callback is called when done
// toBlob은 비동기 작업이며 완료되면 콜백이 호출됩니다
canvas.toBlob(function(blob) {
// blob ready, download it
// Blob이 준비되어 다운로드합니다
let link = document.createElement('a');
link.download = 'example.png';

link.href = URL.createObjectURL(blob);
link.click();

// delete the internal blob reference, to let the browser clear memory from it
// 내부 Blob 참조를 삭제하여 브라우저가 메모리를 지우도록 합니다
URL.revokeObjectURL(link.href);
}, 'image/png');
```

If we prefer `async/await` instead of callbacks:
콜백 대신 `async/await`를 선호한다면,
```js
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
```

For screenshotting a page, we can use a library such as <https://github.com/niklasvh/html2canvas>. What it does is just walks the page and draws it on `<canvas>`. Then we can get a `Blob` of it the same way as above.
페이지 스크린샷을 찍을 때 <https://github.com/niklasvh/html2canvas> 같은 라이브러리를 사용할 수 있으며 페이지를 돌아다니다가 `<canvas>`에 그려줍니다. 그러면 페이지 스크린샷의 `Blob`을 위와 같은 방식으로 얻을 수 있습니다.

## From Blob to ArrayBuffer
## Blob에서 ArrayBuffer로

The `Blob` constructor allows to create a blob from almost anything, including any `BufferSource`.
`Blob` 생성자에서는 `BufferSource`를 포함하여 거의 모든 것으로부터 Blob을 만들 수 있습니다.

But if we need to perform low-level processing, we can get the lowest-level `ArrayBuffer` from it using `FileReader`:
그러나 저수준 처리를 수행해야 하는 경우 `FileReader`를 사용하여 Blob으로부터 가장 저수준 형태인 `ArrayBuffer`을 얻을 수 있습니다.

```js
// get arrayBuffer from blob
// blob에서 arrayBuffer 얻기
let fileReader = new FileReader();

*!*
Expand All @@ -227,15 +227,15 @@ fileReader.onload = function(event) {
```


## Summary
## 요약

While `ArrayBuffer`, `Uint8Array` and other `BufferSource` are "binary data", a [Blob](https://www.w3.org/TR/FileAPI/#dfn-Blob) represents "binary data with type".
`ArrayBuffer`, `Uint8Array`, 그 밖의 다른 `BufferSource`는 그냥 "이진 데이터"이지만 [Blob](https://www.w3.org/TR/FileAPI/#dfn-Blob)은 "타입을 가진 이진 데이터"입니다.

That makes Blobs convenient for upload/download operations, that are so common in the browser.
이런 이유로 Blob은 브라우저에서 매우 일반적인 업로드/다운로드 작업에 편리합니다.

Methods that perform web-requests, such as [XMLHttpRequest](info:xmlhttprequest), [fetch](info:fetch) and so on, can work with `Blob` natively, as well as with other binary types.
웹 요청을 수행하는 [XMLHttpRequest](info:xmlhttprequest), [fetch](info:fetch) 등과 같은 메소드에서는 다른 이진 타입과 마찬가지로 `Blob`도 기본적으로 함께 사용할 수 있습니다.

We can easily convert betweeen `Blob` and low-level binary data types:
`Blob`은 저수준 이진 데이터 타입은 서로 쉽게 변환할 수 있습니다.

- We can make a Blob from a typed array using `new Blob(...)` constructor.
- We can get back `ArrayBuffer` from a Blob using `FileReader`, and then create a view over it for low-level binary processing.
- `new Blob(...)` 생성자를 사용하여 형식화 배열을 Blob으로 만들 수 있습니다.
- `FileReader`를 사용하면 Blob을 도로 `ArrayBuffer`로 얻어 저수준 이진 처리를 위한 뷰를 생성할 수 있습니다.