AWS 기술 블로그

AWS 에 구축하는 클라우드 디자인 패턴 시리즈 3부: 마이그레이션

이전의 블로그 게시물에서 안정성, 연결성, 그리고 조합에 관련된 주제로, AWS에서 구축하는 클라우드 디자인 패턴들을 살펴 보았습니다.

좋은 디자인 및 구현 방법은 클라우드에서 운영하는 애플리케이션과 서비스의 품질 뿐만 아니라 비용 부분에서도 굉장히 많은 영향을 끼칩니다. 그 과정에 관리 및 배포 방법이 간단한 유지 관리 용이성, 구성 요소 및 하위 시스템이 다른 애플리케이션과 다른 시나리오에 사용될 수 있는 재사용 가능성 등의 요소도 함께 고려가 되어야 합니다.

이번 블로그에서는 클라우드 환경에 마이크로서비스 아키텍처로 마이그레이션 하는 과정에서 유용하게 사용할수 있는 교살자 무화과 패턴 (Strangler Fig pattern)손상 방지 계층 패턴 (Anti-Corruption Layer pattern)을 소개합니다. 그리고, 각 패턴 별로 관련된 문제, 고려 사항, AWS에 기반한 아키텍처 등에 대해서 자세하게 설명합니다.

(1) 손상 방지 계층 패턴 (Anti-Corruption Layer pattern)

디자인 패턴 개념

손상 방지 계층 패턴 (ACL)은 2003년 Eric Evans의 Domain-Driven Design 방법론에서 처음 소개된 디자인 패턴입니다. 이는 동일한 의미 체계를 공유하지 않는 시스템 간에 상호 작용을 관리하고 중재하는 계층 역할을 통하여, 시스템의 변경을 최소화하기 위한 디자인 패턴입니다. 최신 애플리케이션의 “손상”을 최소화 하기 위함에 초점을 두게 되고, 다음과 같은 이유로 필요합니다.

  • 모놀리식 애플리케이션과 마이크로서비스간의 통신 체계를 변환
  • 기존 시스템의 종속성으로 인한 디자인 제한을 최소화
  • 마이그레이션의 위험과 비즈니스 중단 가능성을 최소화

적용 대상 및 고려 사항

주로 신규로 디자인하는 애플리케이션이 기존 시스템의 종속성 때문에 제한되지 않도록 하기 위해, 신규 애플리케이션과 기존 애플리케이션 사이에 중재 계층을 추가하여 영향도를 최소화 하기 위함이며, 다음과 같은 상황에 적용할 수 있습니다.

  • 기존의 모놀리식 애플리케이션과 마이그레이션된 마이크로서비스는 여전히 통신이 가능해야 하며, 마이그레이션된 서비스 도메인 모델과 의미가 원래의 기능과 다른 경우
  • 다른 의미 체계를 가진 두 시스템이 통신을 해야 하지만, 이를 위해 애플리케이션을 수정하는 것이 실용적이지 않은 경우
  • 영향은 최소화하면서 서로 다른 시스템 간의 통신을, 빠르고 단순화된 접근 방식으로 수정이 필요한 경우
  • 애플리케이션이 외부 시스템과 통신을 해야 하는 경우
  • 공유 객체로 설계하여 호출을 여러 서비스 또는 서비스별 클래스로 변환이 필요한 경우

손상 방지 계층 패턴을 구현할 때 다음과 같은 사항에 대한 고려가 필요합니다.

  • 운영 오버헤드: 손상 방지 계층 패턴은 운영과 유지 관리에 추가적인 노력이 필요합니다. 예를 들어서 모니터링 및 알림 도구, 릴리스 프로세스, CI(Continuous Integration)/CD(Continuous Delivery) 와 통합하는 작업도 같이 진행이 되어야 합니다.
  • 단일 장애 지점: 손상 방지 계층 패턴에 장애가 발생하면 대상 서비스에 연결할 수 없게 되어 단일 장애 지점이 될 가능성이 있습니다. 이를 위해 백오프를 활용한 재시도 (Retry with Backoff) 패턴회로 차단기 (Circuit Breaker) 패턴 적용에 대한 고민이 필요합니다.
  • 기술 부채: 임시 솔루션인지 또는 장기 솔루션인지 고려가 필요합니다. 즉 마이그레이션된 이후에, 해당 계층의 사용을 중지하거나 또는 영구적으로 사용할지에 대한 여부를 결정해야 합니다.
  • 응답 시간: 추가적인 계층을 통한 통신이기 때문에 시스템 간의 호출이 지연될 수 있습니다.
  • 확장성 제한: 확장성에 대한 병목 현상이 발생 할 수 있어서, 손상 방지 계층의 크기를 조정하는 방식에 대한 고려가 필요 합니다.
  • 복잡도 증가: 새로운 계층을 통해 통신이 이루어지므로 시스템의 복잡도가 증가 합니다.

