-
서비스 지향 아키텍처와 마이크로서비스 아키텍처는 최근에 큰 인기를 끌고 있다. 그 이유는 다음과 같다.
1. 서비스를 사용하면 상호 결합이 철저하게 분리되는 것처럼 보인다. (일부만 맞는 말이다.)
2. 서비스를 사용하면 개발과 배포 독립성을 지원하는 것처럼 보인다. (일부만 맞는 말이다.)
서비스 아키텍처?
-
서비스를 사용한다는 것이 본질적으로 아키텍처에 해당하는 것이 아니다.
시스템의 아키텍처는 의존성 규칙을 준수하며 고수준의 정책을 저수준의 세부사항으로부터 분리하는 경계에 의해 정의된다.
단순히 앱의 행위를 분리할 뿐인 서비스라면 값비싼 함수 호출에 불과하며, 아키텍처 관점에서 꼭 중요하다고 볼 수는 없다.
모든 서비스가 반드시 아키텍처 관점에서 중요해야만 한다는 뜻은 아니다.
기능을 프로세스나 플랫폼에 독립적이 되게끔 서비스들을 생성하면 의존성 규칙 준수 여부와 상관없이 큰 도움이 될 때가 많다.
그러나 서비스 그 자체로는 아키텍처를 정의하지 않는다.
-
함수들의 구성 형태도 비슷하다
모노리틱 시스템이나 컴포넌트 기반 시스템에서 아키텍처를 정의하는 요소는 바로 의존성 규칙을 따르며 아키텍처 경계를 넘나드는 함수 호출들이다.
반면 시스템의 나머지 많은 함수들은 행위를 서로 분리할 뿐이며, 아키텍처적으로 전혀 중요하지 않다.
서비스도 마찬가지다.
결국 서비스는 프로세스나 플랫폼 경계를 가로지르는 함수 호출에 지나지 않는다.
서비스의 이점?
* 결합 분리의 오류
-
이점 중 하나는 서비스 사이의 결합이 확실히 분리된다는 점이다.
어쨌든 각 서비스는 서로 다른 프로세스에서, 심지어는 서로 다른 컴퓨터에서 실행된다.
서비스는 다른 서비스의 변수에 직접 접근할 수 없고, 모든 서비스의 인터페이스는 반드시 잘 정의되어 있어야 한다.
-
서비스는 개별 변수 수준에서는 각각 결합이 분리된다.
하지만 프로세서 내의 또는 네트워크 상의 공유 자원 때문에 결합될 가능성이 여전히 존재한다.
더욱이 서로 공유하는 데이터에 의해 이들 서비스는 강력하게 결합되어 버린다.
예를 들어 서비스 사이를 오가는 데이터 레코드에 새로운 필드를 추가한다면, 이 필드를 사용해 동작하는 모든 서비스는 반드시 변경되어야 한다.
또한 이 서비스들은 이 필드에 담긴 데이터를 해석하는 방식을 사전에 완벽하게 조율해야 한다.
따라서 서비스들은 이 데이터 레코드에 강하게 결합되고, 서비스들 사이는 서로 간접적으로 결합되어 버린다.
* 개발 및 배포 독립성의 오류
-
서비스를 사용함에 따라 예측되는 또 다른 이점은 전담팀이 서비스를 소유하고 운영한다는 점이다.
이러한 개발 및 배포 독립성은 확장 가능한(scalable) 것으로 간주된다.
대규모 엔터프라이즈 시스템을 독립적으로 개발하고 배포 가능한 수십, 수백, 수천 개의 서비스들을 이용하여 만들 수 있다고 믿는다.
일리는 있지만, 극히 일부일 뿐이다.
결합 분리의 오류에 따르면 서비스라고 해서 항상 독립적으로 개발하고, 배포하며, 운영할 수 있는 것이 아니다.
데이터나 행위에서 어느 정도 결합되어 있다면 결합된 정도에 맞게 개발, 배포, 운영을 조정해야 한다.
야옹이 문제
-
택시 배차 앱에서 "고양이 운반" 기능을 추가할 경우 모든 서비스들이 결합되어 있어 독립적으로 배포하거나 유지될 수 없다.
횡단 관심사(cross-cutting concern)가 지닌 문제이다.
모든 소프트웨어 시스템은 서비스 지향이든 아니든 이 문제에 직면하게 마련이다.
기능적 컴포넌트 분해는 새로운 기능이 기능적 행위를 횡단하는 상황에 매우 취약하다.
객체가 구출하다.
-
SOLID 설계 원칙을 들여다보면, 다형적으로 확장할 수 있는 클래스 집합을 생성해 새로운 기능을 처리하도록 함을 알 수 있다.
기존 컴포넌트들에 있는 추상 기반 클래스를 템플릿 메서드(Template Method)나 전략 전략(Strategy Pattern) 등을 이용해서 구현한다.
그리고 UI 의 제어 하에 팩토리(Factory)를 이용하여 원하는 기능으로 갈아끼운다.
컴포넌트 기반 서비스
-
서비스도 SOLID 원칙대로 설계할 수 있으며 컴포넌트 구조를 갖출 수도 있다.
횡단 관심사
-
아키텍처 경계가 서비스 사이에 있지 않다.
오히려 서비스를 관통하며, 서비스를 컴포넌트 단위로 분할한다.
모든 주요 시스템이 직면하는 횡단 관심사를 처리하려면, 서비스 내부는 의존성 규칙도 준수하는 컴포넌트 아키텍처로 설계해야 한다.
이 서비스들은 시스템의 아키텍처 경계를 정의하지 않는다.
아키텍처 경계를 정의하는 것은 서비스 내에 위치한 컴포넌트다.
결론
-
서비스는 시스템의 확장성과 개발 가능성 측면에서 유용하지만, 그 자체로는 아키텍처적으로 그리 중요한 요소는 아니다.
시스템의 아키텍처는 시스템 내부에 그어진 경계와 경계를 넘나드는 의존성에 의해 정의된다.
시스템의 구성 요소가 통신하고 실행되는 물리적인 메커니즘에 의해 아키텍처가 정의되는 것이 아니다.
서비스는 단 하나의 아키텍처 경계로 둘러싸인 단일 컴포넌트로 만들 수 있다.
혹은 여러 아키텍처 경계로 분리된 다수의 컴포넌트로 구성할 수도 있다.
드물게는 클라이언트와 서비스가 강하게 결합되어 아키텍처적으로 아무런 의미가 없을 때도 있다.
'프로그래밍 놀이터 > 디자인 패턴, 리펙토링' 카테고리의 다른 글
[책 정리] 29. 클린 임베디드 아키텍처 - Clean Architecture (0) | 2022.11.10 |
---|---|
[책 정리] 28. 테스트 경계 - Clean Architecture (0) | 2022.11.09 |
[책 정리] 26. 메인(Main) 컴포넌트 - Clean Architecture (0) | 2022.11.07 |
[책 정리] 25. 계층과 경계 - Clean Architecture (0) | 2022.11.06 |
[책 정리] 24. 부분적 경계 - Clean Architecture (0) | 2022.11.05 |
댓글