Strangler fig 패턴 - AWS 권장 가이드

Strangler fig 패턴

의도

스트랭글러 피그 패턴은 모놀리식 애플리케이션을 마이크로서비스 아키텍처로 증분 마이그레이션하여 트랜스포메이션의 위험과 비즈니스 중단을 줄이는 데 도움이 됩니다.

목적

모놀리식 애플리케이션은 단일 프로세스 또는 컨테이너 내에서 대부분의 기능을 제공하도록 개발되었습니다. 코드가 긴밀하게 결합되어 있습니다. 따라서 애플리케이션 변경 시 회귀 문제를 방지하도록 철저하게 다시 테스트해야 합니다. 변경 사항은 격리된 상태로 테스트할 수 없으며, 이는 주기 시간에 영향을 미칩니다. 애플리케이션이 더 많은 기능으로 보강되면 복잡성이 증가하여 유지 관리에 더 많은 시간이 소요되고, 출시 시간이 늘어나며, 결과적으로 제품 혁신이 느려질 수 있습니다.

애플리케이션이 스케일 인하면 팀의 인지 부하가 증가하여 팀 소유권 경계가 명확해지지 않을 수 있습니다. 로드를 기반으로 개별 기능 규모를 조정하는 것은 불가능합니다. 피크 로드를 지원하도록 전체 애플리케이션 규모를 조정해야 합니다. 시스템이 노후화되면 해당 기술을 더 이상 사용하지 않아 지원 비용이 증가할 수 있습니다. 모놀리식 레거시 애플리케이션이 따르는 모범 사례는 개발 당시 사용 가능했지만 배포하도록 설계되지 않은 사례입니다.

모놀리식 애플리케이션이 마이크로서비스 아키텍처로 마이그레이션되면 더 작은 구성 요소로 분할할 수 있습니다. 이러한 구성 요소는 독립적으로 규모를 조정할 수 있고, 독립적으로 릴리스할 수 있으며, 개별 팀이 소유할 수 있습니다. 그러면 변경 사항을 현지화하고 빠르게 테스트 및 릴리스할 수 있으므로 변경 속도가 빨라집니다. 구성 요소는 느슨하게 결합되고 개별적으로 배포할 수 있으므로 변경 사항이 미치는 영향 범위는 더 작습니다.

코드를 다시 작성하거나 리팩터링하여 모놀리스를 마이크로서비스 애플리케이션으로 완전히 바꾸는 작업은 작업량이 많고 위험 부담도 큽니다. 모놀리스가 단일 작업으로 마이그레이션되는 대규모 마이그레이션은 트랜스포메이션의 위험과 비즈니스 중단을 초래합니다. 애플리케이션을 리팩터링하는 동안 새 기능을 추가하는 것은 매우 어렵거나 불가능합니다.

이 문제를 해결하는 한 가지 방법은 Martin Fowler에서 도입한 스트랭글러 피그 패턴을 사용하는 것입니다. 이 패턴에는 기능을 점진적으로 추출하고 기존 시스템을 중심으로 새 애플리케이션을 생성하여 마이크로서비스로 이전하는 작업이 포함됩니다. 모놀리스의 기능은 점진적으로 마이크로서비스로 대체되며, 애플리케이션 사용자는 새로 마이그레이션된 기능을 점진적으로 사용할 수 있습니다. 모든 기능이 새 시스템으로 이전되면 모놀리식 애플리케이션을 안전하게 폐기할 수 있습니다.

적용 가능성

다음과 같은 경우 스트랭글러 피그 패턴을 사용합니다.

  • 모놀리식 애플리케이션을 마이크로서비스 아키텍처로 점진적으로 마이그레이션하려고 합니다.

  • 모놀리스의 규모와 복잡성 때문에 대규모 마이그레이션 접근 방식은 위험합니다.

  • 비즈니스에서 새 기능을 추가하려고 하며 트랜스포메이션이 완료될 때까지 기다릴 수 없습니다.

  • 트랜스포메이션 중에 최종 사용자에 주는 영향이 최소화되어야 합니다.

