Chapter 4

부호화와 발전

  • 4.1 데이터 부호화 형식
  • 4.2 데이터플로 모드

시스템은 변하고, 코드는 바뀌고, 스키마는 진화해. 그런데 새 코드와 옛 코드가 동시에 존재하는 시기가 반드시 생기잖아 — 순회식 업그레이드를 하든, 클라이언트가 업데이트를 안 하든. 이 공존을 가능하게 하는 건 결국 부호화(encoding) 형식이 호환성을 얼마나 잘 지원하느냐에 달려 있어.

양방향 호환성이 필요해. 하위 호환성(새 코드가 옛 데이터를 읽는 것)은 비교적 쉬운데, 상위 호환성(옛 코드가 새 데이터를 읽는 것)은 까다로워 — 모르는 필드를 무시할 수 있어야 하니까. Java Serializable이나 Python pickle 같은 언어 내장 직렬화는 이런 호환성 체계가 없고, 언어 종속에 보안 문제까지 있어서 쓰면 안 돼. JSON/XML은 널리 쓰이지만 수 부호화의 모호성이나 이진 데이터 미지원 같은 미묘한 문제가 있지.

진짜 답은 스키마 기반 이진 부호화야 — 프로토콜 버퍼, 스리프트, 아브로 같은 것들. 프로토콜 버퍼와 스리프트는 각 필드에 필드 태그(숫자)를 부여하고, 부호화된 데이터에 필드 이름 대신 태그 번호만 넣어. 크기가 줄고, 태그만 안 바꾸면 호환성이 유지돼. 아브로는 아예 태그 번호도 없이 쓰기 스키마읽기 스키마를 분리해서, 필드 이름 매칭으로 호환을 처리하지. DB 스키마에서 아브로 스키마를 자동 생성할 수 있어서 동적으로 생성된 스키마에 특히 강해.

데이터가 흐르는 경로도 중요해. DB를 통한 데이터플로에서는 옛 코드가 새 필드를 가진 레코드를 읽고 다시 쓸 때 그 필드를 날려먹지 않도록 주의해야 하고. 서비스를 통한 데이터플로에서 RPC는 원격 호출을 로컬처럼 보이게 하려는데, 이 투명성은 환상이야 — 네트워크는 예측 불가능하고, 타임아웃이 있고, 멱등성 문제가 있거든. 메시지 브로커를 통한 비동기 전달이 이런 결합을 줄여줘. 수신자가 느려도 버퍼 역할을 하고, 하나의 메시지를 여러 수신자에게 보낼 수 있고, 송신자와 수신자를 시간적으로 분리하니까.


정리

4장 읽고 기억할 거:

  1. 부호화 형식이 호환성을 결정한다. 프로토콜 버퍼, 스리프트, 아브로 같은 스키마 기반 이진 부호화가 효율적이면서 호환성도 체계적으로 관리한다
  2. RPC의 투명성은 환상이다. 네트워크 호출은 로컬 호출과 근본적으로 다르고, 숨기려 하면 문제가 생긴다
  3. 메시지 브로커는 서비스 간 결합을 줄인다. 비동기 메시지 전달이 시스템의 유연성과 내결함성을 높인다