BASIC-COMMON-SENSE

Public Notification
  • account_tree
  • bug_report

엔디언(endian)

숫자를 구성하는 바이트(byte)를 메모리와 같은 1차원의 공간에서 정렬하는 방법을 나타낸다.

비트(bit)와 바이트(byte)

디지털에서 비트는 01을 나타내는 최소 정보 단위를 의미하며 바이트(byte)는 비트(bit)의 그룹이며 상위 단위 개념이다. 즉 8개의 비트(bit)가 모여 1바이트(byte)가 된다. 1바이트에서 표현할 수 있는 정보의 수 다시 말해 경우의 수는 256개이다. 이것을 수학식으로 28승으로 표현한다. 여기서 201이라는 경우의 수를 의미하며 8승은 그 경우의 수가 8개가 있다는 뜻과 같다. 이 8개의 경우의 수가 모여 총 경우의 수가 계산될 수 있다. 컴퓨터는 이렇게 비트를 묶어서 정보를 표현한다. 그 기본 단위가 8비트가 모인 1 바이트인 것이다. 모든 하나의 문자를 비트로 표현할 때 1바이트로 가능하다. 하지만 아시아권 문자와 같이 복잡한 조합으로 구성된 문자는 2바이트까지 사용될 수 있다. 예를 들어서 "ab"라는 연속된 문자를 표현하기 위해서 2바이트만 있으면 된다. 8비트의 경우 총 두 번의 처리가 필요한 셈이다.

한번에 처리 가능한 비트의 수는 처리 속도와 연관되어 있다. 흔히 8차선과 그 이상의 차선을 가진 도로와 비교하는 데 당연히 8차선보다 큰 도로가 자동차의 속도가 더 빠르지 않겠는가? 그래서 16비트 나아가 32비트 방식이 등장한다. 각각 2바이트, 4바이트씩 한번에 처리할 수 있다는 뜻이다. 그렇다면 16비트 이상의 경우 "ab" 문자열을 한번의 처리로 가능하다. 그런데 2바이트를 갖는 "ab" 문자열은 2바이트 이상을 한번에 처리 가능한 16비트와 32비트에서 저장되는 순서를 정해야 하는 데 그 순서를 정하는 기술적 개념이 엔디안(endian)이다.

구조(structure)

엔디안은 16비트 이상의 공간에 이진 데이터를 바이트 단위로 저장하는 순서를 나타낸다. 바이트의 순서를 이야기 하기에 앞서 비트 배열의 개념에 대해 알아보자. 다음은 32비트의 기본 구조를 나타내는 그림이다. 바이트(비트)의 순서를 상위 바이트(비트)와 하위 바이트(비트)로 나누는 배열의 개념이다.

다음 그림은 메모리 주소에 대한 개념을 나타낸다. 메모리의 주소 공간을 로우 메모리(low memory)와 하이 메모리(high memory)로 나눈다. 기본적으로 메모리의 낮은 주소에서 높은 주소의 방향으로 값이 할당된다.

엔디안(endian)

엔디안에는 대표적으로 빅 엔디안(big-endian)과 리틀 엔디안(little-endian)이라는 두 가지 방식이 존재한다. 32비트일 경우 총 4개의 바이트를 배열하는 데 상위 바이트에서 하위 바이트 순으로 메모리의 낮은 주소쪽에서 높은 주소쪽으로 저장하는 방식이 빅 엔디언이다. 반대로 하위 바이트에서 상위 바이트 순으로 낮은 주소쪽에서 높은 주소쪽으로 저장하는 방식을 리틀 엔디언이라고 한다. 좀더 쉽게 표현하자면 빅 엔디안은 사람이 표현하는 방식과 동일한 반면 리틀 엔디안은 거꾸로 표현된다. 대표적인 이 두 가지 저장 방식은  자체적으로 순서를 정하는 것이 아니라 작동하는 기반 시스템(CPU)에 의해서 결정된다.

다음은 "ABDC" 문자열을 이진 데이터가 32비트로 저장될 경우에 빅 엔디안과 리틀 엔디안을 비교했다. 참고로 문자열은 아스키(ASCII) 값에 의해서 숫자로 처리된다. 즉 A65, B66, C67, D68이다.