문제 및 고려 사항

  • 코드베이스 액세스: 스트랭글러 피그 패턴을 구현하려면 모놀리스 애플리케이션의 코드베이스에 액세스할 수 있어야 합니다. 기능이 모놀리스에서 마이그레이션되면 사소한 코드 변경을 수행하고 모놀리스 내에 손상 방지 계층을 구현하여 새 마이크로서비스로 직접 호출을 라우팅해야 합니다. 코드베이스 액세스 없이 직접 호출을 가로챌 수 없습니다. 코드베이스 액세스는 수신 요청을 리디렉션하는 데도 중요합니다. 프록시 계층이 마이그레이션된 기능에 대한 직접 호출을 가로채 마이크로서비스로 라우팅할 수 있도록 일부 코드를 리팩터링해야 할 수도 있습니다.

  • 불명확한 도메인: 특히 도메인이 명확하지 않고 서비스 경계가 잘못될 수 있는 경우 시스템의 조기 분해에 비용이 많이 들 수 있습니다. 도메인 기반 설계(DDD)는 도메인을 이해하는 메커니즘이며, 이벤트 스토밍은 도메인 경계를 결정하는 기법입니다.

  • 마이크로서비스 식별: DDD를 마이크로서비스 식별을 위한 핵심 도구로 사용할 수 있습니다. 마이크로서비스를 식별하려면 서비스 클래스 사이에서 자연스러운 분할을 찾습니다. 많은 서비스가 자체 데이터 액세스 객체를 소유하며, 쉽게 분리됩니다. 포함하는 관련 비즈니스 로직 및 클래스에 종속성이 없거나 거의 없는 서비스가 마이크로서비스에 적합합니다. 강한 결합을 방지하기 위해 모놀리스를 분해하기 전에 코드를 리팩터링할 수 있습니다. 또한 규정 준수 요구 사항, 릴리스 케이던스, 팀의 지리적 위치, 규모 조정 요구 사항, 사용 사례 기반 기술 요구 사항, 팀의 인지 부하도 고려해야 합니다.

  • 손상 방지 계층: 마이그레이션 프로세스 중에 모놀리스 내 기능이 마이크로서비스로 마이그레이션된 기능을 직접 호출해야 하는 경우 각 직접 호출을 적절한 마이크로서비스로 라우팅하는 손상 방지 계층(ACL)을 구현해야 합니다. 모놀리스 내 기존 직접 호출자를 분리하고 변경을 방지하기 위해 ACL은 직접 호출을 최신 인터페이스로 변환하는 어댑터 또는 파사드로 작동합니다. 이에 대해서는 이 가이드 앞부분에 나온 ACL 패턴의 구현 섹션에서 자세히 설명합니다.

  • 프록시 계층 장애: 마이그레이션 중에 프록시 계층은 모놀리식 애플리케이션으로 이동하는 요청을 가로채고 이를 레거시 시스템 또는 새 시스템으로 라우팅합니다. 그러나 이 프록시 계층은 단일 장애점 또는 성능 병목 현상이 될 수 있습니다.

  • 애플리케이션 복잡성: 큰 모놀리스는 스트랭글러 피그 패턴에서 가장 많은 이점을 얻습니다. 전체 리팩터링의 복잡성이 낮은 소규모 애플리케이션의 경우 마이그레이션하는 대신 마이크로서비스 아키텍처에서 애플리케이션을 다시 작성하는 것이 더 효율적일 수 있습니다.

  • 서비스 상호 작용: 마이크로서비스는 동기식 또는 비동기식으로 통신할 수 있습니다. 동기 통신이 필요한 경우 제한 시간으로 인해 연결 또는 스레드 풀이 소비되는지를 고려합니다. 이 경우 애플리케이션 성능 문제가 발생할 수 있습니다. 이 경우 회로 차단기 패턴을 사용하여 장애가 장기간 이어질 가능성이 있는 작업에 대한 즉각적인 장애를 반환합니다. 이벤트 및 메시징 대기열을 사용하여 비동기 통신을 수행할 수 있습니다.

  • 데이터 집계: 마이크로서비스 아키텍처에서 데이터는 여러 데이터베이스에 분산됩니다. 데이터 집계가 필요한 경우 프런트엔드에서 AWS AppSync를 사용하거나 백엔드에서 명령 쿼리 책임 분리(CQRS) 패턴을 사용할 수 있습니다.

  • 데이터 일관성: 마이크로서비스가 데이터 저장소를 소유하며, 모놀리식 애플리케이션도 잠재적으로 이 데이터를 사용할 수 있습니다. 공유를 활성화하려면 대기열과 에이전트를 사용하여 새 마이크로서비스의 데이터 저장소를 모놀리식 애플리케이션의 데이터베이스와 동기화할 수 있습니다. 그러나 이로 인해 두 데이터 저장소 간에 데이터 중복 및 최종 일관성이 나타날 수 있으므로 데이터 레이크와 같은 장기 솔루션을 설정할 수 있을 때까지 이를 전술적 솔루션으로 처리하는 것이 좋습니다.

