마이크로 서비스별 데이터 주권
팁
이 콘텐츠는 eBook, 컨테이너화된 .NET 애플리케이션을 위한 .NET 마이크로 서비스 아키텍처에서 발췌한 것이며, .NET 문서에서 제공되거나 오프라인 상태에서도 읽을 수 있는 PDF(무료 다운로드 가능)로 제공됩니다.
마이크로 서비스 아키텍처에 대한 중요한 규칙으로, 각 마이크로 서비스는 자체 도메인 데이터와 논리를 갖고 있어야 합니다. 완전한 애플리케이션이 자체 논리와 데이터를 갖는 것처럼, 각 마이크로 서비스는 자율적 수명 주기에서 자체 논리와 데이터를 가져야 하고, 마이크로 서비스마다 독립적으로 배포되어야 합니다.
즉, 도메인의 개념적 모델이 하위 시스템 또는 마이크로 서비스 간에 달라집니다. CRM(고객 관계 관리) 애플리케이션, 트랜잭션 구매 하위 시스템, 고객 지원 하위 시스템이 각각 고유한 고객 엔터티 특성 및 데이터를 호출하고 각각 서로 다른 BC(경계가 지정된 컨텍스트)를 사용하는 엔터프라이즈 애플리케이션을 생각해 보세요.
이 원칙은 DDD(도메인 기반 디자인)와 비슷합니다. 각 경계가 지정된 컨텍스트 또는 자율적 하위 시스템 또는 서비스가 자체 도메인 모델(데이터와 논리 및 동작)을 가져야 합니다. 각 DDD 경계가 지정된 컨텍스트는 한 비즈니스 마이크로 서비스(하나 또는 여러 서비스)와 상관 관계가 있습니다. 바인딩된 컨텍스트 패턴에 대한 이 포인트는 다음 섹션에서 다루겠습니다.
반면, 여러 애플리케이션에 사용되는 전통적인(모놀리식 데이터) 방식은 중앙 집중식 데이터베이스 하나 또는 데이터베이스 몇 개만 사용합니다. 이는 그림 4-7처럼 종종 전체 애플리케이션 및 모든 내부 하위 시스템에 사용되는 정규화된 SQL 데이터베이스입니다.
그림 4-7. 데이터 주권 비교: 모놀리식 데이터베이스와 마이크로 서비스 비교
기존의 접근 방식에서는 모든 서비스(일반적으로 계층화된 아키텍처에서)에서 공유되는 단일 데이터베이스가 있습니다. 마이크로 서비스 접근 방식에서 각 마이크로 서비스는 해당 모델/데이터를 소유합니다. 중앙 집중식 데이터베이스 접근 방식은 처음에는 간단해 보이고 엔터티를 여러 하위 시스템에 재사용하여 모든 것을 일관적으로 유지할 수 있는 것처럼 보입니다. 그러나 결국에는 여러 하위 시스템을 처리하는 거대한 테이블이 생기고, 대부분의 경우 필요 없는 특성과 열이 포함됩니다. 단거리 하이킹, 하루가 걸리는 자동차 여행 및 지질 연구에 똑같은 물리적 맵을 사용하는 것에 비유할 수 있습니다.
일반적으로 단일 관계형 데이터베이스를 사용하는 모놀리식 애플리케이션의 두 가지 주요 이점은 ACID 트랜잭션 및 SQL 언어로, 둘 다 애플리케이션과 관련된 모든 테이블 및 데이터에서 작동합니다. 이 접근 방식은 여러 테이블의 데이터를 결합하는 쿼리를 손쉽게 작성하는 방법을 제공합니다.
그러나 마이크로 서비스 아키텍처로 전환하면 데이터 액세스가 점점 더 복잡해집니다. 마이크로 서비스 또는 바인딩된 컨텍스트 내에서 ACID 트랜잭션을 사용하는 경우에도 각 마이크로 서비스 소유의 데이터는 해당 마이크로 서비스에 대해 비공개이며 API 엔드포인트(REST, gRPC, SOAP 등)를 통해 동기적으로 또는 메시징(AMQP 또는 이와 유사)을 통해 비동기적으로만 액세스된다는 점을 고려해야 합니다.
데이터를 캡슐화하면 마이크로 서비스가 느슨하게 결합되므로 서로 독립적으로 발전할 수 있습니다. 여러 서비스가 동일한 데이터에 액세스하는 경우 스키마를 업데이트하려면 모든 서비스에 대한 조정된 업데이트가 필요합니다. 이렇게 하면 마이크로 서비스 수명 주기 자율성이 손상됩니다. 하지만 분산 데이터 구조는 마이크로 서비스에 단일 ACID 트랜잭션을 만들 수 없습니다. 다시 말해서, 비즈니스 프로세스가 여러 마이크로 서비스에 걸쳐 있는 경우 최종 일관성을 사용해야 합니다. 이는 간단한 SQL 조인보다 구현하기가 훨씬 어렵습니다. 나중에 설명하겠지만, 무결성 제약 조건을 만들거나 별도의 데이터베이스 간에 분산 트랜잭션을 사용할 수 없기 때문입니다. 마찬가지로, 다른 많은 관계형 데이터베이스 기능은 여러 마이크로 서비스에서 사용할 수 없습니다.
좀 더 깊이 들어가자면, 종종 다양한 마이크로 서비스에서 다양한 종류의 데이터베이스를 사용합니다. 최신 애플리케이션은 다양한 종류의 데이터를 저장 및 처리하며, 따라서 관계형 데이터베이스가 언제나 좋은 선택은 아닙니다. 일부 사용 사례에서는 Azure CosmosDB 또는 MongoDB 같은 NoSQL 데이터베이스가 SQL Server 또는 Azure SQL Database 같은 SQL 데이터베이스보다 편리한 데이터 모델과 우수한 성능 및 확장성을 제공할 수도 있습니다. 그 외에는 여전히 관계형 데이터베이스가 가장 좋은 방법입니다. 이러한 이유로 마이크로 서비스 기반 애플리케이션에서는 SQL 및 NoSQL 데이터베이스를 혼합해서 사용하는 경우가 많으며, 이를 다국어 지속성 접근 방식이라고도 합니다.
데이터 스토리지에 사용되는 분할된 다국어 아키텍처는 여러 가지 이점이 있습니다. 느슨한 결합과 더 우수한 성능, 확장성, 비용 및 관리성을 예로 들 수 있습니다. 하지만 이 챕터의 뒷부분에 나오는 "도메인 모델 경계 식별"에서 설명한 바와 같이 분산 데이터 관리가 어려울 수 있습니다.
마이크로 서비스와 경계가 지정된 컨텍스트 패턴 사이의 관계
마이크로 서비스의 개념은 DDD(도메인 기반 디자인)의 BC(경계가 지정된 컨텍스트) 패턴에서 파생됩니다. DDD는 대형 모델을 여러 BC로 분할하고 경계에 대해 명시적으로 만드는 방식으로 대형 모델을 처리합니다. 각 마이크로 서비스에 자체적인 관련 데이터가 있듯이, 각 BC에도 자체적인 모델 및 데이터베이스가 있어야 합니다. 또한 일반적으로 각 BC에는 소프트웨어 개발자와 도메인 전문가 간의 통신을 도와주기 위한 자체적인 유비쿼터스 언어가 있습니다.
유비쿼터스 언어에서 이러한 용어(주로 도메인 엔터티)는 심지어 여러 도메인 엔터티가 동일한 ID(즉, 스토리지에서 엔터티를 읽는 데 사용되는 고유의 ID)를 공유하는 경우에도 바인딩된 다른 컨텍스트에서 다른 이름을 가질 수 있습니다. 예를 들어 사용자 프로필 경계가 지정된 컨텍스트에서, 사용자 도메인 엔터티는 주문 경계가 지정된 컨텍스트의 구매자 도메인 엔터티와 ID를 공유할 수 있습니다.
이러한 점에서 마이크로 서비스는 바인딩된 컨텍스트와 비슷하지만, 거기서 그치지 않고 분산 서비스임을 지정합니다. 바인딩된 각 컨텍스트에 대한 별도의 프로세스로 빌드되며, 앞서 언급했듯이 HTTP/HTTPS, WebSockets 또는 AMQP 같은 분산 프로토콜을 사용해야 합니다. 그러나 바인딩된 컨텍스트 패턴은 바인딩된 컨텍스트가 분산 서비스라고 지정하거나 모놀리식 배포 애플리케이션 내의 단순한 논리적 경계(예: 제네릭 하위 시스템)라고 지정하지 않습니다.
바인딩된 각 컨텍스트에 대한 서비스를 정의하는 것부터 시작하는 것이 좋다고 강조해야 합니다. 하지만 디자인을 거기에 제한할 필요는 없습니다. 경우에 따라 경계가 지정된 컨텍스트를 디자인해야 할 때도 있고 여러 물리적 서비스로 구성된 비즈니스 마이크로 서비스를 디자인해야 할 때도 있습니다. 하지만 궁극적으로 두 패턴, 즉 바인딩된 컨텍스트와 마이크로 서비스는 밀접하게 관련되어 있습니다.
DDD는 실제 경계를 분산된 마이크로 서비스의 형태로 가져오는 마이크로 서비스의 이점을 활용합니다. 하지만 마이크로 서비스 간에 모델을 공유하지 않는 아이디어는 경계가 지정된 컨텍스트에도 사용할 수 있습니다.
추가 리소스
Chris Richardson 패턴: 서비스별 데이터베이스
https://microservices.io/patterns/data/database-per-service.htmlMartin Fowler. BoundedContext
https://martinfowler.com/bliki/BoundedContext.htmlMartin Fowler. PolyglotPersistence
https://martinfowler.com/bliki/PolyglotPersistence.htmlAlberto Brandolini. 컨텍스트 매핑을 통한 전략적인 도메인 기반 디자인
https://www.infoq.com/articles/ddd-contextmapping
.NET