마이크로서비스 아키텍쳐(MSA)는 애플리케이션을 핵심 기능으로 세분화해서 각각의 기능들을 독립적인 서비스로 구성, 구축, 배포하고 각 서비스들의 간의 통신을 API로 설계하는 현대적인 애플리케이션 설계 방법론입니다.
고전적인 모놀리식 아키텍쳐에서는 전체 애플리케이션의 소스코드가 하나의 배포 단위 (.war 도는 .jar)로 구성되고 모든 기능들이 단일 서버에서 구동됩니다. 이커머스 서비스를 모놀리식 방식으로 설계한다고 가정한다면, UI/UX 프런트엔드 및 백엔드 기능 (사용자, 상품, 장바구니, 주문, 결제, 배송) 등이 단일 서비스로 구성되어 실행되고, 단일 데이터베이스에 각 기능별 필요한 정보들이 저장될것입니다.
애플리케이션 동작에 필요한 기능들은 각각의 독립된 서비스로 구성되며 각 서비스들은 고유의 데이터베이스를 소유합니다. 특정 서비스에서 다른 서비스의 기능을 호출할 때는 API를 통해 통신합니다.
특정 서비스에 대한 요청이 증가할 경우 서비스 전체를 확장할 필요 없이 오토 스케일링을 통해 해당 서비스만 확장 시킬 수 있습니다. 이때 특정 서비스의 워크로드에 적합한 인프라를 선택할 수 있습니다. AWS를 기준으로 했을 때 메모리 사용이 많은 서비스에는 Memory Optimized 인스턴스를, 불규칙한 워크로드를 가진 서비스에는 Burstable 인스턴스 또는 AWS Lambda와 DynamoDB를 이용한 Serverless 방식을 선택할 수 있습니다.
애플리케이션을 구성하는 각각의 서비스들은 API나 Messaging Protocols(HTTP, MQ, etc) 을 통해서 통신하므로 개발자들은 필요한 기능에 맞는 최적의 언어, 기술, 도구들을 자유롭게 선택할수 있습니다. 예를 들어 애플리케이션의 전반적인 부분은 Java로 개발하고 I/O 작업이 많이 이루어지는 서비스는 Node.js을 통해서 비동기 방식으로 개발할 수 있습니다.
하나의 큰 애플리케이션을 구성하는 다수의 서비스들을 각각의 독립된 팀에서 전담하여 동시에 개발할 수 있습니다. 이는 개발에 소요되는 시간을 단축할 수 있으며 애자일 개발 방법론을 도입할 경우에는 개발 주기를 보다 단축할 수 있습니다.
배포 단위가 작아짐으로써 개발자가 적용한 애플리케이션의 변경 사항을 더 빠르게 빌드, 테스트, 배포할 수 있고 변경된 사항에 문제가 발생하더라도 더 빠르게 복구 및 수정 할 수 있습니다.
모놀리식 아키텍처에서는 각 구성 요소가 서로 종속되어 있기 때문에 단일 서비스의 장애가 전체 애플리케이션 장애를 초래할 수 있습니다. 반면 마이크로서비스 아키텍쳐에서의 독립적인 서비스들은 서로에게 미치는 영항이 없거나 최소화합니다.
CI/CD 파이프라인 구축을 통해 신속히 애플리케이션 변경 사항을 반영할 수 있다면 사용자의 피드백 시간 역시 단축될 것입니다. 이를 바탕으로 새로운 기능을 개발할 수 있고, 나아가 Software Development Life Cycle의 선순환 효과도 기대할수 있습니다. 더 빠르게 빌드하고, 테스트하기 위해서는 확장 가능한 빌드 및 테스트 시스템 구성이 필수적입니다. 실시간으로 발생하는 수십개의 빌드 및 테스트를 고정된 개수의 서버로 고전적인 Queue 방식으로 처리한다면 CI/CD의 장점을 극대화 할 수 없습니다.
마이크로서비스를 설계하는 방식에 정답은 없습니다. 각기 다른 요구사항에 따라 아키텍처가 달라질 수 있고 시스템을 설계하는 사람마다 다른 관점에서 마이크로서비스를 바라볼 수 있기 때문입니다. 하지만 마이크로서비스를 설계할 때 아래와 같은 요소들을 기초로 해야한다는 것에는 이견이 없습니다.
또한, Twelve-Factor App 방법론에 명시된 원칙들 역시 마이크로서비스 설계 단계에서 많이 고려되고 적용되고 있습니다.
마이크로서비스가 특정 디자인 패턴에 의해서만 설계된다고 볼 수는 없지만 AWS상에서 가장 많이 적용되는 기본적인 2가지 패턴을 일반적인 애플리케이션을 구성하는 Presentation Layer, Application Layer, Database Layer를 기준으로 했을 때 아래와 같이 구성할 수 있습니다.
위의 샘플 아키텍처는 resentation Layer(User Interface)에서 AWS S3의 정적 웹 호스팅과 CloudFront를 이용하고, Application Layer(Microservices)는 ECS 또는 EKS 클러스터에 컨테이너 기반으로 구축하고, Database Layer는 관계형 데이베이스인 Amazon Aurora 또는 비관계형 데이터베이스인 DynamoDB를 통해서 구성됩니다.
위의 구성에서 가장 주목해야할 부분은 ‘컨테이너’입니다. 컨테이너는 마이크로서비스를 얘기할 때 항상 빠지지 않는 주제이기도 합니다. 컨테이너를 사용하지 않고 EC2 같은 가상머신(VM)을 이용하면 안될까요? 물론 가능하지만 리소스 사용 효율을 저하시킵니다. 이러한 현상이 일어나는 이유는 가상머신과 컨테이너를 비교하면 보다 쉽게 이해할 수 있습니다.
가상머신에서 독립된 환경의 애플리케이션을 구동하려면 각 애플리케이션 마다 Guest OS가 필요합니다. 컨테이너 같은 경우에는 독립된 환경을 구축하더라도 호스트 서버의 OS 커널을 공유해서 사용하므로 OS 가상화에 소비되는 리소스를 절약할수 있습니다.
더불어애플리케이션이 필요로하는 최소 단위의 가상머신이 필요로하는 리소스의 양이 하나의 마이크로서비스가 필요로 하는 리소스 보다 클 때는 사용되지 않는 리소스가 낭비될 수 있다는 점도 유념해야합니다.
서버리스 마이크로 서비스가 컨테이너 기반의 마이크로 서비스와 다른점은 Application Layer가 Function as a service인 AWS Lambda를 이용한다는 점입니다. AWS Lambda를 사용하면 서버를 프로비저닝하거나 관리할 필요 없이 코드를 실행할 수 있고 호출된 코드는 병렬로 처리되면서 스스로 스케일링이 됩니다. 또한 코드가 실행될 때만 과금되므로 일정하지 않은 워크로드를 가진 서비스를 구동할때 비용 효율성 측면에서 장점을 가지고 있습니다.
csm@saltware.co.kr
T. 02-2025-4942