구현

스트랭글러 피그 패턴에서는 특정 기능을 한 번에 하나의 구성 요소에 해당하는 새 서비스 또는 애플리케이션으로 바꿉니다. 마이그레이션 중에 프록시 계층은 모놀리식 애플리케이션으로 이동하는 요청을 가로채고 이를 레거시 시스템 또는 새 시스템으로 라우팅합니다. 프록시 계층은 사용자를 올바른 애플리케이션으로 라우팅하므로 모놀리스가 계속 작동하도록 보장하면서 새 시스템에 기능을 추가할 수 있습니다. 결국 새 시스템은 이전 시스템의 모든 기능을 대체하며, 이전 시스템을 폐기할 수 있습니다.

상위 수준 아키텍처

다음 다이어그램에서 모놀리식 애플리케이션에는 사용자 서비스, 장바구니 서비스, 계정 서비스와 같은 세 개의 서비스가 있습니다. 장바구니 서비스는 사용자 서비스에 따라 달라지며 애플리케이션은 모놀리식 관계형 데이터베이스를 사용합니다.

세 가지 서비스를 포함하는 모놀리식 애플리케이션.

첫 번째 단계는 스토어프론트 UI와 모놀리식 애플리케이션 사이에 프록시 계층을 추가하는 것입니다. 먼저 프록시는 모든 트래픽을 모놀리식 애플리케이션으로 라우팅합니다.

모놀리식 애플리케이션에 프록시 추가.

애플리케이션에 새 기능을 추가하려는 경우 기존 모놀리스에 기능을 추가하는 대신 새 마이크로서비스로 구현합니다. 그러나 애플리케이션 안정성을 보장하기 위해 모놀리스에서 버그를 계속 수정합니다. 다음 다이어그램에서 프록시 계층은 직접 호출을 API URL을 기반으로 모놀리스 또는 새 마이크로서비스로 라우팅합니다.

프록시는 모놀리스 또는 새 마이크로서비스로 직접 호출을 라우팅합니다.

손상 방지 계층 추가

다음 아키텍처에서는 사용자 서비스가 마이크로서비스로 마이그레이션됩니다. 장바구니 서비스는 사용자 서비스를 직접 호출하지만 모놀리스 내에서 구현을 더 이상 사용할 수 없습니다. 또한 새로 마이그레이션된 서비스의 인터페이스가 모놀리식 애플리케이션 내 이전 인터페이스와 일치하지 않을 수 있습니다. 이러한 변경 사항을 해결하려면 ACL을 구현합니다. 마이그레이션 프로세스 중에 모놀리스 내 기능이 마이크로서비스로 마이그레이션된 기능을 직접 호출해야 하는 경우 ACL은 직접 호출을 새 인터페이스로 변환하고 적절한 마이크로서비스로 라우팅합니다.

ACL을 추가하여 직접 호출을 새 인터페이스로 변환합니다.

모놀리식 애플리케이션 내에서 ACL을 UserServiceFacade 또는 UserServiceAdapter와 같이 마이그레이션된 서비스에 특정한 클래스로 구현할 수 있습니다. 모든 종속 서비스가 마이크로서비스 아키텍처로 마이그레이션된 후에는 ACL을 폐기해야 합니다.

ACL을 사용하는 경우 장바구니 서비스는 모놀리스 내에서 여전히 사용자 서비스를 직접 호출하고, 사용자 서비스는 ACL을 통해 마이크로서비스로 직접 호출을 리디렉션합니다. 장바구니 서비스는 여전히 마이크로서비스 마이그레이션을 인식하지 못하고 사용자 서비스를 직접 호출해야 합니다. 회귀 및 비즈니스 중단을 줄이려면 이러한 느슨한 결합이 필요합니다.

데이터 동기화 처리