하이 레벨 아키텍처

모놀리식에서 마이그레이션되는 서비스 전용 클래스로 구현하거나, 독립 서비스로 구현하는 방식으로 손상 방지 계층 패턴을 적용 합니다.
다음과 같은 아키텍처인 모놀리식 시스템이 있다고 가정하겠습니다.


다음과 같은 절차로 손상 방지 계층 패턴을 구현합니다.

  1. ACL은 모놀리식 애플리케이션 내에서 클래스로 구현
  2. Order의 Inventory 요청을 ACL로 라우팅
  3. ACL은 마이크로서비스 Inventory Service의 의미에 맞게 변환

AWS 기반의 구현

AWS에서 손상 방지 계층 패턴을 구현할 때 사용할 수 있는 가장 대표적인 서비스는 Amazon API GatewayAWS Lambda의 조합입니다. 다른 시스템 간의 데이터 변환 및 중간 계층 역할을 수행할 수가 있고, 필요한 경우 Amazon DynamoDB와 연동하여 이력을 저장하도록 아키텍처를 확장할 수 있습니다.

다음은 AWS로 신규 애플리케이션이 마이그레이션 되었을때 손상 방지 계층 패턴을 구성한 흐름에 대한 설명 입니다.

  1. Program.cs에서 사용자 서비스 호출 (UserInMonolith.cs)
  2. Monolithic 내부에서 ACL로 라우팅 (UserServiceACL.cs)
  3. ACL은 호출을 새로운 인터페이스로 변환하고 API Gateway를 통해 마이크로서비스 호출

최종적으로 Program.cs라는 시스템에서는, 이러한 변화를 인식하지 못하기 때문에 비즈니스 중단이 줄어들고 위험이 최소화 됩니다.


(2) 교살자 무화과 패턴 (Strangler Fig pattern)

디자인 패턴 개념

교살자 무화과 패턴은 2002년 Martin Fowler의 Patterns of Enterprise Application Architecture 방법론에서 처음 소개된 디자인 패턴입니다. 이는 일반적으로 기존의 시스템을 빅뱅 형태로 한번에 마이그레이션을 하는 것을 지양하고, 특정 기능을 새로운 애플리케이션 및 서비스로 점진적으로 교체하여 시스템을 단계적으로 마이그레이션하는 디자인 패턴 입니다.

이름에서도 알 수 있듯이 교살자 무화과 패턴은 점진적인 세대교체 그리고 인수인계를 의미하고 주로 다음과 같은 이유로 필요합니다.

  • 모놀리식 애플리케이션을 마이크로서비스로 완전히 대체하는 것은 엄청난 작업이자 큰 위험
  • 기존 애플리케이션 운영 영향도를 최소화 하면서 마이그레이션
  • 애플리케이션의 규모가 커지면서 팀의 인지 부하가 증가하고 팀 소유권 경계가 불분명

다음과 같은 일반적인 3-티어 모놀리식 시스템을 교살자 무화과 패턴을 적용하여, 모놀리식 시스템을 점진적으로 마이크로서비스로 마이그레이션 합니다.

사용자 인터페이스는 기존 모놀리식 및 마이크로서비스에 모두 접속이 가능한 엔드포인트를 제공하도록 구현됩니다.


모놀리식의 모든 기능을 마이크로서비스로 마이그레이션 하게 되면, 최종적으로 사용자 인터페이스에서 기존 서비스를 해제하고 접두사(prefix)에 의해 각 마이크로서비스로 통신이 되도록 라우팅 설정을 하게 됩니다.


적용 대상 및 고려사항