빅 엔디안(big-endian)

 리틀 엔디안(little-endian)

사실 빅 엔디안과 리틀 엔디안은 성능상의 차이가 거의 없다고 보는 견해이다. 그럼에도 이 두 가지 방식이 존재하는 이유는 설계 관점의 차이 때문일 것이라 추측된다. 일반적으로 사용하고 있는 시스템인 인텔(intel) 또는 AMD의 CPU와 같이 X86(80x86) 아키텍처 기반은 리틀 엔디안으로 처리한다. 반면 네트워크 기반에서는 네크워크의 호출 체계인 주소가 순차적인 형식으로 되어 있어 프로토콜(protocol)과 일부 파일 포맷(format)에서는 빅 엔디안을 사용한다. 중요한 포인트는 일반적으로 사용되고 있는 것은 리틀 엔디안(little-endian)이라는 것이다.

자바스크립트에서의 엔디안(endian)

다양한 개발 언어에서 엔디안(endian)에 대해 이해하고 원하는 처리 결과가 나오도록 신경을 써야할 것이다. 이 문서는 엔디안에 대해 설명하는 게 목적이지만 데브딕의 레퍼런스가 대부분 웹 개발, 그것도 클라이언트(client side) 기술들을 다루므로 자바스크립트 개발 환경에서 새롭게 도입한 ArrayBufferSharedArrayBuffer에 대해 끝으로 간단하게 언급하자고 한다. 자세한 기술적인 내용들은 해당 섹션을 참고하기 바란다.

ECMAScript의 최신 버전에는 ArrayBuffer, SharedArrayBuffer 객체가 새롭게 추가되었다. 이 두 가지 객체는 메모리 상에서 이진 데이터를 다루는 기술들이다. 여담으로 자바스크립트에서 메모리를 들여다 보는 기술이 등장하기 시작했다는 것에 대해 격세지감을 느낀다. 참고로 SharedArrayBuffer는 2018년에 발견된 CPU 버그로 인해 각 유저 에이전트에서 지원하는 방식과 정책이 다르다. 표준 아닌 표준이 되어버린 셈이다. 따라서 이후 ShardArrayBuffer 객체는 빼고 설명을 이어나가겠다.

메모리와 연관되어 있다보니 당연히 엔디안을 이해해야 한다. ArrayBuffer는 메모리에 데이터를 저장하기 위한 기본 준비를 하는 객체이다. 실제로 데이터를 저장하고 읽고 변경하는 객체는 뷰(view)라는 개념으로 다음과 같은 별도의 객체가 존재한다.

TypedArray

TypedArray는 이름에서 의미하듯이 타입이 정해진 데이터의 배열이라는 뜻이다. 즉 숫자의 유형이 정해져 메모리에 저장된다는 의미이다. 하위 클래스로 다양한 유형을 지원하는 객체가 존재한다. TypedArray은 마치 배열처럼(보통 유사배열이라 불림) 설계되어 있어 인덱스(index)로 접근이 가능하다. 그리고 중요한 것은 TypedArray 유형은 시스템의 기본 엔디안(endian)을 사용한다. 앞서 이야기했듯이 대부분의 컴퓨터는 리틀 엔디안을 사용한다. 따라서 시스템의 기본 엔디안을 이해하고 올바른 데이터 처리를 해야 할 것이다.

DataView

DataView 객체는 상대적으로 TypedArray 객체에 비해 고정된 타입이 아닌 자유로운 타입을 지원한다. 그리고 시스템의 엔디안과 관계없이 스스로 결정할 수도 있다. 기본으로 빅 엔디안으로 되어 있으며 리틀 엔디안으로 바꿀 수도 있다.

위 두 개의 뷰 객체는 확연한 차이를 가지고 있다. TypedArray는 데이터 구성에 더 중점을 두고 있고 DataView는 데이터의 사용에 중점을 둔 것이라 보면 좀더 이해가 쉬울 듯 하다.