기본 콘텐츠로 건너뛰기

마이크로서비스와 SOA 비교

근래 마이크로서비스에 관심이 생겨 읽어본 글. 찾은 글 중에선 마이크로서비스와 SOA에 관해 전반적으로 정리가 잘된 거 같아서 요약해 두기로 했다. 내용이 적지는 않아서 키워드 위주로 정리했지만 역시 한눈에 들어오지 않음. #딴지금지 #지적환영

원글은 https://www.nginx.com/microservices-soa/ 에서 pdf로 배포하고 있다.

목차
  • The World of Service-Based Architectures 
  • Comparing Service Charateristics 
  • Comparing Architecture Characteristics 
  • Comparing Architecture Capabilities 
  • Summary 

1. The World of Service-Based Architectures

a. Service Contracts






"서비스 계약"은 REST API 문서같이 서비스와 서비스 컨슈머(consumer)간 동의를 말한다. 서비스 기반 아키텍쳐는 "서비스 중심 계약"(Service-Based Contracts)과 "컨슈머주도 계약"(Cosumer-Driven Contracts) 두가지 모델이 있다. 차이점은 일방적이냐 아니냐 하는 “협업 정도(The degree of collaboration)”이다.

"서비스 중심" 아키텍쳐는 컨슈머를 고려하지 않은 계약변경을 한다. "컨슈머 주도 계약"은 컨슈머가 변경을 제안하고 서비스는 다른 컨슈머들의 영향도를 판단해서 적용 여부를 결정한다. 이런 "컨슈머 주도 계약" 컨셉을 테스트 시점에 적용할 수 있게 구현하고 툴링을 제공하는 오픈소스로 "Pact", “Pacto”가 있다. 컨슈머는 서비스 프로바이더에게 Pact라는 테스트를 보내고 서비스 프로바이더는 계약변경이 생기면 컨슈머가 보낸 테스트를 빌드 시점에 서비스 제공자의 테스트에 포함해 테스트하는 방식이다.

또 한 가지 중요한 것이 "계약 버전"(Contract versioning)이다. 버전 관리를 돕는 오픈소스/상용 프레임워크들이 있지만 직접 "동종버전 전략"(homogeneous versioning)과 "이종버전 전략"(heterogeneous versioning)을 사용할 수 있다. "동종버전 전략"은 서비스 계약은 같지만 버전을 달리 가는데 (그림에서 서비스 계약 A와 B 모두 동그라미 모양이다), 버전이 바뀌면 하위호환을 유지하고 필드가 추가된다. "이종버전 전략"은 여러 종류의 계약을 가진다. "컨슈머 주도계약" 컨셉에 가깝다. 새로운 기능이 추가되면 새로운 계약을 만든다. JMS 기반 메세징 시스템에 공통으로 쓰이는데, 컨슈머 질의에 스키마를 포함한 XML 응답을 보낸다. 계약에 따라서 스키마가 다르다.

버전 관리의 실질적인 목표는 하위호환을 제공이라고 볼 수 있으며, 다른 계약의 타입별로 여러 버전을 제공할 때는 두 가지 전략을 같이 사용하기도 한다.


b. Service Availability





"서비스 가용성"은 원격지에 있는 서버가 적절한 시간에 요청을 처리하는 능력과 관련 있고, "서비스 응답성"은 적절한 시간에 컨슈머가 응답을 받는 것에 관련이 있다. 서비스 응답성과 관련해서는 타임아웃(timeout)에 관련된 이슈가 많다. 또한, 정해진 시간 내에 응답이 없을 때 컨슈머에게 더이상 기다릴 필요가 없음을 알리는 방법으로 "서킷 브레이커” 패턴이 유명하다. "서킷 브레이커"의 구현으로 넷플릭스의 오픈소스 “리본”이 있다. 그리고 타임아웃값은 일괄적으로 모든 요청에 적용하기보다는 요청마다 적절한 타임아웃값을 적용하고, 외부설정으로 빼두어 변경이 생겼을 때 새로 하고 빌드하고 배포되지 않게 고려되어야 한다. 그리고 부하에 따라 “smart timeout values”를 적용하는 로직을 코드에 넣는 방법도 있다.

c. Security




