멀티 리전 아키텍처 (트래픽 라우팅, 데이터 일관성, Failover)

API 시스템이 일정 규모를 넘어 글로벌 사용자에게 서비스를 제공하기 시작하면, 단일 리전 구조만으로는 성능과 안정성을 모두 만족시키기 어렵습니다. 특정 지역에 인프라가 집중되어 있는 경우, 물리적 거리로 인한 지연이 발생하며, 해당 리전에 장애가 발생하면 전체 서비스가 중단될 위험이 있습니다.

단일 리전 장애 하나로 서비스 전체가 멈추는 상황, 생각보다 흔합니다. 특정 클라우드 리전이 몇 시간 다운되는 걸 경험하면서 멀티 리전 구조를 진지하게 고민하기 시작했습니다. 물리적 거리로 인한 레이턴시(latency, 요청이 서버까지 도달하는 데 걸리는 지연 시간) 문제도 있지만, 결정적인 건 장애 하나가 전체를 삼킨다는 구조적 취약함이었습니다. 이 글은 그 고민 끝에 정리된 멀티 리전 설계의 핵심을 풀어놓은 것입니다.

트래픽 라우팅, 어디로 보낼지가 먼저

멀티 리전을 처음 도입할 때 가장 먼저 맞닥뜨리는 문제가 바로 트래픽 라우팅입니다. 서버를 여러 지역에 뿌려놓았다고 끝이 아니라, 사용자 요청을 "어떤 기준으로 어느 리전에 보낼 것인가"를 정해야 합니다. 이 결정이 성능과 안정성을 동시에 가릅니다.

가장 기본적인 방식은 지리 기반 라우팅(geo-based routing)입니다. 사용자의 IP를 기준으로 가장 가까운 리전으로 요청을 보내는 구조입니다. 서울 사용자는 아시아 리전으로, 베를린 사용자는 유럽 리전으로 자동 연결되는 방식입니다. 레이턴시 감소 효과가 명확해서 글로벌 서비스라면 거의 필수입니다.

그런데 직접 운영해보면, 지리 기반 라우팅만으로는 부족한 상황이 생깁니다. 특정 리전에 과부하가 걸리거나 장애가 발생했을 때, 지리 기준만 고집하면 오히려 망가진 리전에 트래픽을 계속 보내는 꼴이 됩니다. 이때 필요한 게 헬스 체크 기반 라우팅(health check-based routing)입니다. 각 리전의 상태를 주기적으로 확인하다가 문제가 감지되면 정상 리전으로 자동 전환합니다.

여기에 가중치 기반 라우팅(weighted routing)을 조합하면 배포 전략으로도 활용할 수 있습니다. 새 버전을 전체에 한 번에 올리는 대신, 특정 리전에 트래픽 10%만 보내서 검증하는 카나리 배포(canary deployment) 방식입니다. 솔직히 이건 처음에 복잡하게 느껴졌는데, 실제로 적용하고 나서 배포 사고가 눈에 띄게 줄었습니다.

AWS Route 53이나 Google Cloud의 Cloud DNS처럼 DNS 레벨에서 라우팅을 제어하는 도구들이 이 역할을 담당합니다. 출처: AWS Route 53 공식 문서에 따르면 헬스 체크와 지리 기반 라우팅, 가중치 기반 라우팅을 모두 조합해서 설정할 수 있습니다.

데이터 일관성, 가장 풀기 어려운 숙제

트래픽 라우팅보다 훨씬 머리 아픈 문제가 데이터 일관성입니다. 여러 리전에 같은 데이터가 존재해야 하는데, 네트워크를 통해 동기화하다 보면 어느 순간 두 리전의 데이터가 서로 다른 상태가 됩니다. 경험상 이게 단순한 기술 문제가 아니라 비즈니스 요구사항과 직결된 결정입니다.

일관성 모델은 크게 두 가지로 나뉩니다. 강한 일관성(strong consistency)은 어느 리전에서 읽어도 항상 가장 최신 데이터를 보장합니다. 반면 최종 일관성(eventual consistency)은 일시적으로 리전 간 데이터가 다를 수 있지만, 결국은 동일해진다는 모델입니다. 이름만 들으면 최종 일관성이 불안해 보이는데, 실제로는 대부분의 SNS나 커머스 서비스가 이 모델을 씁니다. 잠깐 다른 숫자가 보여도 치명적이지 않기 때문입니다.

