부호화(직렬화)란?

Alan·2023년 3월 13일
0

부호화는 데이터 구조를 네트워크나 디스크 상의 바이트열로 변환하는 것이며, 이는 애플리케이션의 효율성뿐만 아니라 아키텍처와 배포의 선택사항에도 영향을 끼침

  • 이번 장에선 다양한 데이터 부호화 형식과 호환성 속성을 살펴본다

발전성 : 변화를 쉽게 만들기

  • 앞서 데이터 중심 애플리케이션에서 필요한 요구 사항 중 발전성이 있었음. 이를 중심으로 생각하면 이해하기 쉬울 것

  • 대부분의 경우 애플리케이션의 기능을 변경하려면 저장하는 데이터도 변경해야 함.

  • 이런 변화를 대처하기 위한 방법은 데이터 모델별로 다양한 방법이 존재.

  • 관계형 데이터베이스는 일반적으로 모든 데이터가 하나의 스키마를 따른다고 가정함. ALTER 구문으로 스키마를 변경할 수 있지만, 특정 시점에서는 정확하게 하나의 스키마가 적용되는 특징을 가짐

  • 반면 읽기 스키마(schema-on-read) 혹은 스키마리스 데이터 베이스는 스키마를 강요하지 않기때문에 이전 데이터 타입과 새로운 데이터 타입이 섞여서 포함될 수 있음

  • 서버 측 애플리케이션의 업그레이드는 몇 개의 노드에 새 버전을 배포하고 원할하게 실행되는지 확인한 다음 서서히 모든 노드로 확장해가는 순회식 업그레이드(rolling upgrade) 또는 단계적 롤아웃(staged rollout)이라는 방식을 사용

  • 이는 클라이언트 측, 어떤 사용자는 한동안 업데이트를 설치하지 않을 수도 있기 때문

  • 즉, 예전 버전의 코드와 새로운 버전의 코드, 이전의 데이터 타입과 새로운 데이터 타입이 공존할 수 있다는 의미. 시스템이 원활하게 실행되려면 양방향으로 호환성이 유지되어야 함

  • 하위 호환성

    • 새로운 코드는 이전 코드가 기록한 데이터를 읽을 수 있어야 함
  • 상위 호환성

    • 이전 코드는 새로운 코드가 기록한 데이터를 읽을 수 있어야 함
  • 보통 상위 호환성을 다루는 문제가 하위 호환성 다루는 문제보다 복잡함

데이터 부호화 형식

  • 프로그램은 보통 (최소)두 가지 형태로 표현된 데이터를 사용해 동작

  • 메모리에 객체, 구조체, array, hash table, tree 등으로 데이터가 유지됨. 이는 CPU에서 효율적으로 접근하고 조작할 수 있게 최적화(보통은 포인터로)됨

  • 데이터를 파일에 쓰거나 네트워크를 통해 전송하려면 일련의 바이트열(ex. JSON)의 형태로 부호화해야 함. 포인터는 다른 프로세스가 이해할 수 없으므로 바이트열은 보통 메모리에서 사용하는 데이터 구조와는 큰 차이가 있음

  • 따라서 두 가지 표현 사이의 전환이 필요함. 인메모리 표현에서 바이트열로의 전환을 부호화(직렬화)라고 하며, 그 반대를 복호화(역직렬화)라고 함