보안은 초기 SOA 구현에서는 주된 이슈였다. 마이크로서비스는 서비스 간 메세지 중재를 해주는 미들웨어가 없어서 역시 보안이 중요한 문제가 되고 있다. 마이크로서비스에서 보안 디자인의 한가지로 각 서비스에 인증을 위임한 다음, 개별 서비스가 권한처리를 하도록 하는 방법이 있다. 권한을 서비스에 캡슐화하고, 원격지 서비스와 chattiness 하게 그리고 외부 종속성이 없는 강한 “bounded context"를 생성하는 방법을 (필자는) 선호한(단)다.

d. Transactions





ACID(atomicity, consistency, isolation, durability)트랜잭션은 대부분 비즈니스 어플리케이션에서 찾아볼 수 있다. 서비스기반 아키텍쳐는 통산 분산된 아키텍쳐기 때문에 트랜잭션을 관리가 어렵다. 그래서 ACID 트랜잭션보다는 BASE( basically available, soft state, eventual consistency ) 트랜잭션을 필요로 한다. 트랜잭션 레벨에서 일관성(consistency)을 얻기위해 ACID 트랜잭션을 허용하면, 서비스는 비즈니스 로직을 하나의 서비스에 캡슐화 해야 하기 때문에 좀 더 Coarse-Grained 하게 된다.

e. Too much complexity?

서비스 기반 아키텍쳐는 모노리식(monolithic)한 어프리케이션 개선에 의미가 있지만 서비스 계약, 가용성, 보안, 트랜잭션에 관련된 이슈가 고려 되어야 한다.

2. Comparing Service Characteristics

a. Service Taxonomy





"서비스 분류체계"는 아키텍처에서 서비스가 어떻게 분류되는가와 관련 있는데, 기본 두 가지는 "서비스 타입"(Service Type)과 "비즈니스 영역"(Business Area)으로 분류된다. "서비스 타입"의 분류는 서비스가 하는 역활의 타입과 관련 있다. 예를 들어 비즈니스와 관련된 구현이 있고 로깅이나 보안과 같이 비즈니스와 관련이 없는 구현이 있다. "비즈니스 영역"의 분류는 주문서비스, 리포팅과 같이 비즈니스 서비스가 하는 역활과 관련이 있다.

"서비스 타입"은 아키텍쳐 패턴 레벨로 정의되고 "비즈니스 영역"은 아키텍쳐 구현 레벨로 정의된다. 마이크로 서비스 아키텍쳐는 서비스 타입으로 분류할 때 "기능 서비스"(functional service)와 "인프라 서비스"(infrastructure service) 두 가지로 분류한다. "기능 서비스"는 비즈니스 동작이나 기능을 구현하는 것을 말하고, "인프라 서비스"는 비즈니스와 관련된 기능 외에 인증, 권한, 로깅과 같은 구현을 말한다.

SOA 아키텍쳐는 비즈니스 서비스, 메세징 미들웨어, 엔터프라이즈 서비스, 어프리케이션 서비스, 인프라 서비스로 분류된다. "비즈니스 서비스"는 고수준 추상화를 말하는데, WSDL이나 BPEL과 같은 XML 스펙으로 표현된다. 그리고 어떤 것들이 "비즈니스 서비스" 인지 구분해 보려면 “Are we in the business of”를 붙여보면 구분해 보는 데 도움이 된다. 예) ProcessingTrades, InsertCustomer 두 가지를 보면, Are we in the business of processing trades? 와 Are we in the business of inserting customer? 로 테스트 하는식이다.

“엔터프라이즈 서비스”는 실제 구현된 서비스를 말한다. "비즈니스 서비스"에 정의된 기능의 구현이다. "미들웨어 서비스"에서 비즈니스 서비스와 그것에 상응하는 "엔터프라이즈 서비스"로 연결한다. 1:1로 연결되기도 하고 1:N으로 연결되기도 한다. 이 구현체들은 다양한 프로그래밍 언어로 구현되거나 상용 서드파티 제품을 사용하기도 한다. 그리고 "엔터프라이즈 서비스"는 비즈니스 요청을 처리하기 위해 "어프리케이션 서비스"와 "인프라 서비스"에 의존한다.

“어프리케이션 서비스”는 특정한 상황에 사용되는 어프리케이션으로 "엔터프라이즈 서비스"에서 구현되지 않거나 존재하지 않는 특정한 기능을 제공한다. 예를 들어 자동견적 어프리케이션은 보험회사의 하나의 부분이기도 하지만 UI를 제공하고 견적 서비스로써 외부에 노출할 수도 있다.


b. Service Ownership and Coordination






