[NodeJs] 파일 타입 정리

지송현·2023년 1월 8일
0

JS

목록 보기
8/9
post-thumbnail

이전 글에서 음성파일을 다루기 위해 여러 파일의 종류에 대해서 알아야 할 필요성을 느꼈다. 이번 글에서 각 파일의 특징을 알아보자.

자바스크립트는 바이너리 데이터를 다루기 위한 방법으로 Buffer와 FileAPI를 제공한다.

  1. Buffer: 개발자가 메모리 관점에서 바이너리 데이터를 다룰 수 있다.

  2. File API: 파일(png, mp3등)이나 입출력장치(마이크, 카메라, 화면 등)의 바이너리 데이터를 다룰 수 있다.

1. Buffer

먼저 공식 문서의 정의는 아래와 같다.

바이너리 데이터들의 스트림을 읽거나, 조작하는 매커니즘.
이 Buffer클래스는 Node.js의 일부로 도입되어 TCP 스트림이나 파일시스템같은 작업에서의 octet 스트림과의 상호작용을 가능하기 위해 만들어졌습니다.

  • octet Stream은 일반적으로 8bit 형식으로 된 데이터를 의미합니다.

쉽게 말하면 "바이너리 데이터들의 스트림을 조작하기 위한 메커니즘" 정도인 것 같다.
먼저 살펴봐야 할 것들이 생겼다. binary data, stream를 알아야 buffer를 이해할 수 있을 것 같다.


Binary Data

binary data는 말 그대로 데이터를 이진수로 표현한 것이다. 알다시피 컴퓨터는 모든 데이터를 0과 1로 변환해 저장하고 표현한다. 예를 들어 숫자 12는 이진수인 1100으로 변환된다. 그러나 문자열은 어떻게 이진수로 변환할 수 있을까?

Character Set(문자 집합)

문자 집합은 각각의 문자에 대응하는 숫자를 정해놓은 규칙이다. 예를 들어 알파벳 'L'은 76이다. 문자 집합에도 여러 종류가 있지만 대표적으로 유니코드, 아스키코드 등이 있다.

Character Encoding(문자 인코딩)

문자를 숫자로 나타낼 때 문자 집합 규칙이 있는 것처럼 숫자를 바이너리 데이터를 바꿀 때도 규칙이 있다. 문자 인코딩은 이 규칙으로 숫자를 몇 bit로 나타낼 것인가에 대한 규칙이다. 문자 인코딩 중 하나가 utf-8이다. utf-8은 문자가 바이트 단위, 즉 8비트로 이루어진다.

예를 들어 십진수 12를 이진수로 나타내면 1100이지만 utf-8 명세에 따르면 8개의 비트로 구성되어야 한다. 따라서 더 많은 비트를 추가해야 한다. 1100 -> 00001100

이처럼 문자열 뿐만 아니라 이미지나 영상, 음성 등의 경우도 바이너리 데이터로 저장하는 방식이 정해져 있다.


Stream

NodeJs에서 스트림은 간단하게 한 지점에서 다른 지점으로 이동하는 일련의 데이터를 의미한다. 공식 문서에는 "스트리밍 데이터로 작업하기 위한 추상적인 인터페이스"라고 나와 있다.

데이터를 전송할 때 모든 데이터를 한 번에 보낼 수 없으므로(특히 용량이 큰 파일의 경우) 청크단위로 나뉘어 전송하게 된다. 그 청크들의 흐름이 stream이라고 이해했다.

stream에도 여러 종류가 있고 활용할 수 있는 방법 또한 다양하지만 일단 넘어가자.


Buffer

Binary data, Stream에 대해서 대략 알았으니 다시 Buffer에 대해서 알아보자.

stream이 데이터의 흐름을 의미한다는 것을 알았다. 그렇다면 그 데이터들은 정확히 어떻게 이동하는 것일까?

데이터의 이동이 일어날 때 특정 시간동안 한 번에 받을 수 있는 데이터의 최소량과 최대량이 정해져 있다. 만약 데이터를 처리하는 시간보다 데이터가 도착하는 것이 빠른 경우, 초과된 데이터는 어디선가 처리되기를 기다려야 한다.

반대로 한 작업이 데이터를 처리하는 시간이 도착하는 시간보다 더 빠르다면 먼저 도착한 데이터는 처리되기 전에 다음 데이터가 도착할 때까지 기다려야 한다.

여기서 그 기다리는 영역이 buffer이다. 컴퓨터의 메모리에 streaming 중 데이터가 쌓이고, 필요한 데이터가 쌓이면 한 번에 내보내진다.

이 과정을 버스 정류장에 빗대 설명해보자. 정류장에 어느 정도의 승객이 모여야 출발하는 버스가 있다고 가정하자. 승객이 정류자에 오는 시간도 제각각일 것이다. 승객 입장에서, 현재 정류장에 버스가 있어도 다른 승객이 올 때까지 기다려야 하고, 버스가 이미 떠났다면 다음 버스가 올 때까지 기다려야 한다. 즉 어느 경우에도 승객이 기다리는 상황이 있고 그 장소는 버스 정류장이다. 이 버스 정류장이 buffer이다.

예시로 동영상 스트리밍을 할 때, buffering이라고 뜨며 대기하는 화면이 나오는 경우가 승객이 충분히 오지 않아서 버스가 출발하지 않는 상황인 것이다.


nodejs에서 위에서 설명한 buffer에는 3가지 종류가 있다.

  • array buffer : 배열 용도
  • audio buffer : 오디오 용도
  • source buffer : 미디어 용도

ArrayBuffer

