13장, 서비스 기반 아키텍처 스타일

2022.07.20

서비스 기반 아키텍처(service-based architecture)는 마이크로서비스 아키텍처 스타일의 일종으로, 아키텍처가 유연해서 가장 실용적인 아키텍처 스타일 중 하나이다. 마이크로서비스나 이벤트 기반 아키텍처와 마찬가지로 분산 아키텍처지만 비교적 덜 복잡하고 비용이 많이 들지 않아서 많은 비지니스 관련 애플리케이션에 널리 채택된 아키텍처이다.

13.1 토폴로지

서비스 기반 아키텍처의 기본 토폴로지는 각각 따로 배포된 유저 인터페이스와 원격 서비스, 그리고 모놀리스 데이터베이스로 이루어진 대규모 분산 레이어 구조이다.


이 아키텍처 스타일에서 서비스는 큼지막한 단위로 분리해 별도로 배포하는 애플리케이션의 일부이다(보통 도메인 서비스라고함). 여러 서비스가 단일 모놀리식 데이터베이스를 공유하므로 애플리케이션 서비스는 다 합해도 4~12개, 평균 7개 정도이다.

서비스 기반 아키텍처는 중앙 공유 데이터베이스를 사용한다는 특징이 중요하다. 서비스 개수가 적어서 데이터베이스 커넥션을 대개 문제가 안 되지만 데이터베이스 자체의 변경은 이슈가 될 수 있는데, 서비스 기반 아키텍처에서 데이터베이스 변경 문제를 다루는 기법은 13.4절에서 설명한다.

13.2 토폴로지 변형

서비스 기반 아키텍처 스타일은 특유의 유연성 때문에 정말 다양한 변형이 존재한다. 단일 모놀리식 유저 인터페이스는 다시 여러 유저 인터페이스 도메인으로 나눌 수 있고, 한술 더 떠 각 도메인 서비스에 맞게 나눌 수도 있다.


또, 단일 모놀리식 데이터베이스 역시 개별 데이터베이스로 분리할 수 있고 (마이크로서비스 비슷하게) 각 도메인 서비스 전용 데이터베이스들로 쪼갤 수도 있다.


리버스 프록시 또는 게이트웨이로 구성된 API 레이어를 유저 인터페이스와 서비스 사이에 구성할 수도 있다. 도메인 서비스의 기능을 외부 시스템에 표출하거나 (메트릭, 보안, 감사 요구사항, 서비스 디스커버리 등) 공통 관심사를 통합해서 유저 인터페이스 밖으로 떼어낼 경우에도 유용한 방법 이다.

13.3 서비스 설계 및 세분도

서비스 기반 아키텍처의 도메인 서비스는 보통 단위가 크기 때문에 도메인 서비스를 API 퍼사드 레이어, 비지니스 레이어, 퍼시스턴스 레이어로 구성된 레이어드 아키텍처 스타일로 설계하는 것이 일반적이다. 모듈러 모놀리스 아키텍처 스타일처럼 서브도메인을 이용해서 각 도메인 서비스를 분할하는 방법도 많이 쓰인다.


서비스를 어떻게 설계하든 도메인 서비스는 유저 인터페이스에서 비지니스 기능을 호출하기 위해 접속할 일종의 API 액세스 퍼사드(access facede)를 필요로 한다. API 액세스 퍼사드는 유저 인터페이스를 통해 유입된 비지니스 요청을 오케스트레이트(orchstrate, 조정, 조율)하는 역하을 한다. 예를 들어, 유저 인터페이스에서 주문이 접수되면 이 단건 요청은 OrderService 도메인 서비스의 API 액세스 퍼사드가 받아 내부에서 주문 처리, 주문 ID 생성, 결제 처리를 한 후, 주문이 완료된 제품별 재고 정보를 업데이트하는 일련의 비지니스 요청을 오케스트레이트한다. 이런 요청을 마이크로서비스에서 처리한다면 별도 배포된 다수의 전용 원격 서비스를 오케스트레이트해야 한다. 세분도 관점에서 보면, 내부 클래스 수준의 오케스트레이션과 외부 서비스의 오케스트레이션이라는 차이점이 서비스 기반 아키텍처와 마이크로서비스의 중요한 차이점이다.