언어별 형식

  • 프로그래밍 언어 단에서도 인메모리 객체를 바이트열로 부호화하는 기능을 제공

  • Java - java.io.Serializable

  • python - pickle

  • 등등

  • 프로그래밍 언어에 내장된 부호화 라이브러리는 매우 편리하지만 심각한 문제가 존재

    • 부호화가 특정 언어와 묶여있다면 다른 언어에서 데이터를 읽기가 어려워짐. 뿐만 아니라 다른 언어로 작성된 시스템과의 통합에 방해가 될 수 있음

    • 동일한 객체 유형의 데이터를 복원하려면 복호화 과정이 임의의 클래스를 인스턴스화할 수 있어야 함. 종종 이것은 보완 문제의 원인이 됨. 공격자가 임의의 바이트열을 복호화할 수 있는 애플리케이션을 얻을 수 있으면 임의의 클래스를 인스턴스화할 수 있다는 이야기 이고 이는 공격자가 원격으로 임의 코드를 실행하는 것과 같은 끔찍한 일이 발생할 수도 있다는 의미

    • 데이터 버전관리는 보통 부호화 라이브러리에서는 나중에 생각하게 됨. 상위 호환성 및 하위 호환성에서 불편한 문제가 생길 수 있음

    • 효율성(CPU, 부호화된 구조체의 크기)도 등한시됨. 예를 들어 자바의 내장 직렬화는 성능이 좋지 않고 비대해지는 부호화로 유명함

  • 따라서 일반적으로는 언어에 내장된 부호화는 사용하지 않음

JSON, XML, 이진 변형

  • JSON과 XML을 확실히 인기있는 표준화된 부호화

  • 공통적으로 텍스트 형식이기 때문에 어느 정도 사람이 읽을 수 있지만, 일부 미묘한 문제가 존재

    • 수의 부호화에 많은 애매함이 있음. XML과 CSV에서는 수로 구성된 문자열을 구분할 수 없음(외부 스키마 참조 제외). JSON은 문자열과 수를 구분하지만 정수와 부동소수점 수를 구별하지 않으며 정밀도도 지정하지 않음

    • 이러한 애매함은 큰 수를 다룰 때 문제가 됨. 트위터에서는 이러한 문제를 JSON을 JSON 수로 한번, 10진 문자열로 한번 총 두 번 포함하는 형식으로 해결

    • JSON과 XML은 유니코드 문자열을 지원. 하지만, 이진 문자열은 지원하지 않음. 사람들은 보통 이진 데이터를 Base64를 사용해 텍스트로 부호화해 이런 제한을 피함. 이러한 변형의 경우 데이터의 크기가 33% 증가한다는 단점이 존재

    • XML과 JSON은 모두 스키마를 지원하지만, 익히고 구현하기가 상당히 난해함

    • CSV는 스키마가 없으므로 각 로우와 칼럼의 의미를 정의하는 작업은 애플리케이션이 해야 함. 즉, 새로운 칼럼을 추가하려면 수동으로 변경처리를 해야 함. 또한 매우 모호한 형식(값에 쉼표나 개행문자가 있다면?)

    • 이러한 결점에도 불구하고 JSON, XML, CSV는 다양한 용도에서 사용하기 적합함
  • 이진 부호화

    • JSON, XML은 이진 형식과 비교해 훨씬 많은 공간을 차지함

    • 이 예로 보자면, 스키마를 지정하지 않는 부호화에서는 필드값 문자열을 항상 포함해야 함

    • 아파치 스리프트와 프로토콜 버퍼

      • 두 형식 모두 부호화할 데이터를 위한 스키마가 필요

      • 즉 스키마를 통해 필드값을 항상 적어야 하는 문제를 해결(대신 필드 대그(field tag)를 사용)

  • 이러한 방식은 필드타입과 태그 숫자를 단일 바이트로 줄이고 가변 길이 정수를 사용해 부호화 하는 형태임

  • 이는 -64에서 63 사이의 숫자는 1바이트로 부호화하고, -8192에서 8191 사이의 숫자는 2바이트로 부호화한다는 의미

  • 스키마의 required와 optional을 살펴보자. 이진 데이터에서 필드가 필수인지 아닌지 나타내는 것은 아님. required를 사용하면 필드가 설정되지 않은 경우를 실행시에 확인할 수 있을 뿐임

JSON과 XML의 특징, 그리고 이러한 형식의 문제점을 해결하는 방식인 스키마의 도입과 공간을 절약하는 방법에 대해 간단하게 살펴봤다.
다음 포스팅에서는 필드 태그와 스마의 발전 방향, 하둡에서 주로 사용하는 Avro에 대해 알아보자.

0개의 댓글