"서비스 오너"(Service Ower)는 조직 내에서 서비스를 생성하고 유지하는 데 책임이 있는 그룹의 형태다.

마이크로 서비스는 "기능 서비스"와 "인프라 서비스"로 나뉘는 제한된 서비스 분류체계를 가지기 때문에 마이크로 서비스에서 어프리케이션 개발팀은 "인프라 서비스"와 "기능 서비스" 두가지 모두 책임을 가진다. 그래서 서비스 간 코디네이션이 거의 없다.

SOA에서는 "비즈니스 서비스"는 비즈니스 사용자에게 소유되는 반면 "엔터프라이즈 서비스"는 공통 서비스팀이나 아키텍트에게 소유된다. "어프리케이션 서비스"는 어프리케이션 개발팀이 소유하고 인프라 서비스는 어프리케이션 개발팀이나 인프라 서비스팀이 소유한다. SOA에서 볼 수 있는 "미들웨어 컴포넌트"는 통합 아키텍트(Integration architects)나 미들웨어 팀이 소유한다. 그리고 하나의 비즈니스 요청처리에 모든 팀의 코디네이션이 필요하며, 미들웨어를 통해 모든 코디네이션이 이루어진다.

마이크로 서비스에서는 서비스 간 코디네이션이 없거나 최소한의 코디네이션만 필요하다. 서비스 오너간 코디네이션이 필요할 땐 어프리케이션 개발팀 규모가 작아서 빠르고 효과적으로 코디네이션이 이루어 진다.

c. Service Granularity





