[데이터 중심 애플리케이션 설계] 04장 - 부호화와 발전
이번 장에서는 JSON, XML, 프로토콜 버퍼(Protocol Buffers), 스리프트(Thrift), 아브로(Avro)를 비롯해서 데이터 부호화를 위한 다양한 형식을 살펴본다. 특히 어떻게 스키마를 변경하고 예전 버전과 새로운 버전의 데이터와 코드가 공존하는 시스템을 어떻게 지원하는지를 설명한다. 그다음 웹 서비스에서의 대표 상태 전달(REST, Representational State Transfer), 원격 프로시저 호출(remote procedure call)뿐 아니라 액터(actor)와 메시지 큐 같은 메시지 전달 시스템에서 다양한 데이터 부호화 형식이 데이터 저장과 통신에 어떻게 사용되는지 살펴본다.
1. 부호화(직렬화, 마샬링)
많은 프로그래밍 언어는 인메모리 객체를 바이트열로 부호화하는 기능을 내장한다. 예를 들어 자바는 java.io.Serializable이 있다. 자바 전용인 Kryo 같은 서드파티 라이브러리도 많다. 프로그래밍 언어에 내장된 부호화 라이브러리는 최소한의 추가 코드로 인메모리 객체를 저장하고 복원할 수 있기 때문에 매우 편리하지만 심각한 문제점 또한 많다.
- 부호화는 보통 특정 프로그래밍 언어와 묶여 있어 다른 언어에서 데이터를 읽기는 매우 어렵다. 이런 부호화로 데이터를 저장하고 전송하는 경우 매우 오랜 시간이 될지도 모를 기간 동안 현재 프로그래밍 언어로만 코드를 작성해야 할 뿐 아니라 다른 시스템(다른 언어를 사용할 수도 있음)과 통합하는 데 방해가 된다.
- 동일한 객체 유형의 데이터를 복원하려면 복호화 과정이 임의의 클래스를 인스턴스화할 수 있어야 한다. 이것은 종종 보안 문제의 원인이 된다. 공격자가 임의의 바이트열을 복호화할 수 있는 애플리케이션을 얻을 수 있으면 임의의 클래스를 인스턴스화할 수 있고 공격자가 원격으로 임의 코드를 실행하는 것과 같은 끔찍한 일이 발생할 수 있다.
- 데이터 버전 관리는 보통 부호화 라이브러리에서는 나중에 생각하게 된다. 데이터를 빠르고 쉽게 부호화하기 위해 상위, 하위 호환성의 불편한 문제가 등한시되곤 한다.
- 효율성(부호화나 복호화에 소요되는 CPU 시간과 부호화된 구조체의 크기)도 종종 나중에 생각하게 된다. 예를 들어 자바의 내장 직렬화는 성능이 좋지 않고 비대해지는 부호화로 유명하다.
이런 이유로 매우 일시적인 목적 외에 내장된 부호화를 사용하는 방식은 일반적으로 좋지 않다.
2. JSON과 XML
JSON과 XML은 많은 프로그래밍 언어에서 읽고 쓸 수 있는 표준화된 부호화로서 확실한 경쟁자들이다. 하지만 약간의 문제점들 역시 내포하고 있다.
- 수의 부호화에는 많은 애매함이 있다. 수와 숫자로 구성된 문자열의 구분, 큰 수 처리 등에 주의해야 한다.
- 유니코드 문자열은 잘 지원해서 사람이 읽기는 좋지만 이진 문자열은 지원하지 않는다. Base64로 부호화하여 이런 제한을 피하기도 하지만 데이터 크기가 약 33% 증가한다.
3. 이진 부호화
작은 데이터셋의 경우에는 부호화 형식 선택으로 얻는 이득이 무시할 정도지만 테라바이트 정도가 되면 데이터 타입의 선택이 큰 영향을 미친다. 이진 부호화를 통해 데이터셋의 크기를 JSON이나 XML 등에 비해 많이 줄일 수 있다.
아파치 스리프트와 프로토콜 버퍼는 같은 원리를 기반으로 한 이진 부호화 라이브러리로 둘 다 부호화할 데이터를 위한 스키마가 필요하다. 스키마는 새로운 필드를 추가할 경우 새로운 태그 번호를 부여하면 되는데 이때 예전 코드에서 새로운 코드로 기록한 데이터를 읽는 경우 예전 코드가 인식하지 못하는 태그 번호를 무시하는 것으로 상위 호환성을 유지할 수 있다. 하위 호환성의 경우 각 필드에 고유한 태그 번호가 있는 동안에는 태그 번호가 계속 같은 의미를 가지고 있기 때문에 새로운 코드가 예전 데이터를 항상 읽을 수 있다.
4. 데이터베이스를 통한 데이터 플로
데이터베이스에 기록하는 프로세스는 데이터를 부호화하고 데이터베이스에서 읽는 프로세스는 데이터를 복호화한다. 데이터베이스에 접근하는 단일 프로세스가 있는 경우 읽기는 단순히 동일 프로세스의 최신 버전이다. 이 경우 데이터베이스에 뭔가를 저장하는 일을 미래의 자신에게 메시지를 보내는 일처럼 생각할 수 있다. 여기서 하위 호환성은 분명히 필요한데 그렇지 않다면 이전에 기록한 내용을 미래의 자신이 복호화할 수 없다.
일반적으로 동시에 다양한 프로세스가 데이터베이스에 접근하는 일은 흔한데 어느 방법이든 애플리케이션이 변경되는 환경에서 데이터베이스에 접근하는 경우 아마도 일부 프로세스는 새로운 코드로 수행 중이고 일부 다른 프로세스는 예전 코드로 수행 중일 것이다. 이것은 데이터베이스 내 값이 새로운 버전의 코드로 기록된 다음 현재 수행 중인 예전 버전의 코드로 그 값을 읽을 가능성이 있다는 의미고 따라서 데이터베이스에서 상위 호환성도 대개 필요하다.
Ref
- 데이터 중심 애플리케이션 설계 - p.113 ~ p.146