도메인 서비스는 세분도가 큰 까다락에 단일 도메인 서비스에서 데이터 무결성을 보장하기 위해 커밋/롤백이 수반되는 여느 ACID(원자성, 일관성, 격리성, 지속성) 데이터베이스 트랜잭션을 사용하지만, 마이크로서비스처럼 분산도가 높은 아키텍처는 서비스를 더 잘게 나누어 BASE 트랜잭션(기본적 가용성 basic availability, 소프트 상태 soft state, 최종 일관성 eventual consistencsy)이라고 알려진 분산 트랜잭션 기법을 사용한다. 이 기법은 그 기반이 최종 일관성이므로 서비스 기반 아키텍처의 ACID 트랜잭션 레벨의 데이터 무결성은 지원하지 않는다.

도메인 서비스는 단위가 커서 데이터 무결성과 일관성 측면에서는 유리하지만ㅁ 그에 못지않은 트레이드오프도 있다. 서비스 기반 아키텍처에서 OrderPlacement의 주문 처리 기능을 변경할 일이 생기면 (결제 처리를 포함하여) 전체 서비스를 테스트해야 하지만, 마이크로서비스 아키텍처에서는 규모가 작은 OrderPlacement 서비스 하나만 변경 영향도가 있을 것이다. 또한 서비스 기반 아키텍처는 코드가 점점 더 많이 배포될수록 (결제 처리를 비롯해) 뭔가 문제를 일으킬 소지가 커지지만, 마이크로서비스 아키텍처는 각 서비스가 한 가지 역할만 수행하므로 변경을 해도 다른 기능이 망가질 일이 거의 없다.

13.4 데이터베이스 분할

서비스 기반 아키텍처에서 데이터베이스 테이블 스키마를 나타낸 공유 클래스 파일(엔티티 객체라고 함)은 전체 도메인 서비스가 함꼐 사용하는 커스텀 공유 라이브러리에 둔다. 엔티티 객체가 공유하는 단일 라이브러리를 생성하느 프랙티스는 서비스 기반 아키텍처 관점에서 가장 비효율적인 구현 방법이다. 테이블 구조를 조금이라도 변경할 일이 발생하면 해당 엔티티 객체가 포함된 단일 공유 라이브러리도 같이 변경을 해야 하는데, 변경된 테이블의 사용 여부와 상관없이 전체 서비스를 일제히 변경 후 재배포할 수 밖에 없다.


데이터베이스 변경 영향도와 리스크를 낮추는 한 가지 방법은, 데이터베이스를 논리적으로 분할하고 이러한 논리 분할을 연합 공유 라이브러리(federated shared library)를 통해 명시하는 것이다.


위의 그림은 데이터베이스를 5개의 개별 도메인(공통, 고객, 청구, 주문, 추적)으로 논리 분할하고 도메인 서비스마다 논리 분할한 데이터베이스를 바라보는 전용 공유 라이브러리를 5개 둔 구조이다. 이런 식으로 구성하면, 특정 논리 도메인에 속한 테이블을 변경해도 해당 엔티티 객체가 포함된 해당 공유 라이브러리를 사용하는 서비스(즉, 청구 서비스)만 영향을 받을 뿐, 그 밖의 서비스에는 영향이 없다.

모든 서비스의 공통 테이블을 변경하려면 먼저 공유 데이터베이스를 액세스하는 전체 서비스를 미리 조율해야 한다. 테이블 변경 영향도를 낮추는 한 가지 방법은, 공통 엔티티 객체를 버전 관리 시스템에서 락킹하고 수정 권한을 오직 데이터베이스 팀에게만 부여하는 것이다. 이렇게 해야 변경을 통제할 수 있고 모든 서비스의 공용 테이블을 변경하는 작업의 중용성이 부각된다.

서비스 기반 아키텍처에서는 데이터베이스 변경을 통제하기 위해 데이터 도메인을 올바르게 정의/관리하고 데이터베이스는 가급적 논리적으로 잘게 나누는 것이 좋다.

13.5 아키텍처 예시

서비스 기반 아키텍처의 유연한과 강점을 전자 제품 재활용 식스템을 예로 들어 살펴보겠다. 중고 전자 제품의 재활용 처리 프로세스는 다음과 같다. 먼저 고객이 회사에 연락하여 자신이 소유한 중고 제품을 얼마에 보상받을 수 있는지 문의한다.(견적)

  1. 견적 : 고객이 회사에 연락하여 자신이 소유한 중고 제품을 얼마에 보상받을 수 있는지 문의한다.
  2. 수취 : 고객이 보상가에 만족하면 회사에 제품을 보내고 회사는 실물을 받는다.
  3. 감정 : 재활용 회사는 고객이 보낸 제품의 작동 상태를 꼼꼼히 평가한다.
  4. 회계 : 제품 상태가 좋을 경우 회사는 고객에세 약속한 보상가를 지불한다.
  5. 재활용 : 감정 결과에 따라 제품은 안전하게 해체 후 재활용 되거나 재판매된다.
  6. 회사는 재활용 성과에 따른 임시/정기 재무 리포트를 정기적으로 체크한다.
  • 제품 상태 : 위의 회계 과정까지 언제라도 고객은 회사 웹사이트에 접속해서 진행 상황을 확인할 수 있다.