반면 금융 거래나 재고 관리처럼 데이터 정확성이 치명적인 영역에서는 강한 일관성을 포기할 수 없습니다. 문제는 강한 일관성을 유지하려면 모든 리전이 동의할 때까지 응답을 기다려야 하므로, 레이턴시가 올라갑니다. 성능을 일부 희생하는 트레이드오프(trade-off)가 생깁니다.

데이터 복제 방식도 선택해야 합니다. 정리하면 다음 세 가지 기준으로 판단합니다.

  1. 동기 복제(synchronous replication): 모든 리전에 데이터가 기록될 때까지 완료 처리를 하지 않습니다. 안전하지만 느립니다.
  2. 비동기 복제(asynchronous replication): 메인 리전에 기록 후 즉시 응답하고, 다른 리전에는 별도로 전파합니다. 빠르지만 전파 전에 장애가 나면 일부 데이터가 유실될 수 있습니다.
  3. 하이브리드 방식: 중요한 트랜잭션은 동기, 나머지는 비동기로 처리하는 방식으로, 저는 이 방식이 현실적으로 가장 균형 잡혔다고 봅니다.

일반적으로 멀티 리전이면 비동기 복제를 쓰면 된다고 알려져 있지만, 서비스 특성을 먼저 분석하지 않으면 나중에 데이터 정합성 이슈로 큰 코 다칩니다. 초기에 이 부분을 충분히 논의하지 않아서 운영 중에 급하게 구조를 바꾼 적이 있는데, 그 비용이 생각보다 컸습니다.

Failover 전략과 운영 현실 사이에서

멀티 리전을 구축하는 가장 큰 이유 중 하나가 Failover입니다. Failover란 특정 리전이 다운됐을 때 다른 리전이 자동으로 역할을 넘겨받는 구조입니다. 이론적으로는 단순해 보이지만, 실제로 구현하면 생각보다 고려할 것이 많습니다.

자동 Failover의 핵심은 장애를 얼마나 빨리 감지하느냐입니다. 헬스 체크 주기가 너무 길면 장애 감지가 늦어지고, 그 사이에 사용자 요청이 실패합니다. 반대로 너무 짧으면 일시적인 네트워크 지연도 장애로 오인해서 불필요한 Failover가 발생합니다. 솔직히 이건 예상 밖이었습니다. 헬스 체크 인터벌 하나 잘못 설정했다가 멀쩡한 리전이 계속 교체되는 상황을 겪었습니다.

또 Failover 이후에 원래 리전이 복구됐을 때 다시 돌아오는 Failback 전략도 빠뜨리면 안 됩니다. Failback이 자동화되어 있지 않으면, 복구된 리전을 수동으로 개입해야 하고 그 과정에서 또 다른 리전 불균형이 생깁니다. 제가 초기에 Failover만 신경 쓰고 Failback을 소홀히 했다가 운영팀이 야간에 고생했던 기억이 납니다.

운영 복잡성과 비용 문제도 빠뜨릴 수 없습니다. 멀티 리전은 인프라 비용이 최소 두 배 이상 올라갑니다. 모든 서비스에 무조건 적용하는 것은 자원 낭비입니다. 출처: Google Cloud Architecture Framework에서도 서비스 중요도와 RTO(Recovery Time Objective, 허용 가능한 최대 복구 시간), RPO(Recovery Point Objective, 허용 가능한 최대 데이터 손실 범위)를 기준으로 멀티 리전 적용 범위를 결정하라고 명시하고 있습니다. 저도 이 기준을 기준 삼아, 핵심 결제 API와 인증 서비스는 멀티 리전으로, 로그 집계나 배치 작업은 단일 리전으로 분리해서 비용과 안정성의 균형을 맞췄습니다.

멀티 리전은 "도입하느냐 마느냐"보다 "어디에, 어떤 수준으로 적용하느냐"가 진짜 질문입니다. 트래픽 라우팅과 데이터 일관성 전략을 먼저 서비스 특성에 맞게 정하고, Failover와 Failback까지 자동화한 뒤에야 비로소 안정적인 글로벌 서비스가 가능합니다. 지금 단일 리전으로 운영 중이라면, RTO와 RPO부터 정의하는 것을 시작점으로 삼아보시길 권합니다. 그 숫자가 구체화되면, 어느 수준의 멀티 리전 구조가 필요한지 자연스럽게 윤곽이 잡힙니다.


관련 글

댓글

이 블로그의 인기 게시물

HTTP 메서드의 필요성 (GET과 POST, PUT과 DELETE, API 보안)

API 없는 세상의 불편함 (로그인 연동, 서비스 구조, 디지털 인프라)

API 이해하기 (서비스 연결, 시스템 협력, 디지털 구조)