영.Monolithic application 에서 시작하다
Monolith means composed all in one piece. The Monolithic application describes a single-tiered software application in which different components combined into a single program from a single platform.
(Introduction to Monolithic Architecture and MicroServices Architecture 에서 인용)
소프트웨어 애플리케이션의 다른 컴포넌트들을 모두 하나의 프로그램에 배치하는 것을 Monolithic application 이라고 합니다. 예를 들어, 프로그래밍 언어의 기본 기능을 사용하여 애플리케이션을 클래스, 함수, 네임스페이스로 분할하고, 배포 파이프라인을 사용하여 변경사항이 프로덕션 환경에 배포되기 전에 테스트되도록 보장하며, 로드 밸런서 뒤에서 여러 인스턴스를 실행하여 수평적으로 확장합니다:
All your logic for handling a request runs in a single process, allowing you to use the basic features of your language to divide up the application into classes, functions, and namespaces. With some care, you can run and test the application on a developer's laptop, and use a deployment pipeline to ensure that changes are properly tested and deployed into production. You can horizontally scale the monolith by running many instances behind a load-balancer.
이 아키텍처 패턴에서는 애플리케이션이 잘 작동하지만, 2 가지 문제가 있습니다:
-
변경에 제한이 있음: 매우 작은 변경이라도 애플리케이션 전체의 재��드와 배포가 필요하며, 변경의 영향 범위를 제어하기 어려움
-
확장이 어려움: 애플리케이션 내에서 더 많은 리소스를 필요로 하는 부분만 확장할 수 없고, 애플리케이션 전체를 확장할 수밖에 없음
이러한 제한은 클라우드 환경에서 특히 두드러집니다. 그래서 마이크로서비스 아키텍처가 무대에 등장했습니다
일.마이크로서비스 아키텍처란 무엇인가?
Microservices are a software development technique—a variant of the service-oriented architecture (SOA) architectural style that structures an application as a collection of loosely coupled services. In a microservices architecture, services are fine-grained and the protocols are lightweight.
(Microservices 에서 인용)
서비스 지향 아키텍처 (SOA) 의 한 변종으로, 애플리케이션을 느슨하게 결합된 서비스의 컬렉션으로 구조화하고 경량 통신 프로토콜로 조직합니다
Building applications as suites of services. As well as the fact that services are independently deployable and scalable, each service also provides a firm module boundary, even allowing for different services to be written in different programming languages. They can also be managed by different teams.
구체적으로, 애플리케이션을 일련의 소형 서비스로 구축합니다. 이러한 서비스는 독립적으로 배포 가능하고 독립적으로 확장 가능하며, 각 서비스는 견고한 모듈 경계를 가지며, 심지어 다른 프로그래밍 언어로 다른 서비스를 작성할 수 있고 다른 팀에서 관리할 수도 있습니다

