마이크로서비스 아키텍처란 무엇인가?
마이크로서비스 아키텍처의 핵심 사상은 기능 분해이다. 이전에는 확장성, 신뢰성, 보안 등이 아키텍처의 주요 목표였지만, 이제는 신속, 안전하게 소프트웨어를 전달하는 능력도 매우 중요해졌다. 마이크로서비스 아키텍처는 관리성, 테스트성, 배포성이 높은 아키텍처 스타일.
▶ 소프트웨어 아키텍처의 4+1 뷰 모델
애플리케이션 아키텍처를 바라보는 관점은 다양하다. 필립 크러첸(Phillip Krutchen)은 소프트웨어 아키텍처가 4+1 뷰 모델이라고 기술한 논문을 발표했다. 4+1 뷰 모델은 소프트웨어 아키텍처를 바라보는 상이한 4뷰를 정의한다.
- 논리 뷰 (logical view): 개발자가 작성한 소프트웨어 엘리먼트: 클래스, 패키지 (객체 지향). 상속(inheritance), 연관(association), 의존(depends-on) 등 클래스와 패키지의 관계를 말함
- 구현 뷰 (implementation view): 빌드 시스템의 결과물. 모듈(패키징된 코드)과 컴포넌트(하나 이상의 모듈로 구성된 실행/배포 가능 단위)
- 프로세스 뷰 (process view): 런타임 컴포넌트. 각 엘리먼트는 개별 프로세스고, IPC는 프로세스 간 관계를 나타냄
- 배포 뷰 (deployment view): 프로세스가 머신에 매핑되는 방법. 엘리먼트는 (물리 또는 가상) 머신 및 프로세스고, 머신 간의 관계가 바로 네트워키임. 프로세스와 머신 사이의 관계가 기술됨
▶ 계층화 아키텍처 스타일
계층화 아키텍처 (layered architecture)는 전형적인 아키텍처 스타일. 계층마다 명확히 정의된 역할을 분담하며, 계층 간 디펜던시는 아키텍처로 제한함. 따라서 어떤 계층은 바로 하위에 있는 계층에만 의존하거나, 하위에 위치한 어느 한 계층에 의존함.
- 표현(프레젠테이션) 계층 (presentation layer): 사용자 인터페이스 또는 외부 API가 구현된 계층
- 비즈니스 로직 계층 (business logic layer): 비즈니스 로직이 구현된 계층
- 영속화(퍼시스턴스) 계층 (persistence layer): DB 상호 작용 로직이 구현된 계층
계층화 아키텍처는 몇 가지 중요한 흠이 있음.
- 표현 계층이 하나뿐: 애플리케이션을 호출하는 시스템이 하나밖에 없을까?
- 영속화 계층이 하나뿐: 애플리케이션이 상호작용하는 DB가 하나밖에 없을까?
- 비즈니스 로직 계층을 영속화 계층에 의존하는 형태로 정의: 이런 디펜던시 때문에 DB 없이 비즈니스 로직을 테스트하기가 불가능
이러한 문제점을 해결하고자 고안된 아키텍처: 육각형 아키텍처
▶ 육각형 아키텍처 스타일
표현 계층 대신 비즈니스 로직을 호출하여 외부에서 들어온 요청을 처리하는 인바운드 어댑터, 영속화 계층 대신 비즈니스 로직에 의해 호출되고 외부 애플리케이션을 호출하는 아웃바운드 어댑터를 둔다. 비즈니스 로직이 어댑터에 전혀 의존하지 않는다는 것이 이 아키텍처의 가장 중요한 특장점이다. 외려 어댑터가 비즈니스 로직에 의존한다.
인바운드 포트는 비즈니스 로직이 표출된 API이며, 아웃바운드 포트는 비즈니스 로직이 외부 시스템을 호출하는 방법이다. 이렇게 분리를 하면 비즈니스 로직만 따로 테스트하기도 쉽고, 현대 애플리케이션 아키텍처를 좀 더 정확하게 반영할 수 있다. 육각형 아키텍처는 마이크로서비스 아키텍처를 이루는 각 서비스 아키텍처를 기술하는 가장 좋은 방법이다.
▶ 마이크로서비스 아키텍처는 일종의 아키텍처 스타일이다
- 모놀리식 아키텍처: 애플리케이션을 실행/배포 가능한 단일 컴포넌트로 구성
- 마이크로서비스 아키텍처: 애플리케이션을 느슨하게 결합된, 독립적으로 배포 가능한 여러 서비스로 구성
▶ 서비스란 무엇인가?
서비스는 어떤 기능이 구현되어 단독 배포가 가능한 소프트웨어 컴포넌트이다. 클라이언트가 자신이 서비스하는 기능(functionality)에 접근할 수 있도록 커맨드, 쿼리, 이벤트(event)로 구성된 API를 제공한다. 서비스 API는 내부 구현 상세를 캡슐화하는데 모놀리스와 달리 개발자는 API를 우회하여 서비스에 접근하는 코드를 작성할 수 없으므로 마이크로서비스 아키텍처에서 애플리케이션 모듈성은 보장된다.
▶ 느슨한 결합
느슨하게 결합된(loose-coupled) 서비스는 마이크로서비스 아키텍처의 주요 특성 중 하나이다. 서비스는 구현 코드를 감싼 API를 통해서만 상호작용하므로 클라이언트에 영향을 끼치지 않고 서비스 내부 구현 코드를 바꿀 수 있다. 느슨하게 결합된 서비스는 유지보수성(maintainability), 테스트성(testability)을 높이고 애플리케이션 개발 시간을 단축하는 효과가 있다.
서비스는 느슨하게 결합되고 API를 통해서만 동작하기 때문에 서비스가 직접 DB와 통신하는 일은 불가능하다. 또한 클래스 필드 같은 서비스의 영속적 데이터는 반드시 프라이빗으로 유지해야 한다. 이렇게 해야 개발자가 자신이 맡은 서비스의 DB 스키마를 변경할 때, 다른 서비스 개발자와 조율하느라 시간을 허비하지 않는다. 서비스가 DB 테이블을 서로 공유하지 않기 때문에 런타임 격리(runtime isolation)도 향상된다. 어떤 서비스가 DB 락을 획득하여 다른 서비스를 블로킹하는 일 자체가 불가능. 물론 여러 서비스에 걸쳐 데이터를 쿼리하고 일관성을 유지하는 일은 더 복잡해진다는 단점이 있다.
▶ 공유 라이브러리의 역할
코드 중복을 방지하기 위해 여러 애플리케이션에서 재사용 가능한 기능을 라이브러리로 패키징하는 것은 개발자에게 당연한 일이다. 그래서 마이크로서비스 아키텍처에서도 공유 라이브러리(shared library)를 사용하고픈 유혹에 빠지기 쉬운데, 서비스 코드 중복을 줄이는 것은 좋지만 의도치 않은 서비스 간 결합도를 유발하지 않도록 조심해야 한다. ※ 나도 이러한 경험이 많은데, 마이크로서비스는 많은 컴포넌트가 생기기 때문에 같은 코드를 작성하는 일이 많다. 이 부분은 공통 모듈을 빼는 방식으로 작업을 하곤 했는데, 아키텍처 딴에서는 지양하는 방식이었던 것 같다. 그래도... 같은 작업을 반복하는 것도 싫고 모든 컴포넌트에 일일이 소스를 업데이트 해주는 것도 싫긴 하다...
▶ 서비스 규모는 별로 중요하지 않다
마이크로(micro)라는 어감 때문에 서비스를 아주 작게 만들어야 할 것 같은 느낌이 들지만 사실 크기가 중요한 것이 아니다. 크기보다는 작은 팀이 가장 짧은 시간에, 다른 팀과 협동하는 부분은 최소로 하여 개발 가능한 서비스를 설계해야 한다.
마이크로서비스 아키텍처 정의
애플리케이션은 사용자의 요청을 처리하기 위해 존재한다. 따라서 아키텍처를 정의하는 1단계는 애플리케이션 요건을 핵심 요청으로 추출하는 것이다. 시스템 작업은 애플리케이션이 처리하는 요청을 추상화한(abstract) 것이다.
2단계는 어떻게 여러 서비스로 분해할지 결정하는 것이다. 비즈니스 아키텍처 시각에서 비즈니스 능력에 따라 서비스를 정의할 수도 있고, DDD의 하위 도메인별로 서비스를 구성하는 전략도 가능하다. 어떤 전략을 구사하든 최종 결과는 기술 개념이 아닌 비즈니스 개념 중심으로 이루어진 서비스들이다.
3단계는 서비스별로 API를 정의하는 일이다. 이를 위해 1단계에서 식별된 시스템 작업을 각 서비스에 배정해야 하며, 스탠드얼론 작업이 구현된 서비스도 있겠지만 다른 서비스와 협동할 수 밖에 없는 작업이 구현된 서비스도 있다. 여러 서비스가 협동하는 방식을 결정해야하는데, 대부분 서비스에 추가 지원 작업을 두는 형태가 될 것이다.
분해 과정에는 장애물이 많은데, 첫번째는 네트워크 지연(network latency)이다. 서비스간 왕복이 너무 잦아 실제로 분해할 수 없는 경우도 있다. 둘째는 서비스 간 동기 통신으로 인해 가용성이 떨어지는 문제이며(self-contained service 개념으로 해결가능), 셋쩨는 여러 서비스에 걸쳐 데이터 일관성을 지키는 요건(보통 사가로 해결)이다. 넷째는 애플리케이션 도처에 숨어있는 만능 클래스(god class)이다. 이런 클래스는 DDD 개념을 활용하면 어렵지 않게 제거할 수 있다.
▶ 시스템 작업 식별
▶ 고수준 도메인 모델 생성
서비스 정의: 비즈니스 능력 패턴별 분해
마이크로서비스 아키텍처를 구축하는 첫 번째 전략은 비즈니스 능력에 따라 분해하는 것이다. 비즈니스 능력은 곧 조직이 하는 일이다.
한 조직의 비즈니스 능력은 조직의 목표, 구조, 비즈니스 프로세스를 분석하여 식별한다. 비즈니스 능력은 보통 특정 비즈니스 객체에 집중하며, 여러 개의 하위 능력으로 분해할 수 있다. 비즈니스 능력을 식별한 후에는 능력에 따라 또는 연관된 능력 그룹에 따라 서비스를 정의한다.
서비스 정의: 하위 도메인 패턴별 분해
'컴퓨터 공학 > 소프트웨어 공학' 카테고리의 다른 글
[마이크로 서비스 패턴] 모놀리식 지옥에서 벗어나라 (0) | 2022.08.12 |
---|