저장·통신 형식을 바꿀 때는 읽기를 먼저 배포하고, 쓰기는 다음 배포에서
옛 클라이언트와 새 서버, 새 클라이언트와 옛 데이터가 함께 도는 시간이 반드시 있다. 두 형식을 다 읽게 먼저 배포하고, 새 형식 쓰기는 다음 배포에서 켠다.
저장 형식이나 메시지 형식을 바꾼 배포 직후, 아직 새로고침하지 않은 탭이 새 형식의 데이터를 받아 깨지거나, 거꾸로 옛 탭이 옛 형식으로 덮어써 새 데이터를 망가뜨린다.
배포는 한순간에 끝나지 않는다. 열려 있던 탭은 옛 코드로 계속 돌고, 서버도 하나씩 교체되는 동안 옛 버전과 새 버전이 섞여 돈다. 이 시간 동안 양쪽이 서로의 형식을 읽을 수 있어야 한다.
배포를 둘로 나눈다.
- 배포 1: 새 형식과 옛 형식을 모두 읽는다. 쓰기는 옛 형식 그대로다. 기존 데이터를 고칠 때도 원래 형식을 지킨다.
- 기다림: 옛 클라이언트가 사라질 때까지 기다린다. 새 버전 안내로 새로고침을 권하면 빨라진다.
- 배포 2: 새 형식으로 쓴다. 기능 플래그 하나로 켜서 문제가 생기면 바로 끈다.
- (선택) 배포 3: 옛 형식 읽기를 없앤다.
// 배포 1: 두 형식을 다 읽는다
function readPoints(value: string | number[]): number[] {
return typeof value === 'string' ? decodeBinary(value) : value;
}
// 배포 2: 플래그로 새 형식 쓰기를 켠다
function writePoints(points: number[]): string | number[] {
return flags.enabled('points-binary') ? encodeBinary(points) : points;
}
DB 스키마의 expand/contract와 같은 생각이다. 넓히는 변경과 좁히는 변경을 같은 배포에 넣지 않는다.