마이크로서비스와 SOA
Service-oriented architecture (SOA) is a style of software design where services are provided to the other components by application components, through a communication protocol over a network.
(Service-oriented architecture 에서 인용)
SOA 에서 서비스는 애플리케이션 컴포넌트에 의해 네트워크 통신 프로토콜을 통해 다른 컴포넌트에 제공됩니다. 따라서, 마이크로서비스 아키텍처는 SOA 의 한 변종, 또는 특정 사례로, 특정 특징을 만족하는 SOA 설계를 가리킵니다
이.마이크로서비스 아키텍처의 9 가지 특징
서비스를 통한 컴포넌트화 (Componentization via Services)
컴포넌트는 독립적으로 교체 및 업그레이드 가능한 소프트웨어 유닛으로 이해할 수 있으며, 일련의 컴포넌트를 함께 연결하여 소프트웨어 시스템을 구성합니다. 물리적 세계에서 우리가 보는 것과 마찬가지입니다:
Our definition is that a component is a unit of software that is independently replaceable and upgradeable. There's been a desire to build systems by plugging together components, much in the way we see things are made in the physical world.
마이크로서비스 아키텍처에서 컴포넌트는 서비스입니다. Web 서비스 요청이나 RPC 등의 메커니즘을 통해 통신합니다. 이 서비스 입자의 컴포넌트화에는 2 가지 장점이 있습니다:
-
서비스는 독립적으로 배포 가능
-
서비스는 명시적인 외부 인터페이스 (PublishedInterface) 를 가짐
독립 배포란, 서비스의 내부 변경은 해당 서비스만 재배포하면 되고, 서비스 인터페이스 변경이 관여할 때만 여러 서비스의 협력 변경이 필요함을 의미합니다. 다른 한편, 서비스 경계와 서비스 프로토콜의 진화를 통해 이러한 연관을 가능한 한 줄일 수 있습니다
명시적인 외부 인터페이스는 강력한 제약으로, 컴포넌트의 캡슐화를 보장하고 컴포넌트 간의 과도한 밀결합을 피합니다
하지만 프로세스 내 호출에 비해 RPC 의 성능 비용이 더 높기 때문에 RPC 인터페이스는 대부분 조립적이며 종종 사용하기 더 어렵습니다. 다른 한편, 컴포넌트 책임을 조정하고 싶다면 리팩토링 비용도 더 높아집니다
비즈니스 기능을 중심으로 팀 조직하기 (Organized around Business Capabilities)
마이크로서비스는 시스템을 비즈니스 기능에 기반하여 일련의 서비스로 분해할 수 있게 하므로, 비즈니스 기능을 중심으로 크로스펑셔널 팀을 조직할 수 있습니다. 또한, 이 조직 구조는 서비스 경계를 강화하는 데에도 도움이 됩니다:

P.S.콘웨이 법칙: 설계 구조는 결국 해당 조직의 커뮤니케이션 구조와 일치합니다:
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure. -- Melvyn Conway, 1967
커뮤니케이션 구조가 설계 구조를 변경하는 매우 흥미로운 예는, 일부 팀이 로직을 자신이 제어할 수 있는 애플리케이션에 밀어넣는 것입니다. 크로스팀 협업의 커뮤니케이션 비용을 피하기 위해서입니다:
A smart team will optimise around this and plump for the lesser of two evils - just force the logic into whichever application they have access to.
Monolithic application 에서 비즈니스 라인별로 팀을 분할하는 것과 비교하여, 서비스 경계가 더 명확하고 제약력도 더 강합니다. 모듈 경계를 넘어선 비즈니스 기능이 나타나기 쉽고, 서비스 경계는 상대적으로 더 안정적이기 때문입니다
프로젝트가 아닌 프로덕트 만들기 (Products not Projects)
마이크로서비스 아키텍처는 프로덕트가 소속된 개발 팀에 의해 장기적으로 유지보수/진화되는 것을 선호하며, 프로젝트가 딜리버리된 후 다른 유지보수 팀에 인계되는 것을 선호하지 않습니다:
Microservice proponents tend to avoid this model, preferring instead the notion that a team should own a product over its full lifetime.
이러한 프로덕트 철학은 개발 팀과 사용자 사이에 지속적인 관계를 구축하고, 개발 팀이 소프트웨어가 어떻게 사용자를 지원하여 비즈니스 기능을 향상시키는지에 주목하게 합니다:
There is an on-going relationship where the question is how can software assist its users to enhance the business capability.
스마트 엔드포인트와 덤 파이프 (Smart endpoints and dumb pipes)
통신 메커니즘에 대해, 전형적인 예는 엔터프라이즈 서비스 버스 (Enterprise Service Bus) 로, 메시지는 모두 ESB 를 흐르고, ESB 가 메시지의 라우팅, 오케스트레이션, 변환 및 비즈니스 규칙 적용을 담당한 후 엔드포인트 (endpoints) 에 도달하여 처리됩니다. 이 모드에서는 엔드포인트를 덤으로 유지할 수 있습니다. 많은 로직이 ESB 메시지 파이프 내에서 처리되기 때문입니다. 따라서 스마트 파이프와 덤 엔드포인트 (smart pipes and dumb endpoints) 라고 합니다
마이크로서비스는 이와 반대되는 접근을 선호하며, 스마트 엔드포인트와 덤 파이프 (smart endpoints and dumb pipes) 입니다:
That the lanes of communication should be stripped of business processing and logic and should literally only distribute messages between components. It's then the components themselves that do processing / logic / validation etc... on those messages.
즉, 파이프는 컴포넌트 간에 메시지를 배포하는 것만 담당하고, 서비스 자체가 메시지에 대해 해당 처리를 수행합니다
분산형 기술 거버넌스 (Decentralized Governance)
중앙집중형 기술 거버넌스의 최대 문제는 그 제한성으로, 통일된 기술 스택이 모든 시나리오에 적합한 것은 아닙니다:
Experience shows that this approach is constricting - not every problem is a nail and not every solution a hammer, we prefer using the right tool for the job.
마이크로서비스 배경에서, 각 서비스는 개별적으로 구축되며, 다른 기술 스택을 선택할 기회가 있어, 더 적절한 도구를 사용하여 다른 일을 수행할 수 있습니다. 이 기술 스택의 자유는 서비스의 독립적 진화에 도움이 되며, 자연스럽게 더 나은 패턴을 선택합니다
물론, "이전에는 선택이 없었지만 지금은 선택할 수 있다"는 것이 백화제방이 좋다는 것을 의미하지는 않습니다. 다른 기술 에코시스템을 유지보수하는 비용이 그 수익을 초과할 수 있기 때문입니다:
We don't end up with 20 different languages in the same system because each of them is opinionated and brings their own vision inside the system, maintaining different ecosystem is very expensive and potentially confusing without providing too many benefits.
저울질之下、我们可以将选择范围限制到某几种技术栈,而不再与一种技术栈强绑定:
But a trade-off could help out, having a limited list of languages or frameworks we can pick from can really help. Suddenly, we are not tightly coupled with one stack only.
분산형 데이터 관리 (Decentralized Data Management)
가장 추상적인 레벨에서 보면, 분산형으로 데이터를 관리한다는 것은 각 시스템이 객관 세계에 대해 형성하는 개념 모델이 다르다는 것을 의미합니다. 예를 들어, 영업 담당자의 눈속 고객과 개발자가 이해하는 고객은 다르며, 같은 개념이라도 2 개의 관점에서 미묘한 차이가 있을 수 있습니다
이러한 상황에 대처하기 위한 효과적인 조치는 도메인 주도 설계 (Domain-Driven Design) 의 경계 있는 컨텍스트 (Bounded Context) 입니다:
应该显式地定义某个模型所应用的上下文。还应该在团队组织、应用中特定部分的使用以及像代码库和数据库模式等物理表现等方面显式地设定边界。要保持边界中模型的严格一致,而不要受外界问题的影响与干扰。
(初窥 Bounded Context 에서 인용)
즉, 모델 개념에 컨텍스트를 한정하고, 그 컨텍스트 내에서 개념의 엄격한 일관성을 보장합니다. 복잡한 도메인을 여러 개의 경계 있는 컨텍스트로 분할하고, 그 사이의 연관을 그려내는 것이 개념 모델 레벨의 분산형 입니다:
DDD divides a complex domain up into multiple bounded contexts and maps out the relationships between them.
데이터 스토리지 구체화에서, 마이크로서비스도 유사한 분산형 정책을 채택하여, 각 서비스가 자신의 데이터베이스를 관리하는 것을 선호합니다. 이러한 데이터베이스는 같은 데이터베이스 기술의 다른 인스턴스일 수도 있고, 완전히 다른 데이터베이스 시스템일 수도 있으며, 혼합 지속성 이라고 합니다:
Microservices prefer letting each service manage its own database, either different instances of the same database technology, or entirely different database systems - an approach called Polyglot Persistence.
P.S.분산형 데이터 스토리지로 인해 발생하는 데이터 일관성 문제에 대해서는, 일부 보상 작업을 통해 데이터를 최종적으로 일관되게 만드는 것을 고려할 수 있습니다. 자세한 내용은 Starbucks Does Not Use Two-Phase Commit 를 참조하십시오
인프라스트럭처 자동화 (Infrastructure Automation)
Monolithic application 과 비교하여, 마이크로서비스의 배포는 더 복잡합니다. 복잡한 네트워크 환경에서는 하나의 독립된 애플리케이션을 배포하는 것보다 여러 서비스를 배포하는 것이 더 어렵기 때문입니다:

