💡
아키텍처 스타일(모놀리식 vs 마이크로서비스)에 대한 선택은 트렌드나 경쟁사의 특징을 따르기보다, 소프트웨어의 목표와 비즈니스 요구 사항에 따라 달라진다. 모놀리식은 소프트웨어 개발을 위한 기본 접근 방식이지만, 마이크로서비스 아키텍처가 대세로 떠오르면서 여러 프로젝트에 활발하게 채택되고 있다. 그러면 현재 모놀리식 접근 방식을 버려야 할까? 각각의 이점은 무엇일까? 비교하며 살펴보자!
MA : Monolithic Architecture
전통적인 개발 방식으로, 하나의 프로젝트에 모든 기능을 함께 포함한다.
Monolithic : 단단히 짜여 하나로 되어 있는
모든 프로세스가 긴밀하게 결합되고 단일 서비스로 실행된다는 의미의 'Monolithic'이다. 따라서 애플리케이션의 한 프로세스에 대한 수요가 급증하면 해당 아키텍처 전체를 확장해야 한다.
아래와 같이, 모놀리식 서비스 아키텍처에서 여러 비즈니스 로직들을 담은 시스템은 하나의 DB와 하나의 애플리케이션과 상호작용한다.

서버 환경, DB 환경이 하나이기에 환경 세팅에 시간 소요가 상대적으로 적고, 환경을 고려한 개발이 쉽다.
구현이 쉽고, 덜 복잡하다.
모든 코드가 단일 코드베이스에 있다. 변경 사항이 발생할 경우 코드가 한곳에 존재한다는 의미이다. 이로써 배포도, 디버깅 및 테스트도 수행이 쉽다.
모든 기능들이 하나의 시스템에서 동작하므로, 모든 기능들에 대한 테스트(End to End)를 하기 쉽다.
E2E 테스트
End-To-End Test : 시스템의 시작부터 끝까지 전체 흐름을 확인하는 테스트 유형
기능이 많아진다는 것은 하나의 프로젝트에 코드들이 무수히 많아진다는 것을 의미한다. 코드가 많아지면 코드를 이해하고 해석하고 개발하는데 시간이 오래 걸리는 것을 의미한다. 이는 유지 보수가 어려워진다고 할 수 있다.
기능 하나의 아주 작은 일부만 수정해도 전체를 다시 빌드하고 배포해야 한다. 만약 시스템의 크기가 크다면 빌드 및 배포 시간이 늘어난다는 것을 의미한다. 이는 버그나 수정사항의 즉시 적용이 어렵다는 점을 내포한다.
기능 일부의 오류가 시스템 전체에 영향을 미친다. 기능 하나에서 발생한 오류로 시스템 자체가 다운될 수 있다는 것이다. 트래픽이 급증하게 되면 전체 시스템에 영향을 미치는 것까지 생각할 수 있다.
대규모 팀 작업이 어렵다. 모든 팀이 동일한 코드, 동일한 프로젝트에서 작업하기 때문에 코드 병합에 대한 충돌 가능성이 높고, 기능 변경 시 다른 팀이 작업에 영향을 줄 수 있다.
기능별로 알맞은 기술, 언어, 프레임워크를 선택하기가 까다롭다.
MSA : MicroService Archtecture
서비스가 커지면 커질수록 시스템이 무거워지는 모놀리식의 단점을 해결하기 위해 등장한 아키텍처이다. 하나의 큰 애플리케이션을 여러 개의 작은 서비스 유닛으로 쪼개어 변경과 조합이 가능하도록 만들어, 각각이 독립적인 DB를 가진다. 각 서비스는 REST API를 사용하여 잘 정의된 인터페이스를 통해 서로 통신한다.
마이크로서비스(microservice)는 애플리케이션을 느슨하게 결합된 서비스의 모임으로 구조화하는 *서비스 지향 아키텍처(SOA) 스타일의 일종인 소프트웨어 개발 기법이다.
서비스 지향 아키텍처?
SOA - Service-Oriented Architecture
: 애플리케이션 구성요소가 통신 프로토콜을 통해 다른 구성요소에 서비스를 제공하는 아키텍처 접근 방식
아래 그림과 같이 MSA 아키텍처를 사용한 환경에서, 여러 비즈니스 로직은 기능(모듈)별 각자의 DB 환경을 가지고, 모듈 별로 애플리케이션과 독립적으로 통신한다.

