무중단 배포(Zero Downtime Deployment)의 모든 것: 서비스 운영의 필수 전략

실제 어플리케이션을 운용시에는 배포를 할때면 많은 긴장을 해야합니다..
만약 다운되면 어떡하지 이런생각이 들지만 이를 그나마 방지해주는 장치 중 하나인 무중단배포에 대해 설명하려합니다.

1. 무중단 배포란 무엇일까?

무중단 배포(Zero Downtime Deployment)란 이름 그대로 사용자의 서비스 이용에 중단이나 지연을 발생시키지 않으면서 애플리케이션의 새로운 버전을 서버에 배포하는 기술 및 전략을 의미합니다.

과거에는 새로운 코드를 반영하기 위해 모든 서버를 일시적으로 내리고(Shut down) 업데이트를 진행한 뒤 다시 올리는(Start up) 방식, 즉 Stop & Start 방식을 사용했습니다. 이 과정에서 필연적으로 수 초에서 수 분 동안 서비스에 접속할 수 없는 다운타임(Downtime)이 발생했습니다.

● 전통적인 배포 방식의 치명적인 문제점 (다운타임)

과거의 배포 방식인 Stop & Start는 다음과 같은 절차를 따릅니다.

  1. Stop: 모든 트래픽을 차단하고 기존 버전의 서버를 종료합니다.
  2. Update: 코드를 업데이트하고 빌드합니다.
  3. Start: 새로운 버전의 서버를 다시 시작합니다.

이 과정에서 발생하는 서비스 이용 불가 시간을 다운타임(Downtime)이라고 합니다. 특히,
서버 시작 시간(Startup Time)이 긴 대규모 모놀리식(Monolithic) 애플리케이션의 경우 다운타임은 수 분에 달할 수 있으며, 이는 치명적인 사용자 이탈과 비즈니스 손실로 이어집니다.

하지만 오늘날처럼 24시간 365일 실시간 연결이 중요하고 사용자의 이탈이 쉬운 환경에서는, 잠시라도 서비스가 멈추는 것은 심각한 비즈니스 손실로 이어질 수 있습니다. 무중단 배포는 이러한 문제를 해결하기 위해 고안된 핵심 운영 기술입니다.

반응형

2. 무중단 배포의 필요성

무중단 배포가 현대 서비스 운영의 필수 전략으로 자리 잡은 이유는 다음과 같습니다.

  •  사용자 경험(User Experience, UX) 극대화: 가장 중요한 이유입니다. 서비스 중단은 사용자에게 불편함과 불만을 주며, 브랜드 신뢰도를 하락시킵니다. 무중단 배포는 사용자가 업데이트 사실조차 인지하지 못하도록 하여 끊김 없는(Seamless) 서비스 경험을 제공합니다.
  •  비즈니스 손실 최소화: 이커머스, 금융, 게임 등 실시간 거래나 활동이 중요한 서비스에서 다운타임은 곧바로 매출 손실로 이어집니다. 서비스 중단 시간을 '0'에 가깝게 만들어서 기회 비용 손실을 막을 수 있습니다.
  •  개발 속도 및 빈도 증가: 배포에 대한 부담이 줄어들면 개발팀은 더 빠르고 자주 코드를 업데이트하고 개선할 수 있습니다. 이는 애자일(Agile) 개발 문화를 가능하게 하고, 시장 변화에 더 민첩하게 대응할 수 있게 합니다.
  • 안정성 및 롤백(Rollback) 용이성 확보: 배포 과정 중 문제가 발생했을 때, 무중단 배포 방식은 기존 버전이 여전히 활성화되어 있기 때문에 롤백이 매우 용이합니다. 이는 서비스 안정성을 크게 향상시킵니다.

3.무중단 배포의 핵심 원칙

무중단 배포의 핵심은 "현재 구동 중인 서비스 인스턴스를 유지하면서 동시에 새로운 버전의 인스턴스를 올리는 것"입니다. 이를 위해 필수적으로 활용되는 요소는 다음과 같습니다.

  • 로드 밸런서(Load Balancer) 혹은 프록시 서버 등: 사용자 트래픽을 여러 서버 인스턴스에 분산시켜주는 장치. 배포 중에도 트래픽을 구 버전과 신 버전 인스턴스 간에 유연하게 전환하는 핵심 역할을 수행합니다.
  • 다중 인스턴스 환경: 최소 두 개 이상의 서버 인스턴스(혹은 그룹)가 동시에 운영되어야 트래픽 전환이 가능합니다.

