책너두 (데이터 중심 애플리케이션 설계) 11일차 (~133p)

요약

  • 아브로 이진 부호화 형식을 이해하게 됨.
    • 스리프트, 프로토콜 버퍼와 대적할 만한 또 하나의 이진 부호화 형식
    • 스키마에 태그 번호가 없음
      • 스키마를 함꼐 확인하여 데이터 복호화 해야 함.
    • 쓰기, 읽기 스키마가 동일하지 않아도 됨.
      • 호환만 가능하면 됨.
      • 동적 스키마 생성에 유리함.
    • 아브로는 코드 생성 없이, 간단히 데이터를 조회할 수 있음.
      • 자기 기술적이라고 함.
  • 데이터플로 모드에 대한 내용을 알게 됨.
    • 추상적인 개념, 데이터 복호화, 부호화의 주체에 대한 내용임.
    • 데이터 베이스를 통한 데이터 플로를 알게 됨.
      • 여러 프로세스가 데이터베이스에 접근하면서 데이터 호환성이 필요함.
      • data outlives code 가 발생할 수 있음.

메모

아브로

  • 아파치 아브로는 프로토콜 버퍼와 스리프트와 대적할 만한 또 하나의 이진 부호화 형식임.
  • 아브로도 부호화할 데이터 구조를 지정하기 위해 스키마를 사용함.
    • 두 개의 스키마 언어 사용
      • 아브로 IDL
      • JSON 기반 언어
  • 아브로는 스키마에 태그 번호가 없음.
    • 스키마를 이용하여 레코드를 부호화하면, 아브로 이진 부호화 길이는 32바이트로 살펴본 모든 부호화 중 길이가 가장 짧음.
    • 아브로로 부호화된 바이트열에는 필드나 데이터타입을 식별하기 위한 정보가 없음.
      • ex) 문자열임을 알려주는 정보가 부호화된 데이터에 없음.
      • 따라서, 아브로를 이용해 이진 데이터를 파싱하려면 스키마에 나타난 순서대로 필드를 살펴보고, 스키마를 이용하여 각 필드의 데이터 타입을 미리 파악해야 함.
        • 이는, 데이터를 읽는 코드가 데이터를 기록한 코드와 정확히 같은 스키마를 사용한 경우에만 이진 데이터를 올바르게 복호화할 수 있음.

쓰기 스키마와 읽기 스키마

  • 아브로로 데이터를 부호화하려면 알고있는 스키마 버전을 사용해 데이터를 부호화한다.
    • 해당 스키마를 애플리케이션에 포함할 수 있고, 이를 쓰기 스키마(writer’s schema) 라고 함.
  • 읽은 데이터를 복호화하려면 데이터가 특정 스키마로 복호화하길 기대함.
    • 이 스키마를 읽기 스키마(reader’s schema) 라고 함.
    • 애플리케이션 코드는 이 스키마에 의존함.
  • 아브로의 핵심 아이디어는 쓰기 스키마와 읽기 스키마가 동일하지 않아도 됨.
    • 단지 호환 가능하면 됨.
    • ex) 쓰기 스키마와 읽기 스키마는 필드 순서가 달라도 상관 없음.
      • 스키마 해석에서 이름으로 필드를 일치시키기 때문
    • 데이터를 읽는 코드가 읽기 스키마에는 없고 쓰기 스키마에 존재하면 이 필드는 무시함.
    • 데이터를 읽는 코드가 쓰기 스키마에 없는 필드를 읽기를 기대하면, 읽기 스키마에 선언된 기본값으로 채움.

스키마 발전 규칙

  • 아브로는 상, 하위 호환성은 다음을 의미함.
    • 상위 호환성 : 새로운 버전의 쓰기 스키마와 예전 버전의 읽기 스키마를 가질 수 있음.
    • 하위 호환성 : 새로운 버전의 읽기 스키마와 예전 버전의 쓰기 스키마를 가질 수 있음.
  • 호환성을 유지하기 위해, 기본값이 있는 필드만 추가하거나 삭제할 수 있음.
    • 기본값이 없는 필드를 추가하면 하위 호환성이 깨짐.
    • 기본값이 없는 필드를 삭제하면 상위 호환성이 깨짐.
  • 아브로는, 필드에 널을 기본 값으로 허용하지 않음.
    • 필드에 널을 허용하려면 유니온 타입(union type)을 사용해야 함.
  • 아브로는 타입을 변환할 수 있으므로 필드의 데이터타입 변경이 가능함.
    • 필드 이름 변경도 가능하지만 조금 까다로움.
      • 읽기 스키마는 필드 이름의 별칭을 포함할 수 있음
      • 따라서, 별칭에 예전 쓰기 스키마 필드 이름을 매치할 수 있음.
        • 즉, 필드 이름 변경은 하휘 호환성은 있지만 상위 호환성은 없다.