제대로 설계된 마이크로서비스는 하나의 비즈니스 범위에 맞춰 만들어지므로 하나의 기능만 수행한다. 즉, 하나의 목표를 향해 일하지만 자기가 개발하는 서비스만 책임진다.
마이크로서비스는 SOA에서 사용되는 집중화된 관리 체계를 사용하지 않는다. 마이크로서비스 구현체의 공통적인 특징 중 하나는 ESB(Enterprise Service Bus)와 같은 무거운 제품에 의존하지 않는다는 점이다. REST 등 가벼운 통신 아키텍처, 또는 Kafka 등을 이용한 message stream을 주로 사용한다.
서비스별 시스템이 독립적으로 구성되어 있어, 그만큼 하나의 기능을 개발할 때 봐야 할 코드의 수도 적으며, 이해하기 쉽다. 즉 적고 작은 만큼 유지보수하기 쉽다.
서비스별 개별 배포가 가능하여 배포 시 전체 서비스의 중단이 없다.
각 기능에 맞는 언어, 데이터베이스, 그리고 프레임워크를 선택할 수 있다.
서버 및 프로세스 장애 발생 시, 격리 및 복구가 쉬워 장애가 전체 서비스로 확장될 가능성이 적다.
여러 모듈들이 분산되어 있어 관리 및 모니터링(트랜잭션 관리, 장애 추적 및 테스트 등)이 쉽지 않다.
서비스 간 호출 시 REST API 사용으로 인한 통신 비용, Latency(지연시간)가 증가한다.
→ 모놀리식일 경우 단순히 같은 시스템 내부에서의 method 호출,
→ but, MSA 일 경우, http 통신 등을 통해 호출해야 한다.
모듈별로 애플리케이션과 통신하므로 다양한 통신에서 발생하는 오류가 상대적으로 잦다.
서비스마다 DB가 분리되어 데이터의 조회가 어렵고 데이터의 중복이 발생한다.
하나의 시스템의 동작을 모두 확인하는 통합 테스트를 End-to-End로 진행하기 위해선 각각의 마이크로 모듈들과 UI, Gateway를 구동시켜야 한다. 즉, 상대적으로 통합테스트 하기 어렵다.
확장성은 마이크로서비스에서만 유효할 것 같지만, 모놀리식도 확장이 가능하다. 다만 모놀리식 아키텍처는 여러 복사본을 배포하는 형태로 확장하는 방식이다. 반면 마이크로 서비스 아키텍처는 분산 시스템을 지원하기에 수요에 따라 독립적으로 확장이 가능하다.
앞서 모놀리식 아키텍처는 복잡성이 낮다고 설명했다. 이에 비해 마이크로서비스는 소프트웨어의 복잡성에 따라 소스 코드, 프레임워크 및 기술이 포함되고, 여러 서비스가 API를 통해 서비스 간 통신하는 형태로 구축된다. 그래서 전체 아키텍처에 대한 높은 수준의 관리와 기술에 대한 이해가 필요하다
마이크로 서비스는 다른 서비스와 통신할 때, 네트워크를 통해 데이터를 보내거나 받는다. 반면 모놀리식은 모든 서비스가 동일한 코드베이스 내에 있기 때문에 네트워크 대기 시간이 발생하지 않는다. 이런 이유로 마이크로서비스는 모놀리식보다 느리다.
모놀리식은 단 하나의 서버로 구성된다. 즉, 장애가 발생하면 전체 애플리케이션이 다운된다. 반면 마이크로서비스는 하나가 실패하면 장애 격리를 통해 애플리케이션을 유지할 수 있다.
다음은 모놀리식과 마이크로서비스를 비교한 표이다.

가장 적합한 아키텍처를 선택하려면 다음의 요소들을 고려해야 한다.
이러한 것을 잘 고려해, 애플리케이션이 크고 복잡해질 가능성이 있고, 팀이 도메인에 대해 잘 알고 있고, 소프트웨어가 가용성과 확장성을 갖춰야 하고, 마이크로서비스에 대한 경험이 있다는 것에 모두 해당된다면 마이크로서비스 아키텍처가 더 적합할 것이다!
💡
MSA를 모놀리식 아키텍처와 비교하자면 위와 같은 개념들로 설명이 충분하다. 그러나 MSA는 아주 복잡하고 어려운 구조인 만큼 자세히 파헤쳐 보면 그 개념이 아주 복잡하다. 하나씩 살펴보자.

