부호화와 발전
- 4.1 데이터 부호화 형식
- 4.2 데이터플로 모드
시스템은 변하고, 코드는 바뀌고, 스키마는 진화해. 그런데 새 코드와 옛 코드가 동시에 존재하는 시기가 반드시 생기잖아 — 순회식 업그레이드를 하든, 클라이언트가 업데이트를 안 하든. 이 공존을 가능하게 하는 건 결국 부호화(encoding) 형식이 호환성을 얼마나 잘 지원하느냐에 달려 있어.
양방향 호환성이 필요해. 하위 호환성(새 코드가 옛 데이터를 읽는 것)은 비교적 쉬운데, 상위 호환성(옛 코드가 새 데이터를 읽는 것)은 까다로워 — 모르는 필드를 무시할 수 있어야 하니까. Java Serializable이나 Python pickle 같은 언어 내장 직렬화는 이런 호환성 체계가 없고, 언어 종속에 보안 문제까지 있어서 쓰면 안 돼. JSON/XML은 널리 쓰이지만 수 부호화의 모호성이나 이진 데이터 미지원 같은 미묘한 문제가 있지.
진짜 답은 스키마 기반 이진 부호화야 — 프로토콜 버퍼, 스리프트, 아브로 같은 것들. 프로토콜 버퍼와 스리프트는 각 필드에 필드 태그(숫자)를 부여하고, 부호화된 데이터에 필드 이름 대신 태그 번호만 넣어. 크기가 줄고, 태그만 안 바꾸면 호환성이 유지돼. 아브로는 아예 태그 번호도 없이 쓰기 스키마와 읽기 스키마를 분리해서, 필드 이름 매칭으로 호환을 처리하지. DB 스키마에서 아브로 스키마를 자동 생성할 수 있어서 동적으로 생성된 스키마에 특히 강해.
데이터가 흐르는 경로도 중요해. DB를 통한 데이터플로에서는 옛 코드가 새 필드를 가진 레코드를 읽고 다시 쓸 때 그 필드를 날려먹지 않도록 주의해야 하고. 서비스를 통한 데이터플로에서 RPC는 원격 호출을 로컬처럼 보이게 하려는데, 이 투명성은 환상이야 — 네트워크는 예측 불가능하고, 타임아웃이 있고, 멱등성 문제가 있거든. 메시지 브로커를 통한 비동기 전달이 이런 결합을 줄여줘. 수신자가 느려도 버퍼 역할을 하고, 하나의 메시지를 여러 수신자에게 보낼 수 있고, 송신자와 수신자를 시간적으로 분리하니까.
정리
4장 읽고 기억할 거:
- 부호화 형식이 호환성을 결정한다. 프로토콜 버퍼, 스리프트, 아브로 같은 스키마 기반 이진 부호화가 효율적이면서 호환성도 체계적으로 관리한다
- RPC의 투명성은 환상이다. 네트워크 호출은 로컬 호출과 근본적으로 다르고, 숨기려 하면 문제가 생긴다
- 메시지 브로커는 서비스 간 결합을 줄인다. 비동기 메시지 전달이 시스템의 유연성과 내결함성을 높인다