주로 모놀리식 애플리케이션을 마이크로서비스 아키텍처로 점진적으로 마이그레이션 함으로써 혁신 위험과 비즈니스 중단을 줄이기 위함에 있고, 다음과 같은 상황에 적용해 볼 수 있습니다.

  • 모놀리식 애플리케이션을 마이크로서비스 아키텍처로 점진적으로 마이그레이션하고자 하는 경우
  • 모놀리식 애플리케이션의 규모와 복잡성으로 인하여 빅뱅 마이그레이션이 위험한 경우
  • 새로운 기능의 추가가 필요하지만, 전체 변환이 완료되기를 기다릴 수 없는 경우
  • 전환 과정에서 최종 사용자의 영향을 최소화 하고자 하는 경우

교살자 무화과 패턴을 구현할 때에, 다음과 같은 사항에 대한 고려가 필요합니다.

  • 불분명한 도메인: 정확한 설계를 위하여 도메인 기반 설계 기법이 필요하고, 그 과정에서 이벤트 스토밍을 활용하는 것을 권장합니다.
  • 마이크로 서비스 식별: 모놀리식 애플리케이션을 분해하기 전에 코드를 리팩토링하여, 긴밀한 결합을 사전에 방지하고 마이크로서비스 분리 작업의 난이도를 낮추는 작업이 필요합니다.
  • 프록시 계층 장애: 프록시 레이어에 장애가 발생했을 때 단일 장애 지점이 되거나 병목 현상이 발생할 수 있기 때문에 복원력(Resilience) 관점에서의 고민이 필요합니다.
    • 예) API Gateway 는 내결함성이 내장된 서버리스 서비스여서 프록시로 사용하면 위험을 완화할 수 있습니다.
  • 애플리케이션 복잡성:모놀리식 애플리케이션의 복잡성이 낮은 경우, 마이그레이션하는 대신 마이크로서비스 아키텍처에서 직접 개발하는 것이 더 효율적일 수 있습니다.
  • 다양한 서비스 패턴을 함께 고려하여 서비스 영향도와 성능 이슈를 해결 합니다.
    • 손상 방지 계층: 손상 방지 레이어를 구현하여 변경된 서비스의 영향을 최소화 합니다.
    • 서비스 상호 작용: 동기 통신에서는 시간 초과로 연결 또는 스레드 풀 소비가 발생하여 성능 문제가 발생할 수 있고, 이는 회로 차단기 (Circuit Breaker) 패턴을 적용하여 완화할 수 있습니다.
    • 데이터 집계: 데이터는 다양한 데이터베이스에 분산되므로 집계가 필요한 경우에 프론트엔드에는 AWS AppSync, 백엔드는 CQRS(Command Query Responsibility Segregation) 패턴의 적용 필요합니다.
  • 데이터 일관성: 모놀리식 및 마이크로서비스에서 데이터 저장소를 공유하는 과정에서 데이터 중복이 발생이 될 수 있기에 정합성에 대한 검증이 필요합니다.

하이 레벨 아키텍처

특정 기능을 한 번에 하나의 구성씩 새로운 서비스로 마이그레이션하고, 프록시 계층에서 마이그레이션이 완료된 마이크로서비스로 라우팅 되도록 설정합니다. 기존 모놀리식 애플리케이션이 운영이 되고 있는 동시에, 새로운 기능이 추가가 되는 방식으로 교살자 무화과 패턴을 적용 합니다.

다음과 같이 일반적인 3-티어 모놀리식 시스템이 있고 기능으로는 Inventory, Cart, Order 세 가지로 구성이 되어 있다고 가정해보겠습니다.

다음과 같은 절차로 교살자 무화과 패턴을 구현합니다.

  1. 프록시 (Proxy) 계층 추가
  2. 새 마이크로서비스로 라우팅
  3. 손상 방지 계층 추가
  4. 데이터 동기화
  5. 추가 서비스 마이그레이션
  6. 모놀리식 애플리케이션 폐기

프록시 계층을 추가하여 모든 트래픽을 우선 모놀리식 애플리케이션에 라우팅하게 설정 합니다. 프록시 계층은 API URL을 기반으로 호출이 되고 신규 마이크로서비스가 생기면 라우팅 경로를 추가합니다.

Inventory 마이크로서비스가 추가가 되면 손상 방지 계층 (ACL) 패턴을 적용하여 변경의 영향도를 최소화 합니다.

마이그레이션된 마이크로서비스에 데이터가 저장 되면 동기화 에이전트 (Synchronizing agent)를 기반으로 모놀리식 데이터베이스에 데이터를 동기화하여 기타 서비스의 데이터 정합성을 보장합니다.