티스토리 뷰

ArrayBuffer

자바스크립트의 어레이 버퍼는 다른 언어에서의 '바이트 어레이'와 같은 개념이다. 바이너리 데이터를 저장하는, 바이트들로 구성된 배열이다. 어레이 버퍼는 직접적으로 조작할 수는 없지만 typed array object나 DataView 객체를 만들어서 버퍼 컨텐츠를 저장할 수 있다.

생성자 안에 길이를 인자로 주면 그 길이 만큼의 어레이 버퍼가 생성된다. 아니면 이미 존재하는 데이터로부터 어레이 버퍼를 생성할 수도 있다. 예를 들어 Base64 스트링으로부터 생성할 수 있다. (Base64란 이진 데이터를 텍스트(아스키 스트링)로 인코딩하는 방법을 말한다.)

아까 어레이 버퍼는 직접 조작할 수 없다고 했으므로 typed array를 생성해서 이를 다뤄볼 수 있는데, typed array라는 전역 프로퍼티나 생성자가 있는 것이 아니고 여러 가지 구현체들이 있다. 예를 들어 Uint8Array는 typed array인데 8비트의 unsigned integar(0 ~ 255)를 저장할 수 있는 어레이 같은 객체다.

protobufjs 에서 사용하기

protobufjs에서는 메세지를 js 객체로 인코딩할 때 wire format이 Uint8Array이다.

Message.encode -> 메세지를 자바스크립트 Uint8Array로 인코딩

Message.decode -> 자바스크립트 Uint8Array를 메세지로 디코드

프로토버프를 사용하는데 로컬스토리지에 데이터를 저장하고 싶은 상황이 있었다. 이 때 로컬스토리지에는 문자열밖에 저장할 수 없으므로 데이터를 문자열화했어야 했는데, 이때 고려한 것이 JSON으로 serialize/deserialize하는 것이었다.

그런데 문제는 커스텀 클래스 타입들을 JSON.parse가 제대로 복원하지 못할 수도 있다는 점이었다.

예를 들어 EnumType.A 같은 경우 JSON.parse를 하면 A가 실제로는 number 1을 가리켜도 그냥 string "A"로 디시리얼라이즈 해버린다.

이 문제를 해결하기 위해 받는 쪽에서, JSON.parse로 파싱된 자바스크립트 객체를 Message.fromObject 메서드에 넣어서 메세지 인스턴스로 복원하는 것도 가능했지만, 모든 곳에서 fromObject로 감싸는 것은 당연히 비효율적이었고, 로컬스토리지를 사용하는 쪽에서만 이걸로 감싸기에는 유지 보수할 때 놓칠 가능성이 있었다.

그래서 프로토버프를 바로 JSON으로 바꾸지 않고, 이를 Uint8Array로 인코딩했다가 자바스크립트 어레이로 바꾸어서, 이것을 다시 JSON으로 바꾸는 방식을 취해보았다.(인코딩 Message -> Uint8Array -> Array -> JSON, 디코딩 JSON -> Uint8Array -> Message)

const protoToString = (protoMessage, data) => {
  const arrayBufferLike = protoMessage.encode(data).finish;
    return JSON.stringify(Array.from(arrayBufferLike));
} 

const protoFromString = (protoMessage, string) => {
  const arrayBufferLike = new Uint8Array(JSON.parse(string));
  // 여기서 Uint8Array를 2번 써야 되는건 arrayBufferLike instance of Uint8Array가 false라서 
  // 이걸 그대로 디코드 함수에 넣으면 illegal buffer라는 에러가 발생한다
  // 왜 Uint8Array의 인스턴스가 아니라고 하는지는 좀 더 알아봐야 한다... 
  return protoMessage.decode(new Uint8Array(arrayBufferLike));
}

JSON으로 바로 stringify, parse할 때에는 enum 타입 같은 것들이 제대로 복원이 안되었는데, 이 방법을 쓰니 제대로 복원이 되었다! 하지만 이렇게 쓰려면 코드가 상당히 길어진다는 단점이 있다. 예를 들어 로컬 스토리지에 저장하고 싶은 데이터 구조를 별도로 proto 파일에 정의해야 하기 때문이다.

Ref

https://www.npmjs.com/package/protobufjs

 

protobufjs

Protocol Buffers for JavaScript (& TypeScript).

www.npmjs.com

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer

 

ArrayBuffer - JavaScript | MDN

ArrayBuffer The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer. It is an array of bytes, often referred to in other languages as a "byte array".You cannot directly manipulate the contents of an ArrayBuffer; instead,

developer.mozilla.org

https://github.com/protobufjs/protobuf.js/issues/963

 

Error: illegal buffer with Uint8Array · Issue #963 · protobufjs/protobuf.js

First, thanks for protobuf.js protobuf.js version: 6.8.3 There is an illegal buffer error when I decode the message which is got from MQService. The code as flowing : onCtlMessageArrived : function...

github.com

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함