트래픽을 전환 시킬만한 무언가가 있어야하며 또 전환된 트래픽을 받을만한 다른 인스턴스가 있어야합니다.
프로세스는 보통 아래와 같습니다.

무중단배포이미지

무중단 배포 프로세스

  1. 구 버전 유지: 새로운 버전을 배포하는 동안에도 구 버전의 애플리케이션 인스턴스가 계속 트래픽을 처리합니다.
  2. 신 버전 준비: 새로운 버전의 인스턴스를 기존 서비스에 영향을 주지 않는 별도의 공간에 준비합니다.
  3. 점진적 전환: 로드 밸런서 혹은 프록시 서버등을 사용하여 트래픽을 구 버전에서 신 버전으로 안전하고 점진적으로 이동시킵니다.

위 방식을 통해서 사용자들은 이게 진짜 업데이트가 되는중인지 아닌지 서비스가 끊김없이 사용되므로 눈치채지 못하게 됩니다.

4. 무중단 배포의 가장 큰 난제: 데이터베이스 마이그레이션

애플리케이션 코드는 무중단으로 배포할 수 있지만, 애플리케이션이 사용하는 데이터베이스(DB) 스키마가 변경되어야 할 경우 문제가 발생합니다.

예를 들어서 신규 버전(V2)의 애플리케이션이 'Users' 테이블에 'email'이라는 새로운 컬럼을 요구한다고 가정해 봅시다.

DB 마이그레이션 중의 동시성 문제

  • V2 배포 과정에서 DB 스키마에 'email' 컬럼을 필수(NOT NULL)로 추가했습니다.
  • 트래픽 전환 기간 동안 V1 인스턴스가 사용자 정보를 업데이트(UPDATE)하거나 새로운 사용자 정보(INSERT)를 DB에 저장합니다.
  • V1 코드는 'email' 컬럼에 대한 정보를 전혀 포함하지 않고 쓰기 쿼리를 실행합니다.
  • DB는 V2가 설정한 필수(NOT NULL) 제약 조건을 확인합니다.
  • V1이 제공하지 않은 'email' 컬럼에 NULL 값이 들어가려고 시도하여, DB에서 NOT NULL Constraint Violation 에러가 발생합니다

즉 쉽게 말해서 V1코드는 email이 없지만 V2는 email이 있을때 이미 트래픽에선 V1을 기반으로 요청을 했지만 db에는 email 컬럼이 이미 생겨버리면 V1 기반의 요청은 전부다 오류가 발생하게 됩니다.

이 문제를 해결하기 위해 배포 전략은 단순한 코드 배포를 넘어 DB 스키마 변경 시의 호환성을 확보하는 방식으로 설계되어야 합니다.

DB 마이그레이션을 위한 핵심 전략: Two-Phase Approach

일반적으로는 V1과 V2 코드가 모두 동작할 수 있도록 DB 변경을 '후방 호환성(Backward Compatibility)'을 유지하며 단계적으로 수행합니다.
예를 들어, V2 배포 후 일정 기간 V1의 트래픽이 완전히 끊긴 후에 불필요해진 구 컬럼을 삭제하는 방식입니다 이러한 문제를 해결하기 위해 무중단 배포 시 DB 마이그레이션은 항상 다단계(Two-Phase)로 진행되어야 합니다.

단계 목표 애플리케이션 상태 DB 스키마 상태
Phase 1: 쓰기 호환성 확보 V1과 V2가 모두 새로운 컬럼에 쓸 수 있도록 준비합니다. V1 배포 (V1 코드에 새 컬럼에 대한 쓰기 로직 추가) 컬럼 추가 (NULL 허용)
Phase 2: 컬럼 필수화 및 V1 제거 V2만 남기고 V1을 완전히 제거합니다. V2 배포 (V2가 트래픽을 모두 받음) 컬럼 제약 조건 변경 (NOT NULL)

이처럼 무중단 DB 마이그레이션은 데이터베이스와 애플리케이션 코드를 동시에, 하지만 단계적으로 변경하는 세심한 접근 방식이 필요합니다.

다음에는 무중단 배포의 종류를 한번 알아보겠습니다.

반응형