그러면 쓰기 스키마는 무엇인가?

  • 읽기는 특정 데이터를 부호화한 쓰기 스키마를 어떻게 알 수 있는가?
    • 모든 레코드에 전체 스키마를 포함할 수 없음.
      • 스키마는 부호화된 데이터보다 훨씬 클 가능성이 있기 때문임.
    • 아브로를 사용하는 상황에 따라 다름.
      • 많은 레코드가 있는 대용량 파일
        • 아브로는 모두 동일한 스키마로 부호화된 수백만 개 레코드를 포함한 큰 파일을 저장하는 용도임.
        • 이 경우, 파일의 쓰기는 파일의 시작 부분에 한 번만 쓰기 스키마를 포함시키면 됨.
        • 아브로는 이를 위해 파일 형식(객체 컨테이너 파일)을 명시함
      • 개별적으로 기록된 레코드를 가진 데이터베이스
        • 데이터베이스의 다양항 레코드가 모두 동일한 스키마를 가진다고 가정할 수 없음. (다양한 쓰기 스키마를 사용해 서로 다른 시점에 쓰여질 수 있기 때문)
          • 간단한 해결책 → 모든 부호화된 레코드의 시작 부분에 버전 번호를 포함하고 데이터베이스에 스키마 버전 목록을 유지함.
      • 네트워크 연결을 통해 레코드 보내기
        • 두 프로세스가 양방향 네트워크 연결을 통해 통신할 때, 연결 설정에서 스키마 버전을 합의 할 수 있음.
        • 아브로 RPC 프로토콜이 이처럼 동작함.

동적 생성 스키마

  • 프로토콜 버퍼와 스리프트에 비해 아브로 방식은 한 가지 장점이 있음.
    • 스키마에 태그 번호가 포함되어 있지 않은 점이다.
    • 이는, 아브로가 동적 생성 스키마에 더 친숙함.
      • 데이터베이스 스키마가 변경되면, 갱신된 데이터베이스 스키마로부터 새로운 아브로 스키마를 생성하고 새로운 아브로 스키마로 데이터를 내보냄.
      • 데이터를 내보내는 과정은 스키마 변경에 신경쓸 필요가 없음.
        • 새로운 데이터 파일을 읽는 사람은 레코드 필드가 변경된 사실을 알게 되지만, 필드는 이름으로 식별되기 때문에 갱신된 쓰기 스키마는 여전히 이전 읽기 스키마와 매치 가능함. → 동적 생성 스키마가 가능
      • 이에 반해, 스리프트와 프로토콜 버퍼는 필드 태그를 수동으로 할당해야만 함.
        • 데이터베이스 스키마가 변경될 때마다 관리자는 데이터베이스 칼럼 이름과 필드 태그의 매핑을 수동으로 갱신해야 함. → 동적 생성 스키마가 불가능함.

코드 생성과 동적 타입 언어

  • 스리프트와 프로토콜 버퍼는 코드 생성에 의존함.
    • 스키마 정의 후, 선택한 프로그래밍 언어로 스키마를 구현한 코드를 생성할 수 있음.
  • 아브로는 동적 생성 스키마의 경우, 코드 생성은 데이터를 가져오는데 불필요한 장애물임.
  • 아브로는 정적 타입 프로그래밍 언어를 위해 코드 생성을 선택적으로 제공함.
    • 하지만 코드 생성 없이도 사용할 수 있음.
    • 쓰기 스키마를 포함한 객체 컨테이너 파일이 있다면 아브로 라이브러리를 사용해 간단히 열어 JSON 파일을 보는것 같이 데이터를 볼 수 있음.
      • 이 파일은 필요한 메타 데이터를 모두 포함하기에 자기 기술(self-describing)적임.

