Microservices
What are Microservices?
In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies. —- James Lewis and Martin Fowler
마이크로서비스는 서비스 디자인 스타일로서 작은 서비스의 결합을 통해 하나의 응용 프로그램을 개발하는 방법으로, 각각의 서비스는 독립적인 비지니스 로직으로 구성되며, 완전 자동화된 개발/배포 환경에 의해 각각 독립적으로 배포할 수 있습니다. 최소한의 중심적인 관리 체계가 있고, 각 시스템들은 다른 프로그래밍 언어, 다른 데이터 스토리지 기술로 작성하는 것이 가능합니다.
Why Microservices?
마이크로서비스는 서비스를 충분히 작은 크기로 나누어 개발하되 상호 연계를 통해 좀 더 복잡하고 거대한 시스템을 만들어 갈 수 있습니다. 그리고 이러한 서비스들은 서비스의 양과 복잡성 뿐만아니라 스케일링에도 높은 자유도를 지니게 되는데, 이러한 특징들은 오늘날 널리 확산되고 있는 클라우드 컴퓨팅이나 고확장성 시스템의 요구조건에 정확하게 부합하고 있습니다.
Monolithic Architecture의 장점
- 하나의 애플리케이션만 개발하면 되기때문에 배포 및 테스트가 편리함
- 컴포넌트간 함수 호출을 사용하기 때문에 높은 성능을 보임
- 개발 레포지터리나 패키지의 운영/관리가 용이함
Monolithic Architecture의 단점
- 시스템 규모가 크면 빌드/배포 시간, 서버 가동시간등이 오래걸림
- 한 사람의 실수가 전체 시스템 빌드 실패를 유발함
- 프로젝트 규모가 클수록 협업이 어려움
- Tight Coupled되어 컴포넌트의 문제가 다른 컴포넌트에 영향을 미침
- 개발자 개개인이 대략적인 전체 시스템을 이해해야함
- 컴포넌트 별로 다른 기술을 도입하기 어려움
Microservices Architecture 장점
- 서비스를 독립적으로 개발 및 배포/운영할 수 있음(Loosely coupled)
- 독립적인 서비스별로 확장을 유연하게 할 수 있음(More Scalability)
- 소프트웨어의 구조가 조직 구조와 일치함(More Agility)
- 새로운 기술 도입 및 변경이 용이함(More Flexibility)
- 서비스의 재사용성이 높음(More Reusability)
Microservices Architecture 단점
- 다른 컴포넌트의 데이터를 API를 통해서 가져오기 때문에 성능이 떨어짐
- 서비스간의 트랜잭션을 묶을 수 없음
- 공통 기능에 대해서 서비스별로 중복이 발생하고 비효율적으로 메모리가 사용됨
- 서비스가 많고 기술이 다양해짐에 따라 End-to-end 테스팅의 복잡도가 높고 운영이 어려움
- 마이크로서비스에 대한 높은 기술적 이해와 개발 구성원의 높은 성숙도를 필요로함
Microservices 도입시 고려사항
Performance
모노리틱은 하나의 프로세스 내에서 함수 호출로 상호운용 됩니다. 반면에 마이크로서비스는 서비스간의 호출이 통신을 통해서 이루어지기 때문에 네트워크 전송 오버헤드가 발생하게 됩니다. 따라서 성능에 민감한 서비스에서는 마이크로서비스 도입이 어렵거나 모노리틱을 혼합하게 디자인해야 합니다.
Transaction Processing
모노리틱에서는 RDB를 사용하면 하나의 애플리케이션내에 트랜잭션에 문제가 있으면 DB의 기능을 이용해서 롤백할 수 있었습니다. 여러개의 DB를 사용해도 트랜잭션 코디네이터(JTS)를 이용해서 쉽게 구현이 가능했습니다. 하지만 마이크로서비스에서는 여러 서비스의 API 기반 트랜잭션을 묶는 것을 불가능합니다. 이러한 문제를 해결하기 위해서는 아래와 같은 방안들이 있습니다.
- 애플리케이션 디자인 단계에서 여러개의 API를 하나의 트랜잭션으로 묶는 분산 트랜잭션 시나리오 자체를 없애는 방법
- 분산 트랜잭션이 반드시 필요하고 중요시되는 시스템에서는 모노리틱 아키텍쳐로 접근하는 방법 (트랜잭션 보장이 중요시되는 금융, 제조와 같은 엔터프라이즈 시스템에서는 적합하지 않고, 대규모 처리가 필요한 B2C형 서비스에 적합)
- 트랜잭션 실패시 보상 트랜잭션을 통한 예외처리 로직을 애플리케이션에서 처리
- 복합 서비스를 만들어서 트랜잭션을 묶어야 하는 두개의 시스템을 지원하는 네이티브 프로토콜을 이용해서 구현하여 하나의 API를 노출시키는 방법 (두개의 서비스가 tightly coupled되어 마이크로서비스의 상호 독립성 사상에 위배되고 서비스 변경시 이 부분을 항상 고려해야함)
Code Duplication
마이크로서비스는 다양한 언어와 기술을 사용하여 개발될 수 있기때문에 다른 서비스와는 독립적으로 최적화된 언어/기술을 사용하여 개발할 수 있다는 장점이 있지만, 동일한 기능을 수행하는 코드를 서비스별로 중복 작성하게 될 수 있습니다. 중복 문제를 해결하기 위해서는 API Gateway에서 이러한 공통 기능을 처리할 수 있지만, API Gateway는 최대한 가볍게 가져가야 한다는 설계 원칙을 고려해야 합니다. 다언어 개발을 위한 코드중복 방지를 위한 다른 방법으로 JVM이나 .net 등을 기반으로한 언어간의 상호 호환성을 고려할 수도 있습니다.
단 다언어 사용에 의한 비용/성능의 장점을 고려하여 이러한 코드 중복을 허용할 수도 있습니다.
※ API Gateway
API Gateway란 프록시 서버처럼 각 서비스의 API들 앞에서 EndPoint(API의 URL)를 통합하고, 공통 기능등의 추가 기능을 제공하는 미들웨어입니다. SOA의 ESB(Enterprise Service Bus)의 경량화된 버전으로, API Gateway에서 무거운 로직을 수행하거나 잘못 설계되면 실패 가능성이 매우 높은 컴포넌트입니다.
Data Duplication
마이크로서비스는 서비스별로 적절한 데이터 스토리지 솔루션을 사용하여 구성될 수 있기 때문에 이에따른 데이터 중복이 발생할 수 있습니다. 이 문제는 사용하는 솔루션에 따라서 적당한 데이터 모델링으로 디자인하여 해결해야 합니다. 또한 다양한 데이터 스토리지 솔루션 사용에 의한 비용/성능의 장점을 고려하여 데이터 중복을 허용할 수 있다.
Memory Duplication
마이크로서비스는 서비스별로 독립된 서버 또는 컨테이너에 분할 배치되기 때문에 동일한 모듈이 중복으로 메모리에 올라갈 수 있습니다. 이 문제는 마이크로서비스 아키텍쳐에서 반드시 발생할 수 있는 문제지만 현대 인프라의 가용성/성능 발전을 고려하면 큰 문제가 되지 않습니다.
Operation Overhead
마이크로서비스는 서비스 개수가 증가함에 따라서 많은 양의 배포 및 릴리즈 작업이 수반됩니다. 또한 각 서비스들이 서로 다른 기술을 사용할 수 있기때문에 필요한 기술도 늘어나게 됩니다. 이 문제를 해결하기 위해서는 배포 및 릴리즈에 수반되는 모든 작업들이 철저하게 자동화되어야 하며 이를 위한 DevOps의 도입이 필수 적입니다.
Testing Challenges
마이크로서비스는 각 서비스가 분리되어 비동기적으로 동작하기 때문에 런타임 환경에서의 상호작용을 테스트하기가 매우 까다롭습니다. 마틴 파울러는 Testing Strategies in a Microservice Architecture에서 각 서비스의 테스트 초기단계에서 최대한 Coverage를 높여서 End-to-end 테스트를 최소화하는 전략을 제시하고 있습니다. 즉, 아래 Summary에서 Unit > Integration > Component > Contract > End-to-end 순으로 Unit Test를 통해서 최대한 Test Coverage를 달성하고, 까다로운 End-to-end 테스트를 최소화한다는 것입니다.
Team Management
마이크로서비스는 도메인 단위의 서비스가 독립적으로 개발/배포되기 때문에 팀 운영에 있어서도 중앙집권적 체계를 벗어나 각 팀이 독립적으로 운영할 수 있습니다. 즉, 팀 자체적으로 기획/개발/운영하며 스스로 서비스를 발전 시키는 하나의 회사같은 개념이 되는 것입니다.
이렇게 독립적인 수행 능력을 가지고 있는 팀 모델을 self-organized team이라고 하며 아래와 같은 특징 및 장점을 가지고 있습니다.
- 최적화된 팀 규모: 의사소통이 효율적이고 의사결정 속도가 빨라져서 생산성이 향상되고 변화에 대한 수용과 대응에서 큰 장점을 지님
- 독립적인 운영: 팀 운영에 있어서 유연성이 향상되고 팀원에게 높은 권한과 책임이 주어져 주인의식을 가지고 일함
- 아키텍쳐 선택의 자율성
- 상향식 개발
팀 운영에 있어서 아래와 같은 단점 및 고려사항들이 있습니다.
- 팀의 영속성 보장: 팀별로 다른 형태의 표준과 기술 프로세스를 통해서 개발하기 때문에 잦은 조직 이동이 있는 경우, 개개인이 가진 기술 노하우를 재활용하기 어렵고 새로운 팀원에 대한 교육과 적응이 필요합니다.
- 높은 수준의 팀 성숙도 요구: 팀내에서 기획/개발/운영을 독립적으로 수행해야 하기때문에 개발과 운영에 높은 성숙도가 요구됩니다.
Presentation
아래 자료는 필자가 컨퍼런스에서 Microservices를 주제로 발표했던 자료 입니다.