1. Background
웹 기반 분산 시스템의 디자인에 많이 반영되는 Architecture Style, 분산 웹 시스템의 구조가 유사하게 설계되었다. MSA를 이해하기 위해서 먼저 모노리틱 아키텍쳐에 대한 이해가 필요하다.
2. Monolithic Architecture
하나의 어플리케이션 내에 모든 로직이 들어가 있다. example) 온라인 쇼핑몰 어플리케이션이 있을 때, Tomcat 서버 내부의 WAR(Web application package)에 사용자 관리, 상품 관리, 주문 관리 등 모든 컴포넌트들이 들어있고 이를 처리하는 프론트엔드 로직까지 하나로 포장되어 들어가 있는 구조
각 컴포넌트들은 함수를 이용한 Call-by-reference 구조로 상호 호출한다.
- 장점 : 전체 어플리케이션을 하나로 처리하기 때문에, 하나의 어플리케이션만 개발하면 되고, 배포 및 테스트 또한 하나의 어플리케이션에 대해서 이루어지기 때문에 편리하다.
- 단점
- 서비스의 규모가 커졌을 때, 빌드 및 배포 시간, 서버의 기동 시간이 오래 걸린다.
- 한 명의 실수로도 전체 시스템의 빌드가 실패할 수 있기 때문에, 여러 사람의 협업 개발이 쉽지 않다.
- 시스템 컴포넌트들이 서로 로컬 콜(Call-by-reference) 기반으로 강하게 연결되어 있기 때문에 전체 시스템의 구조를 제대로 파악하지 않으면, 다른 컴포넌트에 부작용(Side Effect)을 유발할 수 있고, 규모가 커질 수록 모든 개인이 전체 시스템의 구조를 이해하는 것은 매우 어렵다.
- 특정 컴포넌트를 수정했을 떄, 전체 어플리케이션을 다시 빌드하여 배포해야 하기 때문에 배포가 잦은 시스템에 불리하다.
- 컴포넌트 별로 기능적 특성에 맞춰 다른 기술을 도입하고자 할 때, 유연하지 못하다.
상황과 필요에 따라서 그에 맞는 아키텍쳐 설계를 적절히 해야하지만, 서비스의 규모가 커질수록 모노리틱 아키텍쳐는 불리한 점이 많다.
3. Micro Service Architecture
SOA(Service Oriented Architecture)를 근간으로 대용량 웹 서비스가 늘어나면서 대용량 웹 서비스 개발에 맞는 구조로 경량화되고, 대규모 개발 팀의 조직 구조에 맞도록 변형된 아키텍쳐
(1) Architecture Structure
- 서비스 : MSA에서 각 컴포넌트는 서비스라는 개념으로 정의된다. 서비스는 데이터에서부터 비즈니스 로직까지 독립적으로 컴포넌트 간의 상호의존성 없이 개발(수직적 분할 : Vertical Slicing)된 컴포넌트로 REST API와 같은 표준 인터페이스로 그 기능을 외부에 제공한다.
- 서비스 경계는 구문 또는 도메인(업무)의 경계를 따른다.
- 예를 들어, 사용자 관리, 상품 관리, 주문 관리와 같은 각 업무 별로 서비스를 나눠 정의한다. 사용자 및 상품 관리처럼 여러 개의 업무를 동시에 하나의 서비스로 정의하지 않는다.
- REST API에서 /users, /products와 같은 URI가 서비스 정의의 범위로 좋은 예시이다.
- MSA Structure
-
각 컴포넌트는 서비스라는 형태로 구현되고 API를 이용하여 타 서비스와 통신을 한다.
-
배포 관점에서도 각 서비스는 독립된 서버로 타 컴포넌트와의 의존성 없이 독립적으로 배포된다. 가장 큰 특징은 어플리케이션 로직을 분리해서 여러 개의 어플리케이션으로 나누어 서비스화하고, 각 서비스 별로 톰캣을 분산 배치한 것이다.
사용자 관리 서비스는 독립적인 war 패키지로 개발되어, 독립된 톰캣 인스턴스에 배치된다. 확장을 위해서 서비스가 배치된 톰캣 인스턴스는 횡적으로 스케일(인스턴스 수 증가)이 가능하고, 앞단에 로드 밸런서를 배치하여 서비스 간의 로드를 분산시킨다.
-
- 데이터 분리
- 데이터 저장 관점에서는 중앙 집중화된 하나의 데이터베이스를 사용하는 것이 아니라 서비스 별로 별도의 데이터베이스를 사용한다. 보통 모노리틱 서비스 아키텍쳐의 경우에는 하나의 데이터베이스를 사용하는 것이 일반적이지만, MSA의 경우 서비스가 API에서부터 데이터베이스까지 분리되는 수직 분할(Vertical Slicing) 원칙에 따라서 독립된 데이터베이스를 갖는다.
- 그래서 데이터베이스 종류가 서로 다른 데이터베이스들을 사용할 수 있다.
- 하지만, 다른 컴포넌트의 데이터를 API 통신을 통해서만 가지고 올 수 있기 때문에 성능 상의 문제를 야기할 수 있고 이종의 데이터베이스 간의 트랜잭션을 묶을 수 없다는 문제점이 있다.
- API Gateway
- API들 앞에서 모든 API에 대한 End Point를 통합하고, 여러 가지 추가 기능을 제공하는 미들웨어
- SOA의 ESB의 경량화 버전
- 기능
- End Point 통합 및 Topology 정리
- MSA의 문제점 중 하나는 각 서비스가 다른 서버에 분리 배포되기 때문에 API의 End Point(서버의 URL)가 다르다는 것이다.
- API UX 관점에서도 불편하다.
- 컴포넌트를 되도록 업무 단위로 작게 분할하는 작은 규모의(fine grained) 서비스를 지향하는 MSA의 특성 상 API의 수가 많을 수 밖에 없다.
- 때문에 API를 사용하는 클라이언트에서 서버 간의 통신, 서버 간의 API 통신의 경우 P2P(Peer To Peer) 형태로 topology가 복잡해지고 거미줄 모양의 서비스 컴포넌트 간의 호출 구조는 문제를 일으킬 가능성이 높다.
- 이러한 문제점을 해결하기 위해서 중앙에 서비스 버스와 같은 역할을 하는 채널을 배치하여, 전체 topology를 P2P에서 Hub & Spoke 방식으로 변환시켜 서비스 간 호출을 단순화하는 기능이 있다.
- Orchestration
- 여러 개의 서비스를 묶어서 하나의 새로운 서비스로 만드는 개념
- ex : 물품 구매 + 포인트 적립
- 그러나, Orchestration을 API Gateway 계층에서 하는 것은 Gateway 입장에서 매우 부담되는 일이다. 다시 말해, API Gateway에서 과도한 Orchestration 로직을 수행하는 것은 전체적인 성능 저하를 유발한다.
- 그래서 Orchestration 기능의 활용은 MSA와 API Gateway에 대해 높은 수준의 기술적인 이해를 수반한다.
- 공통 기능 처리 (Cross cutting function handling)
- API에 대한 인증(Authentication), Logging 등 공통 기능을 처리할 수 있다.
- Mediation
- XML이나 Native Message Format을 json 등으로 상호 변환해주는 message transformation 기능
- 프로토콜 변환 기능
- 서비스 간의 메시지를 라우팅하는 기능
- 등등 여러 개의 고급 Mediation 기능을 제공하지만, API Gateway를 최대한 가볍게 한다는 설계 원칙 아래서 반드시 필요한 기능들에 대해 높은 이해도, 정확한 설계와 기술적인 노하우를 동반하는 것이 좋다.
- End Point 통합 및 Topology 정리
- 유연한 배포 모델
- 각 서비스가 다른 서비스와 물리적으로 완벽하게 분리되기 때문에 변경이 있는 서비스 부분만 부분적으로 재배포가 가능하다.
- 모노리틱 아키텍쳐보다 빠르고 효율적이고 전체 시스템의 영향도를 최소화하는 재배포가 MSA의 큰 장점 중 하나이다.
- 유연한 확장 모델
- 서비스 별로 독립된 배포 구조는 부하가 많은 특정 서비스에 대해서만 확장이 가능하여 조금 더 유연한 확장 모델을 가질 수 있다.
- Conway’s Law (컨웨이의 법칙)
- ‘소프트웨어의 구조는 그 소프트웨어를 만드는 조직의 구조와 일치한다.’
- MSA는 Architecture Style의 조직 구조나 팀 운영 방식에 영향을 미친다.
- MSA는 각 컴포넌트를 팀에 배치해서 책임지고 개발하는 것을 기반으로 하고, 팀 간의 의존성을 제거해 각 팀이 독립적으로 컴포넌트를 개발할 수 있다.
(2) 문제점
- 성능
모노리틱 아키텍쳐는 하나의 프로세스 내에서 서비스 간의 호출을 Call-by-reference 모델을 이용한다. 반면, MSA는 서비스 간의 호출을 API 통신을 이용하기 때문에 값을 json이나 XML에서 프로그래밍에 사용되는 데이터 모델(Java Object etc..)로 변환하는 Marshalling 오버헤드가 발생하고 호출을 위해서 이 메시지들이 네트워크를 통해서 전송되기 때문에 그만큼의 시간이 추가로 더 소요된다.
- 비동기 패턴, 캐싱 등 해결 방법이 다양하다.
- 메모리 각 서비스를 독립된 서버에 분할 배치하기 때문에, 중복되는 모듈에 대해서 메모리 사용량이 증가한다.
성능과 메모리 문제는 반드시 발생하지만, 현대의 컴퓨팅 파워가 상당히 발달했다는 점과 네트워크 또한 성능 상 많은 발전이 있었기 때문에 기존에 비해 상대적으로 크게 문제가 되지 않는다.
- 어려운 테스팅 서비스들이 각각 분리되어 있고 다른 서비스에 대한 종속성을 갖기 때문에, 특정 사용자 시나리오나 기능을 테스트하고자 하는 경우 여러 서비스에 걸쳐서 테스트를 진행해야 하기 때문에 테스트 환경 구축, 문제 발생 시 분리된 여러 개의 시스템을 동시에 살펴봐야 하기 때문에 테스팅의 복잡도가 오를 수 밖에 없다. 운영의 관점에서는 서비스 별로 서로 다른 기술을 사용할 수 있어 필요한 기술의 수가 늘어날 수 있고, 시스템이 아주 작게 서비스 단위로 분할되기 때문에 운영해야 할 시스템 개수가 늘어나게 된다.
- 서비스 간 트랜잭션 처리
API 기반의 다수의 서비스를 하나의 트랜잭션으로 묶는 것은 불가능하다. (MSA 기반이 되는 기존의 SOA에도 있었던 문제)
- 해결 방안
- 분산 트랜잭션 시나리오 자체를 없앤다.
- 분산 트랜잭션이 꼭 필요하다면, 그 부분만 모노리틱 아키텍쳐로 설계한다.
- 위의 방안이 싫다면, 트랜잭션 처리 시에 발생하는 에러 로직을 직접 구현해야 한다. - 보상 트랜잭션 (Compensation Transaction)
- 트랜잭션으로 묶어 처리해야 하는 다수의 시스템을 트랜잭션을 지원하는 native protocol을 이용해서 구현한 다음, 이를 하나의 API로 제공하는 복합 서비스(Composite Service)를 만든다.
- 그러나 이 방법도 서로 다른 다수의 시스템에 걸쳐 강한 결합(tightly coupled)이 생기기 때문에, MSA의 Isolation(상호 독립)의 원칙에 위배되고 서비스 변경 시에 이 부분을 항상 고려해야 하기 때문에 유연성이 훼손된다는 단점이 있기 때문에 꼭 필요한 경우가 아니라면 사용하지 않는 것이 좋다.
- 해결 방안
(3) Governance Model
- Governance : 시스템을 개발하는 조직의 구조나 프로세스를 정의한 것
- 일반적으로 중앙 집중화된 조직에서 표준 프로세스와 가이드를 기반으로 전체 팀을 운용하는 모델을 사용한다. (중앙 집중형 거버넌스 모델 : Centralized Governance Model) - 전통적인 개발 모델
- 이 경우, 전체 시스템이 동일한 프로세스와 기술을 가지고 개발을 하기 때문에 유지보수가 용이하고 팀 간의 인원 교체 등이 원활하다는 장점이 있다.
- 현대의 웹 개발의 경우, 오픈 소스의 발달로 선택 가능한 기술들이 많고 각 요구 사항에 따라서 효율성 측면 등 특성들을 고려할 때 각각 최적화된 기술을 사용하는 것이 좋은 경우가 있다.
- 이 경우에는 중앙 집중형 거버넌스 모델에서는 모든 개발 팀을 교육시키고 운영 또한 준비를 해야하기 때문에 기술에 대한 적용 민첩성이 떨어진다.
- 이러한 문제점을 해결하는 것이 분산형 거버넌스 모델(De-centralized Governance Model)이다.
- 각 팀이 독립적인 프로세스와 기술 선택 권한을 갖는다.
- 각 서비스가 표준 API로 기능을 외부로 노출할 뿐, 내부적인 기술 구현 구조는 추상화된다.
- 분산형 거버넌스 모델을 수행하기 위한 팀 구조의 특징
- Cross Functional Team
- 기존의 팀 모델은 역할 별로 공통적인 특성으로 나뉘어진 모델로 팀을 기획한다. (기획, UX, 개발, 인프라 운영 등)
- 유연한 리소스의 운영
- 팀 간의 커뮤니케이션이 원활하지 않아 협의에 걸리는 시간으로 인해 팀의 운영 속도가 저하된다.
- Cross Functional Team 모델은 하나의 팀에 기획, UX, 개발, 인프라 운영 등 소프트웨어 시스템을 개발하는데 필요한 모든 역할을 하나의 팀에 구성하고 움직이는 모델. 각각의 서비스가 팀을 나누는 기준
- 다른 팀에 대한 의존성이 없어져 빠른 서비스 개발이 가능하다.
- 기존의 팀 모델은 역할 별로 공통적인 특성으로 나뉘어진 모델로 팀을 기획한다. (기획, UX, 개발, 인프라 운영 등)
- You Build, You Run Devops
- Devops (Development + Operation) : 개발과 운영을 하나의 조직에 합쳐놓는 구조
- 개발과 운영이 분리되어 발생하는 의사소통의 문제점을 해결하고 개발이 운영을 고려하고 운영에서 발생하는 문제점과 고객의 피드백을 빠르게 수용하여 서비스 개선에 반영하는 모델
- 운영 팀만의 고유 영역이었던 인프라에 대한 핸들링이 클라우드의 도입으로 쉬워져 개발자도 웹 사이트를 통해 디스크나 네트워크 설정, 서버 설정 등이 쉽게 가능해졌기 때문에 가능해진 모델
- 개발자가 어플리케이션 개발 뿐만 아니라, 인프라에 대한 설계 및 운영까지 담당해야 하기 때문에 이 모델 역시 높은 수준의 이해도가 수반된다.
- Devops (Development + Operation) : 개발과 운영을 하나의 조직에 합쳐놓는 구조
- Project vs Product
- 분산형 거버넌스 모델에서 중요한 점 중 하나는 팀원의 영속성이다. 거버넌스를 분산시켰기 때문에 팀 별로 다른 형태의 표준과 기술 프로세스를 통해서 개발을 하기 때문에 일정 기간에 정해진 요구 사항을 개발하여 프로젝트가 끝나고 흩어지는 프로젝트, 역할 중심의 팀 모델보다는 상품 전체에 대해 요구 사항 정의 발굴에서부터 개발, 운영까지 책임을 지는 상품 중심의 개발 팀 모델이 적절하다.
- Self-organized Team : 팀 스스로 기획, 개발, 운영하며 독립적인 수행 능력을 가지고 있는 팀 모델
- Alignment
- 각 팀 간의 커뮤니케이션 방법, 프로세스 등 최소한의 표준과 기술적인 수준을 맞추는 과정
- MSA는 각 서비스들이 상호 의존성을 갖기 때문에 개발 경험이 없는 팀이 있다면 전체 팀의 개발 속도를 따라오지 못할 수도 있고 품질에도 심각한 문제를 야기할 수 있다.
- 그래서 일정 수준 이상으로 팀의 능력을 끌어올리고 전체 팀에서 사용하는 최소한의 공통 프로세스 등에 대해서 맞추는 것을 Alignment라고 한다.
- 전체 팀이 나아가야 할 방향과 비즈니스 밸류, 팀 간의 커뮤니케이션 방식, 전체 시스템 구조에 대해 이해해야 하고 이를 바탕으로 모든 역할을 갖추고 있고 빠르고 효율적인 개발 팀을 운영하는 것이 목표이다.
- Cross Functional Team
- 일반적으로 중앙 집중화된 조직에서 표준 프로세스와 가이드를 기반으로 전체 팀을 운용하는 모델을 사용한다. (중앙 집중형 거버넌스 모델 : Centralized Governance Model) - 전통적인 개발 모델
4. Evolutionary Model (진화형 모델)
처음부터 시스템을 MSA로 설계하고 구현하는 것보다 모노리틱 아키텍쳐부터 시작해 비즈니스 운용 시 발생하는 문제점, 비즈니스와 고객의 피드백 등을 점진적으로 반영하고 동시에 팀의 성숙도를 올리면서 단계적으로 시스템의 아키텍쳐 스타일을 변화시켜 나가는 진화형 모델이 더 좋은 모델이 될 수 있다.