스키마의 장점

  • 프로토콜 버퍼, 스리프트, 아브로는 스키마를 사용해 이진 부호화 형식을 기술함.
    • 이 스키마 언어는 XML, JSON 스키마보다 훨씬 간단하며, 더 자세한 유효성 검사 규칙을 지원함.
  • 이러한 부호화 기반 아이디어는 결코 새로운 개념이 아님.
    • 1984년에 처음으로 표준화된 스키마 정의 언어인 ASN.1과 공통점이 많음.
  • 많은 데이터 시스템이 이진 부호화를 독자적으로 구현하기도 함.
    • ex) 대부분의 관계형 데이터베이스에는 질의를 데이터베이스로 보내고 응답을 받을 수 있는 네트워크 프로토콜이 있음.
    • 이 프로토콜은 일반적으로 특정 데이터베이스에 특화되며 데이터베이스 벤더는 데이터베이스 네트워크 프로토콜로부터 응답을 인메모리 데이터 구조로 복호화하는 드라이버(ex: ODBC, JDBC API)를 제공함.

데이터플로 모드

  • 매우 추상적인 개념으로서 하나의 프로세스에서 다른 프로세스로 데이터를 전달하는 방법은 아주 많음.
  • 누가 데이터를 부호화하고 복호화할지에 대한, 보편적인 방법을 살펴본다.
    • 데이터베이스를 통해
    • 서비스 호출을 통해
    • 비동기 메시치 전달을 통해

데이터베이스를 통한 데이터플로

  • 데이터베이스에 접근하는 단일 프로세스가 있다고 하자.
    • 읽기는 단순히 동일 프로세스의 최신 버전임.
      • 이 경우, 데이터베이스에 뭔가 저장하는 일을 미래의 자신에게 메시지를 보내는 일처럼 생각할 수 있음.
      • 이전에 기록한 내용을 미래의 자신이 복호화해야 하므로, 하휘 호환성은 분명히 필요함.
  • 일반적으로 동시에 다양한 프로세스가 데이터베이스를 접근하는 일은 흔함.
    • 이 프로세스는 다양한 애플리케이션이나 서비스일 수 있음.
    • 단순히, 동일한 서비스의 여러 인스턴스일 수도 있음. (서비스의 확장성, 병렬수행 등)
      • 데이터베이스 내 값이 새로운 버전의 코드로 기록된 다음, 현재 수행 중인 예전 버전의 코드로 그 값을 읽을 가능성이 있음. → 데이터베이스에서 상위 호환성도 필요함.
    • 만약, 레코드 스키마에 필드를 추가하고, 새로운 코드가 새로운 필드를 위한 값을 데이터베이스에 기록한다고 하자.
      • 이어서 예전 버전의 코드가 레코드를 읽어서 값을 갱신한 후, 갱신한 값을 다시 기록할 때, 우리가 기대하는 동작은, 예전 코드가 새로운 필드를 해석할 수 없더라도 그 필드 값은 그대로 유지하길 바란다.
      • 하지만, 애플리케이션에서 데이터베이스 값을 모델 객체로 복호화하고, 이 모델 객체를 다시 재부호화 하는 과정에서 필드가 유실될 수 있음.

다양한 시점에 기록된 다양한 값

  • 애플리케이션의 새로운 버전에 대한 배포는 몇 분 내로 대체할 수 있음.
  • 하지만, 데이터베이스 내용은 명시적으로 다시 기록되지 않는 한, 원래의 부호화 상태 그대로 있음.
    • 이 상황을 데이터가 코드보다 더 오래 산다(data outlives code) 라고 함.
  • 데이터를 새로운 스키마로 다시 기록(마이그레이션)하는 작업은 가능함.
    • 하지만, 대용량 데이터셋 대상으로는 값비싼 작업이므로, 대부분의 데이터베이스에서 가능하면 이런 상황을 피한다.
    • 대부분의 관계형 데이터베이스는 기존 데이터를 다시 기록하지 않고, 널을 기본값으로 갖는 새로운 칼럼을 추가하는 간단한 스키마 변경을 허용함.
  • 스키마 발전은 기본 저장소가 여러 가지 버전의 스키마로 부호화된 레코드를 포함해도 전체 데이터베이스가 단일 스키마로 부호화된 것처럼 보이게 함.

보관 저장소

  • 백업 목적이나, 데이터 웨어하우스로 적재하기 위해, 데이터베이스의 스냅샷을 수시로 만든다고 가정하자.
    • 이 경우 데이터 덤프는 보통 최신 스키마를 사용하여 부호화함. (다양한 시점의 스키마 버전이 섞여있어도..)
    • 데이터 덤프는 한 번에 기록하고, 이후에는 변하지 않으므로 아브로 객체 컨테이너 파일과 같은 형식이 적합함.

댓글

Designed by JB FACTORY