마이크로서비스가 데이터를 소유하는 것이 모범 사례입니다. 사용자 서비스는 자체 데이터 저장소에 데이터를 저장합니다. 보고와 같은 종속성을 처리하고 아직 마이크로서비스에 직접 액세스할 준비가 되지 않은 다운스트림 애플리케이션을 지원하려면 데이터를 모놀리식 데이터베이스와 동기화해야 할 수도 있습니다. 모놀리식 애플리케이션에는 아직 마이크로서비스로 마이그레이션되지 않은 다른 함수 및 구성 요소에 대한 데이터가 필요할 수도 있습니다. 따라서 새 마이크로서비스와 모놀리스 간에 데이터 동기화가 필요합니다. 데이터를 동기화하기 위해 다음 다이어그램과 같이 사용자 마이크로서비스와 모놀리식 데이터베이스 사이에 동기화 에이전트를 도입할 수 있습니다. 데이터베이스가 업데이트될 때마다 사용자 마이크로서비스가 대기열로 이벤트를 보냅니다. 동기화 에이전트는 대기열을 수신 대기하고 모놀리식 데이터베이스를 지속적으로 업데이트합니다. 모놀리식 데이터베이스의 데이터는 최종적으로 동기화되는 데이터와 일치합니다.

동기화 에이전트 추가.

추가 서비스 마이그레이션

장바구니 서비스가 모놀리식 애플리케이션에서 마이그레이션되면 새 서비스를 직접 호출하도록 코드가 수정되므로 ACL이 더 이상 해당 직접 호출을 라우팅하지 않습니다. 다음은 이러한 아키텍처를 나타낸 다이어그램입니다.

추가 서비스 마이그레이션.

다음 다이어그램에서는 모든 서비스가 모놀리스에서 마이그레이션되고 모놀리스의 스켈레톤만 남아 있는 최종 스트랭글러 패턴 적용 상태를 보여줍니다. 기록 데이터는 개별 서비스가 소유한 데이터 저장소로 마이그레이션될 수 있습니다. ACL을 제거할 수 있으며, 이 단계에서 모놀리스를 폐기할 준비가 되었습니다.

모든 서비스를 마이그레이션한 후 최종 스트랭글러 패턴 적용 상태.

