MMeshOps
데이터베이스 마이그레이션 실전: 다운타임 없는 안전한 DB 변경
8예상 10중급

앱과 DB의 엇박자 막기: 호환성 확보 타이밍

API 서버 배포와 DB 스키마 업데이트 시점에 구버전 앱과 신버전 DB가 충돌하지 않도록 타이밍을 맞추는 법을 배웁니다.

서비스가 운영 중일 때 우리는 코드(앱)와 데이터베이스(DB)라는 두 개의 톱니바퀴를 함께 교체해야 합니다. 문제는 이 두 개를 눈 깜짝할 사이에 0.1초의 오차도 없이 동시에 교체할 방법은 없다는 것입니다. 앱이 먼저 배포될 수도 있고, DB가 먼저 변경될 수도 있습니다. 이 미세한 틈새에서 발생하는 '엇박자'를 어떻게 막을 수 있는지 살펴봅시다.

배포 시점의 틈새: 구버전과 신버전의 동거

현대의 클라우드 환경에서는 보통 여러 대의 서버가 동시에 동작합니다. 새로운 버전의 앱을 배포하면, 한 번에 모든 서버가 짠! 하고 바뀌는 것이 아니라, 1번 서버가 업데이트되는 동안 2번, 3번 서버는 여전히 구버전 앱으로 요청을 받고 있습니다.

이런 상황에서 데이터베이스 스키마가 변경된다고 상상해봅시다.

  • 상황 A: DB 마이그레이션을 먼저 실행하여 새로운 컬럼 `phone_number`를 없앴습니다. 그런데 아직 배포가 덜 끝난 구버전 앱은 여전히 `phone_number` 컬럼에서 데이터를 읽으려 시도합니다. 바로 에러가 발생합니다.
  • 상황 B: 앱을 먼저 배포하여 신버전 앱이 돌아가기 시작했습니다. 신버전 앱은 방금 추가한 `nickname` 컬럼에 데이터를 쓰려고 합니다. 하지만 아직 DB 마이그레이션을 실행하지 않아서 컬럼이 없습니다. 역시 에러가 발생합니다.

이처럼 앱 배포와 DB 변경 사이에는 필연적으로 시간 차이가 존재하며, 이 타이밍을 잘못 맞추면 사용자는 장애를 겪게 됩니다.

호환성(Compatibility)의 법칙

이 엇박자를 극복하는 유일한 방법은 '하위 호환성(Backward Compatibility)'을 지키는 것입니다.

핵심 원칙은 매우 간단합니다. "새로운 DB 스키마는 구버전 앱과 호환되어야 하고, 새로운 앱은 구버전 DB와 호환되어서는 안 된다." (정확히는 배포 순서에 따라 양방향 호환을 일시적으로 유지하는 것입니다.)

안전한 배포를 위한 호환성 타이밍 규칙

  1. 1무언가(테이블, 컬럼)를 추가할 때는 DB 마이그레이션을 먼저 실행하고, 앱을 나중에 배포한다.
  2. 2무언가(테이블, 컬럼)를 삭제할 때는 앱을 먼저 배포하여 참조를 없애고, DB 마이그레이션은 충분히 나중에 실행한다.

실전 타이밍 시나리오

위의 규칙을 적용하여 컬럼을 추가하고 삭제하는 상황을 구체적으로 살펴보겠습니다.

1. 컬럼을 추가할 때의 타이밍 (DB 먼저)

새로운 컬럼이 필요한 기능이 개발되었습니다.

  1. DB 마이그레이션 먼저 실행: 빈 컬럼이 DB에 추가됩니다.
  2. 이 시점에 구버전 앱은 새 컬럼의 존재를 모르지만, 기존대로 동작하므로 아무 문제가 없습니다.
  3. 신버전 앱 배포 시작: 서버들이 하나둘씩 새 컬럼을 사용하기 시작합니다.
  4. 모든 배포가 끝나면 완료!

2. 컬럼을 삭제할 때의 타이밍 (앱 배포 먼저)

더 이상 안 쓰는 컬럼을 삭제하려고 합니다.

  1. 코드에서 컬럼 참조 제거: 신버전 앱의 코드에서 해당 컬럼을 읽거나 쓰는 로직을 모두 지웁니다.
  2. 신버전 앱 배포 시작: 점진적으로 배포됩니다.
  3. 배포되는 동안, 아직 살아있는 구버전 앱은 컬럼을 계속 사용하지만 DB에는 아직 컬럼이 살아있으니 에러가 없습니다.
  4. 신버전 앱 배포가 완전히 끝납니다. 이제 그 어떤 서버도 해당 컬럼을 찾지 않습니다.
  5. 마지막으로 DB 마이그레이션 실행: 안심하고 `DROP COLUMN`을 실행하여 컬럼을 완전히 날립니다.

분리 배포의 미학

위의 규칙을 보면 알 수 있듯, 복잡한 스키마 변경은 단 한 번의 배포로 끝낼 수 없습니다. 코드를 고치고 배포하는 사이클과 DB 마이그레이션을 실행하는 사이클을 분리하여 여러 단계에 걸쳐 점진적으로 배포해야 다운타임 없는 완벽한 무중단 마이그레이션이 완성됩니다.

개념 퀴즈

퀴즈 답을 맞춰야 학습 완료가 됩니다.

운영 중인 서비스에서 불필요해진 컬럼을 완전히 삭제하려고 합니다. 다운타임(장애)을 막기 위한 가장 올바른 순서는 무엇인가요?

3줄 요약

  1. 1서버 여러 대가 배포되는 시간 동안 구버전 앱과 신버전 DB가 충돌하는 엇박자가 발생할 수 있습니다.
  2. 2컬럼을 추가할 때는 DB 마이그레이션을 먼저 하고, 앱을 나중에 배포해야 호환성이 유지됩니다.
  3. 3컬럼을 삭제할 때는 앱 코드에서 참조를 먼저 지우고 배포한 뒤, 맨 마지막에 DB를 마이그레이션해야 합니다.