메시지 인코딩 고려 사항
많은 클라우드 애플리케이션은 시스템의 구성 요소 간에 정보를 교환하기 위해 비동기식 메시지를 사용합니다. 메시징의 중요한 측면은 페이로드 데이터를 인코딩하는 데 사용되는 형식입니다. 메시징 기술을 선택한 후 다음 단계는 메시지를 인코딩하는 방법을 정의하는 것입니다. 많은 옵션을 사용할 수 있지만 올바른 선택은 사용 사례에 따라 다릅니다.
이 문서에서는 몇 가지 고려 사항에 대해 설명합니다.
메시지 교환 요구
생산자와 소비자 간의 메시지 교환에는 다음이 필요합니다.
- 메시지의 페이로드를 정의하는 모양 또는 구조입니다.
- 페이로드를 나타내는 인코딩 형식입니다.
- 인코딩된 페이로드를 읽고 쓰기 위한 직렬화 라이브러리입니다.
메시지의 생산자는 비즈니스 논리 및 소비자에게 보내려는 정보를 기반으로 메시지 모양을 정의합니다. 모양을 구성하려면 정보를 개별 또는 관련 주제(필드)로 나눕니다. 해당 필드에 대한 값의 특성을 결정합니다. 가장 효율적인 데이터 형식은 무엇인가요? 페이로드에 항상 특정 필드가 있나요? 페이로드에 단일 레코드 또는 반복되는 값 집합이 있나요?
그런 다음 필요에 따라 인코딩 형식을 선택합니다. 특정 요소에는 필요한 경우 고도로 구조화된 데이터를 만드는 기능, 메시지를 인코딩하고 전송하는 데 걸리는 시간, 페이로드를 구문 분석하는 기능이 포함됩니다. 인코딩 형식에 따라 잘 지원되는 직렬화 라이브러리를 선택합니다.
메시지의 소비자는 들어오는 메시지를 읽는 방법을 알 수 있도록 이러한 결정을 알고 있어야 합니다.
메시지를 전송하기 위해 생산자는 메시지를 인코딩 형식으로 직렬화합니다. 수신 측에서 소비자는 데이터를 사용하기 위해 페이로드를 역직렬화합니다. 이렇게 하면 두 엔터티가 모델을 공유하고 모양이 변경되지 않는 한 문제 없이 메시징이 계속됩니다. 계약이 변경되면 인코딩 형식은 소비자를 손상시키지 않고 변경 내용을 처리할 수 있어야 합니다.
JSON과 같은 일부 인코딩 형식은 자체 설명적이므로 스키마를 참조하지 않고 구문 분석할 수 있습니다. 그러나 이러한 형식은 더 큰 메시지를 생성하는 경향이 있습니다. 다른 형식을 사용하면 데이터가 쉽게 구문 분석되지 않을 수 있지만 메시지는 압축됩니다. 이 문서에서는 형식을 선택하는 데 도움이 될 수 있는 몇 가지 요소를 강조합니다.
인코딩 형식 고려 사항
인코딩 형식은 구조화된 데이터 세트가 바이트로 표현되는 방식을 정의합니다. 메시지 유형은 형식 선택에 영향을 줄 수 있습니다. 비즈니스 트랜잭션과 관련된 메시지에는 고도로 구조화된 데이터가 포함될 가능성이 큽니다. 또한 나중에 감사 목적으로 검색할 수도 있습니다. 이벤트 스트림의 경우 가능한 한 빨리 레코드 시퀀스를 읽고 통계 분석을 위해 저장할 수 있습니다.
다음은 인코딩 형식을 선택할 때 고려해야 할 몇 가지 사항입니다.
사람의 가독성
메시지 인코딩은 크게 텍스트 기반 형식과 이진 형식으로 나눌 수 있습니다.
텍스트 기반 인코딩을 사용하면 메시지 페이로드가 일반 텍스트이므로 코드 라이브러리를 사용하지 않고도 사람이 검사할 수 있습니다. 적합한 보관 데이터는 사람이 읽을 수 있어야 합니다. 또한 사람이 페이로드를 읽을 수 있기 때문에 텍스트 기반 형식을 디버그하고 오류 문제 해결을 위해 로그로 보내기가 더 쉽습니다.
단점은 페이로드가 더 큰 경향이 있다는 것입니다. 일반적인 텍스트 기반 형식은 JSON입니다.
암호화
메시지에 중요한 데이터가 있는 경우 Azure Service Bus 미사용 데이터 암호화에 대한 이 지침에 설명된 대로 해당 메시지를 완전히 암호화해야 하는지 여부를 고려합니다. 또는 특정 필드만 암호화해야 하고 클라우드 비용을 줄이려는 경우 NServiceBus와 같은 라이브러리를 사용하는 것이 좋습니다.
인코딩 크기
메시지 크기는 유선 네트워크 I/O 성능에 영향을 줍니다. 이진 형식은 텍스트 기반 형식보다 더 간결합니다. 이진 형식에는 직렬화/역직렬화 라이브러리가 필요합니다. 페이로드는 디코딩되지 않으면 읽을 수 없습니다.
유선 공간을 줄이고 메시지를 더 빠르게 전송하려면 이진 형식을 사용합니다. 이 형식 범주는 스토리지 또는 네트워크 대역폭이 문제가 되는 시나리오에서 권장됩니다. 이진 형식 옵션에는 Apache Avro, Google Protocol Buffers(protobuf), MessagePack 및 CBOR(Concise Binary Object Representation)이 있습니다. 이러한 형식의 장단점은 이 섹션에서 설명합니다.
단점은 페이로드가 사람이 읽을 수 없다는 것입니다. 대부분의 이진 형식은 유지 관리 비용이 많이 드는 복잡한 시스템을 사용합니다. 또한 디코딩할 특수 라이브러리가 필요하며 보관 데이터를 검색하려는 경우 지원되지 않을 수 있습니다.
페이로드 이해
메시지 페이로드는 바이트 시퀀스로 도착합니다. 이 시퀀스를 구문 분석하려면 소비자가 페이로드의 데이터 필드를 설명하는 메타데이터에 액세스할 수 있어야 합니다. 메타데이터를 저장하고 배포하는 데에는 두 가지 주요 방법이 있습니다.
태그가 지정된 메타데이터. 일부 인코딩, 특히 JSON에서 필드는 메시지 본문 내에서 데이터 형식 및 식별자로 태그가 지정됩니다. 이러한 형식은 스키마를 참조하지 않고 값 사전으로 구문 분석할 수 있기 때문에 자체적으로 설명합니다. 소비자가 필드를 이해하는 한 가지 방법은 예상 값을 쿼리하는 것입니다. 예를 들어 생산자는 JSON으로 페이로드를 보냅니다. 소비자는 JSON을 사전으로 구문 분석하고 페이로드를 이해하기 위해 필드의 존재를 확인합니다. 또 다른 방법은 소비자가 생산자가 공유하는 데이터 모델을 적용하는 것입니다. 예를 들어, 정적으로 유형이 지정된 언어를 사용하는 경우 많은 JSON 직렬화 라이브러리가 JSON 문자열을 유형이 지정된 클래스로 구문 분석할 수 있습니다.
Schema. 스키마는 메시지의 구조와 데이터 필드를 공식적으로 정의합니다. 이 모델에서 생산자와 소비자는 잘 정의된 스키마를 통해 계약을 맺습니다. 스키마는 데이터 형식, 필수/선택 필드, 버전 정보, 페이로드 구조를 정의할 수 있습니다. 생산자는 작성자 스키마에 따라 페이로드를 보냅니다. 소비자는 읽기 권한자 스키마를 적용하여 페이로드를 수신합니다. 메시지는 인코딩별 라이브러리를 사용하여 직렬화/역직렬화됩니다. 스키마를 배포하는 방법에는 두 가지가 있습니다.
스키마를 메시지의 프리앰블 또는 헤더로 저장하되 페이로드와는 별도로 저장합니다.
스키마를 외부에 저장합니다.
일부 인코딩 형식은 스키마를 정의하고 스키마에서 클래스를 생성하는 도구를 사용합니다. 생산자와 소비자는 해당 클래스와 라이브러리를 사용하여 페이로드를 직렬화 및 역직렬화합니다. 라이브러리는 작성기와 읽기 권한자 스키마 간의 호환성 검사도 제공합니다. protobuf와 Apache Avro는 모두 이러한 방법을 따릅니다. 주요 차이점은 protobuf에는 언어에 구애받지 않는 스키마 정의가 있지만 Avro는 컴팩트 JSON을 사용한다는 것입니다. 또 다른 차이점은 두 형식이 읽기 권한자와 작성기 스키마 간의 호환성 검사를 제공하는 방식에 있습니다.
스키마 레지스트리에 스키마를 외부적으로 저장하는 또 다른 방법입니다. 메시지에는 스키마 및 페이로드에 대한 참조가 포함되어 있습니다. 생산자는 메시지의 스키마 식별자를 보내고 소비자는 외부 저장소에서 해당 식별자를 지정하여 스키마를 검색합니다. 양 당사자는 형식별 라이브러리를 사용하여 메시지를 읽고 씁니다. 스키마를 저장하는 것 외에도 레지스트리는 스키마가 발전함에 따라 생산자와 소비자 간의 계약이 깨지지 않도록 호환성 검사를 제공할 수 있습니다.
방법을 선택하기 전에 전송 데이터 크기 또는 보관된 데이터를 나중에 구문 분석하는 기능 중 더 중요한 것이 무엇인지 결정합니다.
페이로드와 함께 스키마를 저장하면 인코딩 크기가 더 커지고 일시적인 메시지에 기본 설정됩니다. 더 작은 바이트 청크를 전송하는 것이 중요하거나 일련의 레코드가 예상되는 경우 이 방법을 선택합니다. 외부 스키마 저장소를 유지 관리하는 비용이 높을 수 있습니다.
그러나 페이로드의 주문형 디코딩이 크기보다 더 중요한 경우 페이로드가 있는 스키마 또는 태그가 지정된 메타데이터 방법을 포함하여 이후 디코딩을 보장합니다. 메시지 크기가 크게 증가할 수 있으며 스토리지 비용에 영향을 줄 수 있습니다.
스키마 버전 관리
비즈니스 요구 사항이 변경됨에 따라 형태도 변경될 것으로 예상되며 스키마도 진화할 것입니다. 버전 관리를 통해 생산자는 새로운 기능을 포함할 수 있는 스키마 업데이트를 표시할 수 있습니다. 버전 관리에는 두 가지 측면이 있습니다.
소비자는 변경 내용을 알고 있어야 합니다.
한 가지 방법은 소비자가 모든 필드를 확인하여 스키마가 변경되었는지 여부를 확인하는 것입니다. 또 다른 방법은 생산자가 메시지와 함께 스키마 버전 번호를 게시하는 것입니다. 스키마가 발전하면 생산자가 버전을 증가시킵니다.
변경 내용이 소비자의 비즈니스 논리에 영향을 미치거나 중단되어서는 안 됩니다.
필드가 기존 스키마에 추가되었다고 가정합니다. 새 버전을 사용하는 소비자가 이전 버전에 따라 페이로드를 받는 경우 새 필드의 부족을 간과할 수 없으면 논리가 깨질 수 있습니다. 반대의 경우를 고려하여 새 스키마에서 필드가 제거되었다고 가정합니다. 이전 스키마를 사용하는 소비자는 데이터를 읽지 못할 수 있습니다.
Avro와 같은 인코딩 형식은 기본값을 정의하는 기능을 제공합니다. 앞의 예에서 필드가 기본값으로 추가되면 누락된 필드가 기본값으로 채워집니다. protobuf와 같은 다른 형식은 필수 및 선택 필드를 통해 유사한 기능을 제공합니다.
페이로드 구조
데이터가 페이로드에 배열되는 방식을 고려합니다. 레코드 시퀀스인가요, 아니면 불연속 단일 페이로드인가요? 페이로드 구조는 다음 모델 중 하나로 분류할 수 있습니다.
배열/사전/값: 1차원 또는 다차원 배열의 값을 보유하는 항목을 정의합니다. 항목에는 고유한 키-값 쌍이 있습니다. 복잡한 구조를 나타내기 위해 확장될 수 있습니다. 일부 예에는 JSON, Apache Avro 및 MessagePack이 있습니다.
이 레이아웃은 메시지가 서로 다른 스키마로 개별적으로 인코딩된 경우에 적합합니다. 여러 레코드가 있는 경우 페이로드가 과도하게 중복되어 페이로드가 팽창할 수 있습니다.
테이블 형식 데이터: 정보는 행과 열로 나뉩니다. 각 열은 필드 또는 정보의 제목을 나타내며 각 행에는 해당 필드에 대한 값이 포함됩니다. 이 레이아웃은 시계열 데이터와 같은 반복되는 정보 집합에 효율적입니다.
CSV는 가장 단순한 텍스트 기반 형식 중 하나입니다. 공통 헤더가 있는 레코드 시퀀스로 데이터를 표시합니다. 이진 파일 인코딩의 경우 Apache Avro에는 CSV 헤더와 유사하지만 압축된 인코딩 크기를 생성하는 프리앰블이 있습니다.
라이브러리 지원
독점 모델보다 잘 알려진 형식을 사용하는 것이 좋습니다.
잘 알려진 형식은 커뮤니티에서 보편적으로 지원하는 라이브러리를 통해 지원됩니다. 특수 형식을 사용하면 특정 라이브러리가 필요합니다. 비즈니스 논리는 라이브러리에서 제공하는 일부 API 디자인 선택 사항을 해결해야 할 수 있습니다.
스키마 기반 형식의 경우 읽기 권한자 스키마와 작성기 스키마 간의 호환성 검사를 수행하는 인코딩 라이브러리를 선택합니다. Apache Avro와 같은 특정 인코딩 라이브러리는 소비자가 메시지를 역직렬화하기 전에 작성자와 읽기 권한자 스키마를 모두 지정할 것으로 예상합니다. 이 검사는 소비자가 스키마 버전을 알고 있는지 확인합니다.
상호 운용성
형식 선택은 특정 워크로드 또는 기술 에코시스템에 따라 다를 수 있습니다.
예를 들면 다음과 같습니다.
Azure Stream Analytics는 JSON, CSV 및 Avro를 기본적으로 지원합니다. Stream Analytics를 사용할 때 가능한 경우 이러한 형식 중 하나를 선택하는 것이 좋습니다. 그렇지 않은 경우 사용자 지정 역직렬 변환기를 제공할 수 있지만 이렇게 하면 솔루션이 약간 더 복잡해집니다.
JSON은 HTTP REST API의 표준 교환 형식입니다. 애플리케이션이 클라이언트에서 JSON 페이로드를 수신한 다음 비동기 처리를 위해 메시지 큐에 배치하는 경우 다른 형식으로 다시 인코딩하는 대신 메시징에 JSON을 사용하는 것이 합리적일 수 있습니다.
이는 상호 운용성 고려 사항의 두 가지 예일 뿐입니다. 일반적으로 표준화된 형식은 사용자 지정 형식보다 상호 운용성이 높습니다. 텍스트 기반 옵션에서 JSON은 가장 상호 운용 가능한 것 중 하나입니다.
인코딩 형식 선택
다음은 몇 가지 자주 사용되는 인코딩 형식입니다. 형식을 선택하기 전에 고려해야 할 사항입니다.
JSON
JSON은 개방형 표준(IETF RFC8259)입니다. 배열/사전/값 모델을 따르는 텍스트 기반 형식입니다.
JSON은 메타데이터에 태그를 지정하는 데 사용할 수 있으며 스키마 없이 페이로드를 구문 분석할 수 있습니다. JSON은 이후 및 이전 버전과의 호환성에 도움이 되는 선택적 필드를 지정하는 옵션을 지원합니다.
가장 큰 장점은 보편적으로 사용할 수 있다는 것입니다. 대부분의 메시징 서비스에서 가장 상호 운용 가능하며 기본 인코딩 형식입니다.
텍스트 기반 형식이기 때문에 유선상으로는 효율적이지 않으며 스토리지가 문제인 경우 이상적인 선택이 아닙니다. 캐시된 항목을 HTTP를 통해 클라이언트에 직접 반환하는 경우 JSON을 저장하면 다른 형식에서 역직렬화한 다음 JSON으로 직렬화하는 비용을 절약할 수 있습니다.
단일 레코드 메시지 또는 각 메시지에 다른 스키마가 있는 메시지 시퀀스에 JSON을 사용합니다. 시계열 데이터와 같은 레코드 시퀀스에 JSON을 사용하지 마세요.
이진 JSON(BSON)과 같은 JSON의 다른 변형이 있습니다. 이진 인코딩은 MongoDB에서 작동하도록 정렬됩니다.
쉼표로 구분된 값(CSV)
CSV는 텍스트 기반 테이블 형식입니다. 테이블의 헤더는 필드를 나타냅니다. 메시지에 레코드 집합이 포함된 경우 기본 설정되는 선택입니다.
단점은 표준화가 부족하다는 것입니다. 구분 기호, 헤더 및 빈 필드를 표현하는 방법에는 여러 가지가 있습니다.
프로토콜 버퍼(protobuf)
프로토콜 버퍼 (또는 protobuf)는 강력한 형식의 정의 파일을 사용하여 키/값 쌍에서 스키마를 정의하는 직렬화 형식입니다. 그런 다음 이러한 정의 파일은 메시지 직렬화 및 역직렬화에 사용되는 언어별 클래스로 컴파일됩니다.
메시지에는 압축된 이진 파일 소형 페이로드가 포함되어 있어 전송 속도가 더 빨라집니다. 단점은 페이로드가 사람이 읽을 수 없다는 것입니다. 또한 스키마가 외부에 있으므로 보관된 데이터를 검색해야 하는 경우에는 권장하지 않습니다.
Apache Avro
Apache Avro는 protobuf와 유사한 정의 파일을 사용하지만 컴파일 단계가 없는 이진 파일 직렬화 형식입니다. 대신 직렬화된 데이터에는 항상 스키마 프리앰블이 포함됩니다.
프리앰블은 헤더 또는 스키마 식별자를 보유할 수 있습니다. 인코딩 크기가 작기 때문에 스트리밍 데이터에는 Avro를 사용하는 것이 좋습니다. 또한 레코드 집합에 적용되는 헤더가 있기 때문에 표 형식 데이터에 적합합니다.
MessagePack
MessagePack은 네트워크를 통해 전송하기 위해 압축되도록 디자인된 이진 직렬화 형식입니다. 메시지 스키마 또는 메시지 형식 확인은 수행되지 않습니다. 이 형식은 대량 스토리지에 권장되지 않습니다.
CBOR
간결한 이진 파일 개체 표현(CBOR)(사양)은 작은 인코딩 크기를 제공하는 이진 형식입니다. MessagePack에 비해 CBOR의 장점은 RFC7049의 IETF와 호환된다는 것입니다.
다음 단계
- 클라우드 애플리케이션의 메시징 디자인 패턴을 이해합니다.