Monolithic Architecture
요즈음 개발트렌드가 MSA(Micro Service Architecure)
라고 해서, MSA
와 반대되는 개념인 Monolithic(Monolithic Architecture)
보다 무조건 좋다고는 할 수는 없습니다.
MSA
도 특정한 상황속에서 탄생한 한가지의 소프트웨어 설계 패턴입니다.
작은 시스템에서의 Monolithic
의 경우 여러 비즈니스 로직, 여러 코어 시스템, 여러 커넥션, 클라이언트 서비스 등을 하나의 프로그램에 통합하여 개발 함으로써 다음과같은 이점을 얻을 수 있었습니다.
- 간단한 개발
- 편리한 테스트
- 간단한 배포
- 간단한 확장
위의 이점들은 작은 규모의 프로젝트 혹은 프로토타입 작업을할때 생산성을 최대로 만들어 줄 수 있습니다. 하지만, 서비스 규모가 커지거나 트래픽이 감당할수 없을정도가 된다면 위의 이점들은 다음과같이 변하게 될 것입니다.
- 여러명의 개발자들이 작업하기 복잡한 느린 개발 환경
- 프로그램 내에서 많은 연관관계를 갖는 코드들로 인한 테스트의 어려움
- 여러서비스들이 함께 영향을 받는 배포
- 서비스별 최적의 요구사항을 맞추기 힘든 확장성
위와같은 기존 Monolithic
의 한계 상황속에서 MSA
가 해결책 으로 생겨나게 되었습니다. 이렇게 탄생한 MSA
는 다음과 같은 특성을 갖고 있습니다.
- 기능별 선택적으로 확장이 용이한 확장성
- 기능별 분리, API 제공을 통한 모듈성
- 서비스별 별도의 DB를 갖음
MSA 분해 전략
그렇다면 기존 Monolithic
에서 MSA
로 전환하기 위해서는 어떻게 해야할까요? MSA
로 전환 하기 위해 고려해야 할것들을 먼저 나열 해 보도록 하겠습니다.
- 하나의 시스템을 여러개의 서비스로 어떻게 분해 할 것인가?
- 각 서비스간에 어떻게 통신 할 것인가?
- 서비스간의 트랜잭션을 어떻게 유지 할 것인가?
- 데이터를 어떻게 조합하여 사용 할 것인가?
- 서비스들을 어떻게 배포 할 것인가?
- 각 서비스들간의 상태변화를 어떻게 확인 할 것인가?
- 서비스들의 테스트를 어떻게 할 것인가?
- 서비스들의 공통된 관심사들을 어떻게 처리 할 것인가?
- 여러 서비스들의 보안을 어떻게 설정 할 것인가?
분산 환경 시스템이 되면서 기존 Monolithic
에서는 쉽게 해결 되던 것 들이 해결해야할 새로운 숙제로 나타났습니다.
MSA
도입을 시도해 보신 분이라면 아시겠지만, 위 여러 사항들 중에서도 가장 어려운것은 '시스템을 어떻게 쪼갤것인가?'
일 것 입니다.
그도 그럴것이 MSA
가 서비스를 기능분해하여 여러개의 서비스로 구성된 아키텍쳐를 의미하는 것 이지, 어떻게 서비스를 분해할것에 대한 정의를 내리는 것은 아니기 때문일 것 입니다.
그렇다면 우리 서비스를 MSA
로 전환하기 위해 기능분해를 쉽게 접근하는법에 대해서 알아보도록 하겠습니다.
MSA 정의하기
예제 프로젝트로써, 커머스 업계의 서비스인 Catalog
서비스를 예시로 들어보도록 하겠습니다.
(모르시는 분들을 위해 간략하게 설명 드리자면, Catalog
서비스는 여러 판매자들이 판매중인 같은 상품들에 대해서 동일한 대표상품으로 묶어 주는 서비스를 뜻합니다.)
Step1. 시스템 작업 정리하기
프로젝트를 설계할 때 처럼 User story
들을 정리해보는 단계입니다. User story
를 정리 함으로써 시스템에 어떤 기능들이 행해지는지 나열 해 볼수 있을 것 입니다.
관리자
로써다양한 조건들로 상품검색을 해서 일반상품과 EP 상품들을 조회 하고 싶다
.관리자
로써카탈로그에 매칭된 상품들을 조회
하고 싶다.관리자
로써신규 카탈로그 등록 및 카탈로그의 정보를 수정
하고 싶다.관리자
로써특가 대상 카탈로그를 설정
하고 싶다.MD
로써 내가 관리중인 상품을카탈로그에 등록
하고 싶다.판매자
로써 판매하고자 하는 상품의카탈로그를 조회
해보고 싶다.판매자
로써 내가 등록한 상품을카탈로그에 등록
하고 싶다.판매자
로써 내 상품을 카탈로그 내에서가장 낮은 가격의 품목으로 등록
시키고 싶다.관리자
로써카탈로그에 매칭 요청된 상품을 승인
하고 싶다.구매자
로써 카탈로그중가장 낮은 가격의 상품을 조회
하고 싶다.- …
위 리스트를 정제해보면 아래와같은 기능요건
들로 추려볼 수 있을것 같습니다.
- 일반 상품 조회
- EP 상품 조회
- 상품을 카탈로그에 등록
- 카탈로그 매칭 상품 조회
- 카탈로그 매칭 요청
- 카탈로그 매칭 승인
- 카탈로그 조회
- 카탈로그 정보 등록 및 수정
- 카탈로그내 상품 가격비교
- 특가 카탈로그 설정
- …
Step2. 서비스 정리하기(책임영역 나누기)
위에서 어떤 작업들이 필요한지를 정의 하였으니, 서비스화 시킬 후보들을 정해볼 단계입니다.
작업들을 공통된 서비스로써 정리하기 위해서는 객체지향 설계와 비슷하게 아래의 원칙에서 서비스 후보들이 선정되어야 합니다.
SRP(단일책임원칙)
: 객체지향 클래스를 생성 할 때 처럼, 서비스가 하나의 책임을 갖도록 정의해야 합니다.CCP(공동폐쇄원칙)
: 동일한 변경점이 있는 클래스들은 동일한 패키지로 구성하는 것 처럼, 여러 서비스에서 사용되는 내용의 경우 별도의 서비스로 분리하여 별도의 서비스로 만들거나 여러 서비스를 하나의 서비스로 합치는것을 고려 할 수 있습니다.
특히나 이 단계에서는 DDD(Domain drvien Design)
의 sub-domain
과 bounded context
를 통해 정리해보면 서비스를 나누는데 도움이 될 수 있습니다.
DDD
를 통해 우리의 Catalog 서비스
도메인을 구성하는 하위도메인
을 찾아내야합니다. 하위도메인은 해당 서비스가 비즈니스적으로 구별 될 수 있는도메인으로 나누어주면되는데, 이를 위해 Catalog 서비스
를 비즈니스적으로 접근하여 어떤 작업들을 필요 한 지 나열 해 보도록 하겠습니다.
- 카탈로그 관리
- 카탈로그 생성/삭제
- 카탈로그 속성 관리
- 카탈로그 조회
- 카탈로그 매칭
- 카탈로그 매칭 상품 조회
- 일반상품 조회
- EP상품 조회
…
위와같은 정리를 통해
Catalog 서비스
의 하위도메인은
- 카탈로그
- 일반 상품
- EP 상품
위처럼 각각의 전문영역의 도메인으로 구성시켜 줄 수 있을것입니다.
위의 설정된 하위도메인들은 결국 MSA 분해 대상이되는 서비스 후보들이라고 정리 할 수 있겠습니다.
- 카탈로그 서비스
- 일반 상품 서비스
- EP 상품 서비스
Step3. 서비스 API 및 서비스간 호출 정의하기
위 단계들을 통해 시스템 작업과 서비스가 도출 되었으니 시스템 작업들을 정의된 서비스들에게 배정 해 주도록 하겠습니다.
서비스 | 시스템작업 |
---|---|
카탈로그 서비스 | - searchCatalog() - getCatalogInfo() - matchProducts() - matchEPProducts() - findLowestProduct() … |
일반상품 서비스 | - searchProducts() - … |
EP상품 서비스 | - searchEPProducts() - … |
작업들이 하나의 서비스들에 매칭이 되었으나, 하나의 도메인 서비스만으로 해결 할 수 없는 API 들이 있을것입니다. 이 경우 다른 서비스의 호출을 통해 작업이 이루어져야 하는데 데이터 조합 및 트랜잭션등을 미리 확인 하기 위해 서비스간에 호출이 필요한 API들을 정리 해 주어야 합니다.
서비스 | 시스템작업 | 협동작업 |
---|---|---|
카탈로그 서비스 | matchProduct() | 일반상품 서비스 - verifyProduct() 일반상품 서비스 - updateCatalogMatchingInfo() |
카탈로그 서비스 | matchEPProduct() | EP상품 서비스 - verifyProduct() |
카탈로그 서비스 | findLowestProduct() | 상품 서비스 - getProductsPrice() |
… | … | … |
위와같이 서비스들간의 필요한 협동작업들을 나열해보면 조인이 필요한 데이터 혹은 트랜잭션이 필요한 api들을 미리 정의하여 시스템 분해 전략을 세울 수 있게 될 것 입니다.