array buffer는 지정한 메모리 크기만큼의 바이너리 데이터를 저장하는 객체이다.
단 arraybuffer는 메모리를 확보하고 바이너리 데이터를 0으로 할당하는 역할만을 하며, 실제 데이터 접근은 arraybuffer view를 활용해야 한다.

  • ArrayBuffer : 메모리 확보 및 데이터 생성
  • ArrayBufferView : 데이터 접근(읽기, 수정)
    - TypedArray : Unit8Array, Unit16Array, Float32Array...
    - DataView

ArrayBufferView는 실제 객체가 아니라 TypedArray와 DataView를 통칭하는 말이다.
TypedArray 역시 실제 객체가 아니라 Unit8Array, Unit16Array 등을 통칭하는 말이다.

예를 들면 다음과 같이 쓸 수 있는 것이다.

const arrayBuffer = new ArrayBuffer(4); // 4byte의 arraybuffer생성

const uint8Array = new Uint8Array(arrayBuffer); // Unit8Array 생성

uint8Array[0] = 10;
console.log(uint8Array) // 이런식으로 조작과 조회가 가능하다.

TypedArray의 종류는 다음 링크를 참고하자.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays

  • DataView
    위의 TypedArray는 모두 타입이 정해져 있었다. 이것보다 유연하게 arraybuffer에 접근할 수 있는 view 객체가 dataview이다. 예를 들어 메소드를 이용해 arraybuffer에 접근하는데, .unit8(i) 또는 .unit16(i)와 같이 그 유형으로 값을 가져올 수 있다. 형식은 해당 메소드를 호출하는 시점에 정해지기 때문에 미리 형식이 결정되는 typedarray와 구분된다.

AudioBuffer, MediaBuffer

arraybuffer를 web api를 사용해 위 항목들로 변환할 수 있다. 각각 오디오와 미디어 파일의 raw데이터로 audioContext.decodeAudioData() 등을 이용해서 만든다.


2. File API

FILE API란 단순 텍스트 데이터 뿐만 아니라 이미지, 오디오, 비디오 등의 대용량 바이너리 데이터를 다루기 위한 API이다.

Blob

Blob은 Binary Large Object의 약자로 주로 파일과 같은 객체를 바이너리 형태로 저장한 것을 의미한다. 이렇게 바이너리 형태로 저장하는 이유는 영상, 이미지 등의 파일은 용량이 큰 경우가 많고 이것을 효과적으로 db에 저장하기 위해서는 바이너리 데이터로 바꾸는 것이 필요하기 때문이다.

실제로 디바이스의 마이크, 카메라 등으로 입력 받은 오디오나 비디오 데이터는 blob으로 들어온다. 따라서 이를 클라이언트 단에서 적절히 가공하는 것이 필요하다.

  • blob 생성 방식
  1. 생성자 방식
  2. 기존 blob 객체에서 일부 자름
  3. 마이크, 카메라, 화면 등에서 취득
  • blob 메소드
  1. blob.prototype.arrayBuffer() : arraybuffer로 반환
  2. blob.prototype.text() : utf-8 text형태의 string으로 반환
  3. blob.prototype.stream() : ReadableStream으로 반환
  4. blob.prototype.slice(start, end, contentType) : byte 단위로 쪼갠 blob 객체 반환(위의 생성 방식 2번째)

ObjectURL(객체 URL)
.
ObjectURL은 blob 객체를 가리키는 url이다. 브라우저에서 해당 url로 이동하면 blob 파일을 확인할 수 있다. 따라서 <audio>, <video>, <img>태그 등의 src 값으로 사용할 수 있다. 그러나 ObjectURL은 생성된 페이지에서만 유효하며, 다른 페이지로 넘어가면 사용할 수 없다.
.

생성 방법
window.URL.createObjectURL(Blob)
해제 방법
window.URL.revokeObjectURL(Blob)


File

File 객체란 js에서 파일을 다루기 위한 객체로 Blob을 상속 받는다.
이를 위해 파일을 다루는데 필요한 파일명, 최종수정일 프로퍼티가 추가되어 있다.
따라서 File은 Blob으로 할 수 있는 모든 것을 할 수 있으며, Blob을 요구하는 모든 곳(함수의 인자 등)에 사용될 수 있다.

  • Blob은 주로 파일 형태가 아닌 바이너리 데이터(마이크 목소리, canvas 그림 등)를 다루는 객체이고,
    File은 주로 파일 형태의 바이너리 데이터(mp3, png 등)를 다루는 객체이다.

생성 방법

  1. 생성자
new File(source배열, name, {type: "text/plain"});
  • source 배열 : 파일에 저장할 데이터. ArrayBuffer, ArrayBufferView, Blob, DOMString을 요소로 하는 배열
  • name : 파일명이나 파일의 경로
  • option :
    - type : MIME 유형을 나타내는 DOMString. 디폴트는 ""
    • lastModified : 최종 수정일. 디폴트는 Date.now()

  1. input 엘리먼트 등 사용

브라우저 환경에서 <input type="file"> 엘리먼트 등으로 입력된 파일(mp3, png 등)은 File 객체 형태로 얻을 수 있다.


FileReader

File이나 Blob 객체가 저장하고 있는 바이너리 데이터를 비동기로 읽어 주는 객체이다.

  • FileReader.prototype.readAsArrayBuffer(File or Blob)
  • FileReader.prototype.readAsBinaryString(File or Blob)
  • FileReader.prototype.readAsDataURL(File or Blob)
  • FileReader.prototype.readAsText(File or Blob)

-> File이나 Blob의 바이너리 데이터를 읽어서 각각에 맞는 형태로 반환

profile
백엔드 개발자

0개의 댓글