하지만 클라우드 컴퓨팅의 발전으로 인프라스트럭처 자동화가 가능해져, 서비스의 구축, 배포, 운영의 복잡성을 대폭 줄여주어, 인프라스트럭처 자동화를 이용하여 프로덕션 환경에서 마이크로서비스 관리를 실현할 수 있습니다
장애에 대한 설계 (Design for failure)
마이크로서비스 배경에서, 클라이언트의 내결함성 설계가 더 중요합니다:
A consequence of using services as components, is that applications need to be designed so that they can tolerate the failure of services. Any service call could fail due to unavailability of the supplier, the client has to respond to this as gracefully as possible.
Monolithic application 과 비교하여, 이 내결함성 설계로 인해 발생하는 추가적인 복잡성은 일종의 열세입니다
다른 한편, 장애점을 신속하게 감지하고, 가능한 한 서비스를 자동으로 복구시키기 위해, 실시간 모니터링도 마이크로서비스 아키텍처에서 특히 중요합니다
P.S.내결함성 설계에 대한 자세한 내용은 Fault Tolerance in a High Volume, Distributed System 를 참조하십시오
진화적 설계 (Evolutionary Design)
컴포넌트의 분할은 마이크로서비스 아키텍처에서 매우 중요하며, 변화를 줄일 수 있는지와 관련이 있습니다. 일반적인 원칙은 해당 컴포넌트가 독립적으로 교체 및 업그레이드 가능한지 여부입니다:
The key property of a component is the notion of independent replacement and upgradeability.
하지만, 다른 각도에서 보면, 변화를 제어하는 것이 반드시 변화를 줄여야 하는 것은 아닙니다. 이러한 변화가 예상대로 신속하게 수행되는 것을 보장할 수 있다면, 그것도 매우 우수한 제어입니다:
Change control doesn't necessarily mean change reduction - with the right attitudes and tools you can make frequent, fast, and well-controlled changes to software.
마이크로서비스 아키텍처가 제공하는 서비스의 분해 능력을 도구로 사용하여, 이를 통해 서비스 입자의 변화 제어를 실현합니다:
-
일부 서비스가 장래에 폐지될 것을 예상하고, 장기적으로 진화시킬 필요는 없음
-
동시에 변화하는 것을 같은 서비스에 배치하고,あまり 변화하지 않는 부분을 별도의 서비스에 배치하여, 빈번하게 변화하는 부분과 구분함
삼.마이크로서비스 아키텍처의 중요한 문제
먼저, 컴포넌트 경계를 정확하게 정의하는 것은 쉬운 일이 아닙니다:
It's hard to figure out exactly where the component boundaries should lie.
따라서, 진화적 설계는 타협하여, 경계를 더 쉽게 리팩토링할 수 있도록 합니다 (시행착오 비용을 절감):
Evolutionary design recognizes the difficulties of getting boundaries right and thus the importance of it being easy to refactor them. But when your components are services with remote communications, then refactoring is much harder than with in-process libraries.
다른 한편, 설계가 좋지 않다면, 이는 컴포넌트 내의 복잡도를 컴포넌트 간의 연결로 이전할 뿐이며, 더 제어하기 어려워집니다:
Another issue is If the components do not compose cleanly, then all you are doing is shifting complexity from inside a component to the connections between components. Not just does this just move complexity around, it moves it to a place that's less explicit and harder to control.
이러한 상황이 발생할 수 있습니다. 단일한 단순한 서비스 내부는 좋아 보이지만, 서비스 간의 잡다한 연결은 무시됩니다:
It's easy to think things are better when you are looking at the inside of a small, simple component, while missing messy connections between services.
참고 자료
-
"마이크로서비스"블로그 중국어 번역 완전판: 위 글의 중국어 번역판
-
[I don't understand micro-frontends.](https://medium.com/ @lucamezzalira/i-dont-understand-micro-frontends-88f7304799a9)
아직 댓글이 없습니다