다음 다이어그램에서는 모놀리식 애플리케이션이 폐기된 후 최종 아키텍처를 보여줍니다. 애플리케이션의 요구 사항에 따라 리소스 기반 URL(예: http://www.storefront.com/user) 또는 자체 도메인(예: http://user.storefront.com)을 통해 개별 마이크로서비스를 호스팅할 수 있습니다. 호스트 이름 및 경로를 사용하여 HTTP API를 업스트림 소비자에게 노출하는 주요 방법에 대한 자세한 내용은 API 라우팅 패턴 섹션을 참조하세요.

모놀리스 폐기 후 최종 아키텍처.

AWS 서비스를 사용한 구현

API Gateway를 애플리케이션 프록시로 사용

다음 다이어그램에서는 모놀리식 애플리케이션의 초기 상태를 보여줍니다. 리프트 앤 시프트 전략을 사용하여 AWS로 마이그레이션했다고 가정합니다. 이 경우 Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스에서 실행되고 Amazon Relational Database Service(Amazon RDS) 데이터베이스를 사용합니다. 간소화를 위해 아키텍처는 프라이빗 서브넷 하나와 퍼블릭 서브넷 하나가 있는 단일 가상 프라이빗 클라우드(VPC)를 사용합니다. 그리고 마이크로서비스가 처음에 동일한 AWS 계정에 배포된다고 가정합니다. (프로덕션 환경의 모범 사례는 다중 계정 아키텍처를 사용하여 배포 독립성을 보장하는 것입니다.) EC2 인스턴스는 퍼블릭 서브넷의 단일 가용 영역에 상주하고 RDS 인스턴스는 프라이빗 서브넷의 단일 가용 영역에 상주합니다. Amazon Simple Storage Service(Amazon S3)는 웹 사이트의 JavaScript, CSS 및 React 파일과 같은 정적 자산을 저장합니다.

스트랭글러 피그 패턴을 사용하는 경우 모놀리식 애플리케이션의 초기 상태.

다음 아키텍처에서 AWS Migration Hub Refactor Spaces는 모놀리식 애플리케이션 앞에 Amazon API Gateway를 배포합니다. Refactor Spaces는 계정 내부에 리팩터링 인프라를 생성하고 API Gateway는 직접 호출을 모놀리스로 라우팅하기 위한 프록시 계층 역할을 합니다. 처음에 모든 직접 호출은 프록시 계층을 통해 모놀리식 애플리케이션으로 라우팅됩니다. 앞서 설명한 대로 프록시 계층은 단일 장애점이 될 수 있습니다. 그러나 API Gateway를 프록시로 사용하면 이는 서버리스 다중 AZ 서비스이므로 위험을 완화할 수 있습니다.

API Gateway를 사용하여 스트랭글러 피그 패턴 구현.

사용자 서비스는 Lambda 함수로 마이그레이션되고 Amazon DynamoDB 데이터베이스에서 해당 데이터를 저장합니다. Lambda 서비스 엔드포인트와 기본 경로가 Refactor Spaces에 추가되고 API Gateway는 직접 호출을 Lambda 함수로 라우팅하도록 자동으로 구성됩니다.

API Gateway를 사용하여 스트랭글러 피그 패턴 구현: 라우팅 구현.

다음 다이어그램에서는 장바구니 서비스도 모놀리스에서 Lambda 함수로 마이그레이션됩니다. Refactor Spaces에 추가 라우팅 및 서비스 엔드포인트가 추가되고 트래픽은 Cart Lambda 함수로 자동 전환됩니다. Lambda 함수의 데이터 저장소는 Amazon ElastiCache에서 관리합니다. 모놀리식 애플리케이션은 여전히 Amazon RDS 데이터베이스와 함께 EC2 인스턴스에 남아 있습니다.

스트랭글러 피그 패턴을 사용하여 모놀리스 외부로 서비스 이전.

다음 다이어그램에서는 마지막 서비스(계정)가 모놀리스에서 Lambda 함수로 마이그레이션됩니다. 원본 Amazon RDS 데이터베이스를 계속 사용합니다. 이제 새 아키텍처에는 별도의 데이터베이스가 있는 세 개의 마이크로서비스가 있습니다. 각 서비스는 여러 유형의 데이터베이스를 사용합니다. 마이크로서비스의 특정 요구 사항을 충족하기 위해 목적별 데이터베이스를 사용하는 이러한 개념을 다중 사용 지속성이라고 합니다. Lambda 함수는 사용 사례에 따라 여러 프로그래밍 언어로 구현할 수도 있습니다. 리팩터링 중에 Refactor Spaces는 Lambda로의 트래픽 전환 및 라우팅을 자동화합니다. 이 방법을 사용하면 빌더가 라우팅 인프라를 설계, 배포 및 구성하는 데 필요한 시간을 절약할 수 있습니다.

스트랭글러 피그 패턴을 사용하여 모놀리스 외부로 모든 서비스 이전.

다중 계정 사용

이전 구현에서는 모놀리식 애플리케이션을 위한 하나의 프라이빗 서브넷과 하나의 퍼블릭 서브넷이 있는 단일 VPC를 사용했으며 간소화를 위해 동일한 AWS 계정 내부에 마이크로서비스를 배포했습니다. 그러나 마이크로서비스가 배포 독립성을 위해 여러 AWS 계정에 배포되는 실제 시나리오에서는 이러한 경우가 거의 나타나지 않습니다. 다중 계정 구조에서는 모놀리스에서 다른 계정의 새 서비스로 트래픽을 라우팅하도록 구성해야 합니다.

Refactor Spaces를 사용하면 모놀리식 애플리케이션에서 API 직접 호출을 라우팅하기 위해 AWS 인프라를 생성하고 구성할 수 있습니다. Refactor Spaces는 애플리케이션 리소스의 일부로 AWS 계정 내에서 API Gateway, Network Load Balancer 및 리소스 기반 AWS Identity and Access Management(IAM) 정책을 오케스트레이션합니다. 단일 AWS 계정 계정 또는 여러 계정에서 외부 HTTP 엔드포인트에 새 서비스를 투명하게 추가할 수 있습니다. 이러한 모든 리소스는 AWS 계정 내에서 오케스트레이션되며 배포 후 사용자 지정하고 구성할 수 있습니다.

다음 다이어그램과 같이 사용자 서비스와 장바구니 서비스가 서로 다른 두 계정에 배포된다고 가정합니다. Refactor Spaces를 사용하는 경우 서비스 엔드포인트와 경로만 구성하면 됩니다. Refactor Spaces는 API Gateway–Lambda 통합 및 Lambda 리소스 정책 생성을 자동화하므로 모놀리스에서 서비스를 안전하게 리팩터링하는 데 집중할 수 있습니다.

AWS Migration Hub Refactor Spaces를 사용하여 스트랭글러 피그 패턴 구현.

Refactor Spaces 사용에 대한 비디오 자습서는 Refactor Apps Incrementally with AWS Migration Hub Refactor Spaces를 참조하세요.

워크숍

블로그 참조

관련 내용