Granularity(‘입도'라도 하는 모양인데 와 닿지 않음)는 서비스의 상대적 크기나 자세한 정도를 나타낸다. 이 Granularity가 서비스관점의 마이크로 서비스와 SOA 간 가장 큰 차이점이다.

마이크로 서비스는 작고 fine-grained 한 서비스다. 마이크로서비스에서 컴포넌트는 단일목적의 서비스지만, SOA에서 서비스 컴포넌트는 작은 서비스에서부터 큰 서비까지 범위를 가진다. 아키텍트가 SOA에서 서비스 Granularity가 끼치는 영향 범위를 잘 이해하지 못하고 너무 fine-grained하게 디자인하면 chatty(컴포넌트 간 네트워크 커뮤니케이션이 많은)한 서비스가 되어 성능이 좋지 않게 된다. 예를 들면 fine-grained한 getter와 setter보다는 단위 서비스가 좋다 - GetCustomerAddress, GetCustomerName, UpdateCustomerName 보다는 Customer Service가 좋다.

Granularity는 성능뿐만 아니라 트랜잭션 관리에도 영향을 미친다. 원격 서비스들이 너무 fine-grained 하면 하나의 트랜잭션 유닛으로 작업 되게 코디네이션 할 수 없다.

d. Granularity and Pattern Selection



마이크로 서비스의 작고 fine-grained 한 아키텍쳐 컨셉은 개발, 테스트, 배포 그리고 관리를 포함해 소프트웨어 개발 라이프사이클 전체를 개선한다. 범위가 작은 서비스를 크게 옮기고 있다면 SOA 패턴을 고려해야 하지만, 어프리케이션 비즈니스 기능을 작고 독립적인 파트로 쪼갤 수 있다면 마이크로 서비스 패턴을 고려해야 한다.


3. Comparing Architecture Characteristics

a. Component Sharing


"컴포넌트 공유"(sharing component)관점에서 마이크로 서비스는 "Share-as-little-possible” 아키텍쳐 스타일이고 SOA는 "Share-as-much-as-possibile" 아키텍쳐 스타일이다. 컴포넌트 공유는 SOA의 핵심 교리 중 하나다. "silo-based" 문제는 공유가 되지 않는 문제를 말하는데, 그림에서는 각자 주문서비스를 가지는 문제를 말한다. SOA에서는 "엔터프라이즈 서비스"를 공유하는 방법으로 이런 문제에 접근한다. 그림에서는 주문 서비스를 생성했다. 주문 서비스가 공유되었지만, 여전히 세 개의 다른 데이터베이스에 접근한다. 이 부분이 share-much-as-possible 아키텍쳐 스타일이 사용될 때 가장 좋지못한 부분이다. 주문 서비스는 세 개의 데이터베이스에 걸쳐 데이터를 관리해야 한다. 다른 말로 세 개의 데이터베이스가 복합되어야 주문서비스가 가능하다. share-as-much-as-possible 아키텍쳐 개념은 기능 중복과 관련된 이슈는 해결하지만 컴포넌트가 강결합(tightly coupled component)되고 변경에 따른 위험도가 증가하는 경향이 있다.

마이크로 서비스의 share-little-as-possible 개념은 "Bounded-Context"라 불리는 도메인주도(Domain-Driven) 디자인 위에 구축되어야 효과가 배가된다. SOA는 컴포넌트 공유를 극대화하고 마이크로 서비스는 Bounded-Context를 통해서 공유를 최소화한다.


b. Service Orchestration and Choreography







"서비스 오케스트레이션"(service orchestration)은 다른 악기를 사용하는 음악가들이 지휘자를 통해 코디네이션 되는 거로 예시될 수 있다. "중재 컴포넌트"(mediator component)는 지휘자에 해당하는데 모든 서비스 호출이 "중재 컴포넌트"를 통해 이루어진다. "서비스 코레오그래피"(service choreography)는 발레 댄서들이 서로 상호 작용하며 움직이지만 지휘자가 없는 것으로 예시될 수 있다. 중앙중재가 없이 여러 서비스가 코디네이션 되며, "서비스 chaining"과 관련 있다.

마이크로서비스는 아키텍쳐상 미들웨어 컴포넌트가 없으므로 "서비스 코레오그래피"를 선호한다. 핵심 컴포넌트는 "서비스 컴포넌트"와 "API 계층” 두 가지다. 구현 관점에서는 서비스 등록(service registration)과 서비스 발견(service discovery), 서비스 모니터링, 서비스 배포 매니저를 가질 수 있다. 이런 것들은 아키텍쳐에서는 인프라 서비스에 해당한다.

마이크로 서비스는 가능한 최소한의 공유를 가지는 아키텍쳐기 때문에 아키텍쳐에서는 "서비스 코레오그래피"의 양을 최소화하고 "서비스 기능"과 "인프라 서비스"간 상호작용이 제한되도록 노력 해야 한다. 너무 많은 "서비스 코레오그래피"는 컴포넌트 간 의존이 많이 생기는 “efferent coupling”이 될 수 있다. 서비스 성능도 낮아지고 결합 도도 높아지게 된다. 해결책으로 fine-grained 서비스를 coarse-grained 서비스로 묶거나 DRY 정책을 무시하고 각 coarse-grained 서비스에 공통 기능으로 추가하는 방법이 있다.
SOA는 가능한 공유를 많이 하는 아키텍쳐 이기 때문에, "오케스트레이션"과 "코레오그래피” 두 가지 모두에 의존한다. 미들웨어를 통해 여러 "엔터프라이즈 서비스"로 중재 되고 각각 필요한 서비스 호출 체인이 생길 수 있다.

SOA는 마이크로서비스보다 느리고 개발, 테스트 그리고 유지보수에 더 많은 시간과 노력이 요구된다. 이런 사실 때문에, 아키텍트들은 SOA 아키텍쳐를 멀리하고 간단하고 스트림라인된(streamlined) 마이크로서비스 패턴으로 옮겨간다.


c. Middleware vs. API Layer





"API 계층”은 서비스 앞단에서 "service-access facade"로 동작한다. 컨슈머는 서비스의 실제 엔드포인트(endpoint) 위치가 어디인지 알 필요가 없다. 때문에 컨슈머에게 영향 없이 서비스 Granularity 레벨을 변경할 수 있다. SOA는 "메세지 미들웨어"에 의존한다. "메세지 미들웨어"를 사용하면 마이크로서비스 아키텍쳐 스타일에서 찾아볼 수 없는 중재기능, 라우팅, 메세지 개선(enhancement), 메세지 변형(transformation) 그리고 프로토콜 변형(transformation) 등을 포함한 부가적인 기능들을 많이 받을 수 있다.

d. Accessing Remote Services







마이크로서비스와 SOA에서 "remote access"와 관련해 기본적으로 다른 한 가지는 마이크로서비스는 주된 remote-access 프로토콜로 REST에 의존하는 경향이 있지만, SOA는 이런 제약이 없다는 것이다.

아키텍쳐 패턴을 간결하게 하는 마이크로서비스의 기본 원칙 중의 하나가 사용하는 기술의 수와 아키텍쳐 선택의 여지를 주지 않게 아주 제한적이다. 예를 들어 마이크로서비스는 일반적으로 REST나 JMS, MSMQ, AMQP와 같은 간단한 메세징에 의존한다. 마이크로서비스에서 보여지는 remote-access 프로토콜은 일반적으로 호모지니어스(Homogeneous)하다. 다른 말로 동일 어프리케이션이나 시스템 내에서 access 프로토콜이 혼용되지 않는다. SOA에서는 이런 제약이 없다. 헤테로지니어스(Heterogeneous) 즉, 이기종 서비스간 대여섯개가 넘는 remote-access 프로토콜이 사용된다.

4. Comparing Architecture Capabilities

a. Application Scope



"어프리케이션 범위"(Application Scope)는 아키텍쳐 패턴이 지원할 수 있는 어프리케이션의 전반적인 크기와 관련이 있다. 예를 들어, 마이크로커널(microkernel)이나 파이프라인(pipeline) 아키텍쳐는 작은 어프리케이션이나 서브 시스템에 적합하고, 이벤트 기반(event-driven) 아키텍쳐는 큰 시스템에 적합하다.

SOA는 다양한 이기종 어프리케이션과 서비스간 통합이 필요한 복잡한 엔터프라이즈 규모의 시스템에 적합하다. 또한, 공유 컴포넌트가 많은 곳에 적합하다. 반면, 워크플로우 기반 어프리케이션은 잘 정의된 절차와 흐름을 가지고 공유 컴포넌트가 적기 때문에 SOA 아키텍쳐로 구현하기 어렵다. 작은 웹 기반 어프리케이션 또한 SOA를 사용하기엔 적합하지 않다.

마이크로서비스 패턴은 작고, 잘 분할된 웹 기반 시스템에 어울린다. 중재자(mediator, message middleware)가 없으므로 크고 복잡한 비즈니스 어프리케이션에는 어울리지 않는다. 그리고 마이크로서비스는 초기 아키텍쳐로 선택하기 적합하다. 시스템이 복잡해지면 최초 마이크로서비스 아키텍쳐를 SOA로 전환하거나 반대의 경우로도 전환한다.



b. Heterogeneous Interoperability 



"이기종 상호운용성"(Heterogeneous Interoperability)은 다양한 언어와 플랫폼으로 구현된 시스템 통합 능력과 관련이 있다. 마이크로서비스 아키텍쳐 스타일은 protocol-aware heterogeneous interoperability를 지원한다. 즉, 아키텍쳐가 여러 remote access 프로토콜 타입을 지원할 수 있지만, 특정 컨슈머와 그에 상응하는 서비스는 반드시 같아야 한다. 메세지 미들웨어가 없기 때문이다. SOA 역시 protocol-aware heterogeneous interoperability를 지원하지만, 한 걸음 더 나가 protocol-agnostic heterogeneous interoperability를 지원한다. 즉, 서비스 컨슈머는 서비스의 구현이나 서비스에 필요한 프로토콜을 인지할 필요가 없다. REST로 호출되어도 미들웨어를 통해 RMI로 변환되어 상응하는 서비스가 호출된다.

c. Contract Decoupling



Contract decoupling은 추상화의 성배 같은 거라고 한다. 메세지 변형(transformation)과 메세지 개선(enhancement)의 두 가지 기본 형태가 있다. "메세지 변형"은 실제 데이터와는 관련이 없고, 메세지 포맷과 관련이 있다. 예를 들어 XML을 JSON으로 변환하는 걸 말한다. "메세지 개선"은 요청 데이터와 관련이 있다. 미들웨어가 요청 데이터에 데이터를 추가하거나 변경하는 것을 말한다. 소프트웨어 버전이 업그레이드 되거나 다른 서비스의 변경이 있더라도 contract decoupling으로 비즈니스 어프리케이션은 영향받지 않게 할 수 있다. 마이크로서비스는 contract decoupling을 지원하지 않지만, SOA에서는 중요한 기능중 하나다. contract decoupling이 필요하다면 마이크로 서비스보다는 SOA 아키텍쳐가 필요하다고 볼 수 있다.


5. Summary


기억해야 할 기본 개념중 하나가 마이크로서비스 아키텍쳐는 bounded context에서 강조하는 share-as-little-as-possible 아키텍쳐 패턴이지만 SOA는 추상화와 비즈니스 기능의 재사용을 강조하는 share-as-much-as-possible 아키텍쳐 패턴이다.



1. Service-Based Architectures



2. Comparing Service Characteristics



3. Comparing Architecture Characteristics



4. Comparing Architecture Capabilities



댓글