위의 그림은 전자 제품 재활용 시스템을 서비스 기반 아키텍처로 설계한 것이다. 높은 처리량이 필요한 서비스(견적 서비스와제품 상태 서비스)만 확장하면 되므로 확장성도 충족되고, 그 밖의 서비스는 굳이 확장할 필요가 없으니 단일 서비스 인스턴스로도 충분하다. 유저 인터페이스 애플리케이션이 각 도메인(견적, 수취, 재활용, 회게)과 잘 연합되어 있다. 이러한 연합 덕분에 유저 인터페이스의 내고장성, 확장성, 보안(외부 고객은 내부 기능으로 향하는 네트워크에 접속 불가)이 실현된다. 그리고 데이터베이스를 외부 고객 처리용 데이터베이스와 내부 처리용 데이터베이스로 물리적인 분할을 했다. 내부 데이터와 기능을 외부 작업과 분리된 별도의 네트워크 영역에 두는 것이 데이터 보안상 바람직하다.

이 예제만 보더라도 민첩성, 시험성, 배포성은 물론, 확장성, 내고장성, 보안 등 서비스 기반 아키텍처의 많은 장점을 실감 할 수 있다. 예를 들어, 감정 서비스는 신제품이 출시되면 감정 규칙이 추가될 테니 꾸준히 변경될 것이다. 이런 잦은 변경을 단일 도메인 서비스로 격리하면 민첩성, 시험성, 배포성을 높일 수 있다.

13.6 아키텍처 특성 등급

아키텍처 특성별점
분할 유형도메인
퀀텀 수하나 또는 여러개
배포성⭐⭐⭐⭐
탄력성⭐⭐
진화성⭐⭐⭐
내고장성⭐⭐⭐⭐
모듈성⭐⭐⭐⭐
전체 비용⭐⭐⭐⭐
성능⭐⭐⭐
신뢰성⭐⭐⭐⭐
확장성⭐⭐⭐
단순성⭐⭐⭐
시험성⭐⭐⭐⭐

13.7 언제 이 아키텍처 스타일을 사용하는가

서비스 기반 아키텍처는 도메인 주도 설계와 궁합이 잘 맞다. 서비스를 큰 단위로 나누고 그 범위를 도메인으로 한정하기 때문에 각 도메인은 개별 배포된 도메인 서비스에 딱 맞아 떨어지느 것이다. 서비스 기반 아키텍처의 서비스는 각각 지정된 도메인을 포함하므로 그 기능을 단일 소프트웨어 단위로 구분하면 해당 도메인을 더 쉽게 변경할 수 있다.

서비스 기반 아키텍처는 복잡하게 뒤얽히거나 세분도의 함정에 빠져 허우적거리지 않고도 아키텍처 모듈성을 괜찮을 수준으로 달성할 수 있다. 서비스를 더 잘게 나눌수록 오케스트레이션 및 코레오그래피 관련 이슈가 발생하기 시작하는데, 여러 서비스를 조율해서 비지니스 트랜잭션을 완성하려면 오케스트레이션과 코레오그래피 둘다 필요하다.

  • 오케스트레이션 : 트랜잭션의 워크플로를 제어/관리하는 중재자 서비스를 따로 두고 여러 서비스를 조율하는 기법. (오케스트라의 지휘자 같은)
  • 코레오그래피 : 각 서비스가 중앙의 중재자 없이 서로가 알아서 소통하는 방식. (무대에서 춤추는 댄서들처럼)

서비스가 더 잘게 쪼개지면 비지니스 트랜잭션을 완성하기 위해 서비스를 서로 단단히 묶어주는 오케스트레이션과 코레오그래피가 필요하다. 그러나 서비스 기반 아키텍처의 서비스는 더 큰 단위로 나뉘어지는 편이라서 다른 분산 아키텍처만큼 정교한 조율은 필요하지 않다.