MicroService Architecture는 크게 Inner Architectur와 Outer Architecture로 구분할 수 있다. 그림에서 짙은 남색 부분은 Inner Architecture, 회색은 Outer Architecture의 영역이다.
Inner architecture는 내부 서비스와 관련된 아키텍처이다. 쉽게 말해, 내부의 서비스를 어떻게 잘 쪼개는지에 대한 설계이다.
Inner architecture에서 고려해야 할 사항
Inner architecture는 비즈니스마다, 서비스마다, 시스템마다 각각의 특성이 있기 때문에 표준이 없다. 따라서 이 부분은 MSA를 설계하는 데에 가장 어려운 부분이기도 하다.
맨 위의 그림에서와 같이 Gartner에서는 MSA의 Outer architecture을 총 6개의 영역으로 분류하고 있다.
External Gateway는 전체 서비스 외부로부터 들어오는 접근을 내부 구조를 드러내지 않고 처리하기 위한 요소이다. 인증 및 인가를 수행하며, API Gateway가 여기서 가장 핵심적인 역할을 담당한다.
API Gateway는 서버 최앞단에 위치하여 모든 API 호출을 받는다. 받은 API 호출을 인증한 후, 적절한 서비스들에 메시지를 전달될 수 있도록 하는 방식이다.
Service Mesh는 마이크로서비스 구성 요소 간의 네트워크를 제어하는 역할을 한다.
서비스 간에 통신을 하기 위해서는 service discovery, service routing, 트래픽 관리 및 보안 등을 담당하는 요소가 있어야 하는데, Service Mesh가 이러한 기능을 모두 수행하는 것이다.
서비스가 다양한 환경에 배포 및 실행할 수 있도록 환경을 구성하는 역할을 맡는다.
대표적으로 Kubernetes가 많이 사용되고 있으며, Container 기반의 운영을 위해서는 요즘은 k8s(쿠버네티스)가 필수라고 여기는 추세이다.
Backing Service는 애플리케이션이 실행되는 가운데 네트워크를 통해서 사용할 수 있는 모든 서비스를 말하며, My SQL과 같은 데이터베이스, 캐시 시스템 등 애플리케이션과 통신하는 attached Resource들을 지칭하는 포괄적인 개념이다.
MSA의 대표적인 Backing service는 Message queue이다. 이로써 메시지의 송신자와 수신자가 직접 통신하지 않고 메시지 큐를 활용하여 비동기적으로 통신하는 것을 지향한다.
메시지 큐를 사용하지 않을 경우, 여러 마이크로서비스에 걸치는 실시간 트랜잭션을 처리할 때, 하나의 서비스가 죽어버리면 트랜잭션이 끊어지고 해당 서비스 요청을 보존할 수 없어 에러가 발생하게 된다.
Tele(먼 거리) + metry(측정)
: 실시간으로 먼 거리에서 측정할 수 있다.
MSA는 대부분의 마이크로서비스가 분산 환경에서 운영되기에 서비스들의 상태를 일일이 모니터링하고, 이슈에 대응하는 것은 굉장히 힘들다. Telemetry는 서비스들을 모니터링하고, 서비스별로 발생하는 이슈들에 대응할 수 있도록 환경을 구성하는 역할을 한다.
CI/CD는 소프트웨어 개발 단계를 자동화하여, 이를 보다 짧은 주기로 고객에게 제공하는 방법이다.
지속적인 통합(Continuous Integration), 지속적인 전달(Continuous Delivery), 지속적인 배포(Continuous Deployment)가 CI/CD의 기본 개념으로, 이를 자동화하는 것은 배포가 잦은 MSA 시스템에 꼭 필요한 요소 중 하나이다.
📝 정리하기
모놀리식 아키텍처란 하나의 프로젝트에 모든 기능을 함께 포함하는 전통적인 구조이고, MSA : MicroService Architecture는 하나의 큰 서비스를 작은 서비스 유닛으로 쪼개어 변경과 조합이 가능하도록 만든 구조이다✨