반응형

인상깊은 부분

분산 시스템에서의 데이터 무결성

BASE 분산 트랜잭션라는 새로운 개념의 존재를 알게 됨
분산도가 높은 아키텍처에서는 최종 일관성 기반의 BASE 분산 트랜잭션 활용. 이 기법은 최종 일관성 기반이므로 ACID 트랜잭션 레벨의 데이터 무결성은 지원하지 않음

최종 일관성이란 별도로 분리된 배포 단위에서 처리된 데이터를 미리 알 수 없는 어느 시점에 모두 일관된 상태로 동기화한다.
확장성, 성능, 가용성을 얻는 대가로 데이터 일관성과 무결성을 희생하는 트레이드오프인 셈이다

트랜잭션 사가

오케스트레이션 및 코레오그래피

DB 분리 시 도메인 서비스 간 상호 통신 방지와 데이터베이스 간 중복 데이터 방지를 고려

서비스 기반 아키텍처에서 단일 모놀리식 데이터베이스를 개별 데이터베이스로 분리할 수 있고, 마이크로서비스와 비슷하게 각 도메인 서비스의 전용 데이터베이스들로도 쪼갤 수도 있음
여기서 포인트는 각 데이터베이스에 있는 도메인 데이터를 다른 도메인의 서비스가 필요로 하지 않도록 설계하는 것임
그래야 도메인 서비스 간 상호 통신을 방지하고 데이터베이스 간의 중복 데이터가 방지됨

서비스 단위에 따른 트레이드 오프

서비스 기반 아키텍처는 도메인 서비스의 단위가 크기 때문에 데이터 무결성, 일관성 측면에서 유리하다.
반면 서비 스규모가 작은 MSA와 같은 아키텍처는 작은 서비스 하나만 변경 영향도가 있고, 서비스가 한 가지 역할만 수행하므로 변경을 해도 다른 기능이 망가질 일이 거의 없다.


요약

  • 서비스 기반 아키텍처(service-based architecture)는 마이크로서비스 아키텍처 스타일의 일종으로, 가장 실용적인 아키텍처 스타일 중 하나
  • 유연하고 비교적 덜 복잡하고 비용이 많이 들지 않아서 널리 채택됨

13.1 기본 토폴리지

  • 기본 구성
    • 각각 따로 배포된 유저 인터페이스, N개의 원격 서비스, 그리고 모놀리스 데이터베이스
    • 이 아키텍처 스타일에서 '서비스'는 큼지막한 단위로 분리해 별도로 배포하는 어플리케이션의 일부 (보통 도메인 서비스라고 함)
    • 여러 서비스가 단일 모놀리식 데이터베이스를 공유하며, 서비스는 보통 4개~12개, 평균 7개 정도
  • 배포 : 도메인 서비스는 각각 단일 인스턴스로 배포되지만, 확장성/내고장성/처리량 요구사항에 따라 N개의 인스턴스를 둘 수 있음
  • 통신
    • 유저 인터페이스 외부에서 원격 액세스 프로토콜로 서비스에 접속 가능함. 프로토콜은 일반적으로 REST를 많이 쓰며, 메시징, 원격 프로시저 호출(RPC), SOAP도 사용 가능함
    • 유저 인터페이스(또는 외부 요청)은 프록시나 게이트웨이로 구성된 API 레이어를 통해 서비스 접속 가능하지만, 대개는 [[서비스 로케이터 패턴(service locator pattern)]]에 따라 유저 인터페이스, API 게이트웨이, 프록시에 내장된 유저 인터페이스를 직접 액세스함
  • 서비스 기반 아키텍처는 중앙 공유 데이터베이스를 사용한다는 특징이 중요. 서비스는 기존 모놀리식 레이어드 아키텍처와 동일한 방식으로 쿼리와 조인 기능을 사용함

13.2 토폴로지 변형 (다양한 구성)

  • 유저 인터페이스 변형 (그림 13-2)
  • 데이터베이스 변형 (그림 13-3)
    • 단일 모놀리식 데이터베이스 역시 개별 데이터베이스로 분리할 수 있고, 각 도메인 서비스 전용 데이터베이스들로도 쪼갤 수 있음
    • 데이터베이스 분리 시 중요한 점은, 각 데이터베이스에 있는 도메인 데이터를 다른 도메인 서비스가 필요로 하지 않도록 설계하는 것.그래야 도메인 서비스 간 상호 통신을 방지하고 데이터베이스 간의 중복 데이터를 방지할 수 있음
  • API 레이어 추가 (그림 13-4)
    • 리버스 프록시 또는 게이트웨이로 구성된 API 추가 가능
    • 도메인 서비스의 기능을 외부 시스템에 표출하거나 공통 관심사를 통합해서 유저 인터페이스 밖으로 떼어낼 경우에도 유용한 방법
      ![[소프트웨어 아키텍처 101 13장 다양한 토폴로지.png]]

13.3 서비스 설계 및 세분도 (최상위 분할)

  • 서비스 기반 아키텍처의 도메인 서비스는 보통 단위가 크기 때문에 레이어드 아키텍처 스타일로 기술 분할하는 방법이 일반적이지만, 도메인 분할도 쓰인다.
  • API 액세스 퍼사드(access facade)
    • 유저 인터페이스를 통해 유입된 비즈니스 요청을 오케스트레이트
    • 어떻게 분할하든 도메인 서비스는 유저 인터페이스에서 비즈니스 기능을 호출하기 위해 접속할 수 있게 API 액세스 퍼사드를 제공해야함
  • 세분도 관점에서의 서비스 아키텍처와 MSA의 차이 (API 액세스 퍼사드)
    • 서비스 기반 아키텍처는 내부 클래스 수준의 오케스트레이션
      예를 들어, 유저 인터페이스에서 주문이 접수되면 OrderService 도메인 서비스의 API 액세스 퍼사드가 받아 내부 처리 후, 재고 차감 등의 일련의 비즈니스 요청을 오케스트레이트함
    • MSA는 외부 서비스의 오케스트레이션
      • 예를 들어, 위와 같은 요청을 MSA에서 처리한다면 별도 배포된 다수의 원격 서비스를 오케스트레이션 해야함
  • 데이터 무결성
    • 단일 도메인 서비스 - 커밋/롤백이 수반되는 [[ACID 트랜잭션]] 데이터베이스 트랜잭션 활용
      예를 들어, 고객이 주문 후 만료된 신용카드로 결제를 했다면, 동일 서비스에서 발생한 원자적 트랜잭션이니 데이터베이스에 추가된 주문 관련 데이터를 롤백해서 모두 삭제하고 해당 고객에게 더 이상 결제 진행이 불가함을 알릴 수 있음
    • 분산도가 높은 아키텍처(ex: 마이크로 서비스) - 최종 일관성 기반의 [[BASE 분산 트랜잭션]] 활용. 이 기법은 최종 일관성 기반이므로 ACID 트랜잭션 레벨의 데이터 무결성은 지원하지 않음
      서비스를 잘게 나눈 MSA에서 위와 동일하게 만료된 신용카드로 결제를 했다면, 주문 데이터는 데이터베이스에 삽입되었으나 결제는 불가하고 주문 처리를 진행할 수 없어서 비일관된 상태(inconsistent state)가 됨. 그렇다면 주문과 관련된 재고 정보는 주문이 성공한 것으로 보고 재고 차감을 해야할까요? 만약 재고가 없는 상태에서 다른 고객이 동일 제품을 주문한다면 새 고객이 구매할 수 있게 해야할까, 아니면 신용카드가 만료된 고객이 주문을 마칠 수 있도록 재고를 확보해두어야할까?
    • 서비스가 잘게 나누어진 아키텍처에서 비즈니스 프로세스를 오케스트레이트하려면 신경 써야 할 문제가 많다.
  • 트레이드 오프
    • 서비스 기반 아키텍처의 도메인 서비스는 단위가 커서 데이터 무결성과 일관성 측면에서는 유리하지만 배포와 변경 영향도 측면에서는 트레이드오프가 존재함
    • 서비스 기반 아키텍처는 일부 기능이 변경되어도 서비스 전체를 테스트해야함
    • 반면, 규모가 작은 서비스 단위의 아키텍처는 작은 서비스 하나만 변경 영향도가 있고, 서비스가 한 가지 역할만 수행하므로 변경을 해도 다른 기능이 망가질 일이 거의 없음

13.4 데이터베이스 분할

  • 단일 모놀리식 데이터베이스 공유 시 문제
    • 서비스 기반 아키텍처는 서비스 수가 적은 편이라 보통 단일 모놀리식 데이터베이스를 공유함
    • 데이터베이스 커플링은 테이블 스키마 변경 시 문제가 될 수 있음
    • 테이블 스키마를 올바르게 변경하지 않을 경우 모든 서비스에 악영향을 미침
  • 공용 스키마 관리
    • 단일 공유 라이브러리 활용 (그림 13-6)
      • 테이블 구조를 조금이라도 변경하게 되면, 변경된 테이블의 사용 여부와 상관없이 전체 서비스를 일제히 변경 후 재배포할 수 밖에 었음
    • 여러 공유 라이브러리 활용 (그림 13-7)
      • 변경 영향도와 리스크를 낮추기 위해 데이터베이스를 논리적으로 분할하고 이러한 논리 분할을 연합 공유 라이브러리를 통해 명시 (논리적으로 분할 시 변경 관리에 용이함)
      • 단, 모든 서비스가 참조하는 공통 테이블을 변경하려면 전체 서비스와 미리 조율이 필요함. 테이블 변경 영향도를 낮추는 방법 중 하나는 공통 엔티티 객체를 버전 관리 시스템에서 락킹하고 수정 권한을 DBA팀에만 부여하는 것임. 이렇게 해야 변경을 통제할 수 있고 모든 서비스의 공용 테이블 변경하는 작업의 중요성이 부각됨

13.5 아키텍처 예시

  • 전자제품 재활용 시스템을 예로 서비스 기반 아키텍처의 유연함과 강점을 살펴보자. 중고 전자 제품 재활용 프로세스는 아래와 처리 순서로 이뤄진다.
    • 견적 (quoting) : 고객이 자신의 중고 제품을 얼마에 보상받을 수 있는지 문의
    • 수취 (receiving) : 고객이 보상가에 만족하면 회사에 제품을 보내고 회사는 실물을 받음
    • 감정 (assessment) : 고객이 보낸 제품의 작동 상태를 꼼꼼히 평가
    • 회계 (accounting) : 상태가 좋을 경우 회사는 고객에게 약속한 보상가를 지불
    • 제품 상태 (item status) : 이 과정 중 고객은 언제든 회사 웹사이트에 접속하여 진행 상황 확인 가능
    • 재활용 (recycling) : 감정 결과에 따라 제품은 해제 후 재활용되거나 재판매
    • 리포팅 (reporting) : 재활용 성과에 따른 임시/정기 재무 리포트를 정기적으로 체크
  • 전자 제품 재활용 서스템을 서비스 기반 아키텍처로 설계 (그림 13-8)
    • 유저 인터페이스와 각 도메인의 연합 덕분에 유저 인터페이스의 내고장성, 확장성, 보안이 실현됨
    • 퀀텀 (2개)
      • 외부에서 고객을 상대하는 퀀텀 - 높은 처리량이 필요한 서비스의 확장성 확보
      • 내부 운영 퀀텀 - 그 밖에 서비스는 내부 운영이므로 확장할 필요가 없으니 단일 인스턴스로 설정
    • 보안
      • 외부 고객은 내부 기능으로 향하는 네트워크에 접속 불가
      • 내부 데이터와 기능을 외부 작업과 분리된 별도 네트워크 영역에 두어 데이터 보안에 긍정적 요소
      • 방화벽을 통해 내부 서비스는 단방향으로 외부 서비스에 접근 가능하지만, 반대 케이스는 불가
    • 데이터베이스 분리
      • 외부 고객 처리용 데이터베이스와 내부 처리용 데이터베이스를 물리적으로 분할
      • 데이터베이스에 따라서 내부 테이블을 미러링하고 테이블을 동기화할 수 있음
    • 변경이 잦은 서비스를 단일 도메인 서비스로 격리하여 민첩성(얼마나 빨리 변화에 대응할 수 있나), 시험성(테스트하기 얼마나 쉽고 완전한가), 배포성(배포의 난이도, 빈도, 리스크)을 높일 수 있음

13.6 아키텍처 특성

등급별점 5개 받은 특성은 없지만 두루두루 밸런스 좋은 아키텍처이다.

아키텍처 특성 별점 설명
분할 유형 도메인 도메인 위주로 구성된 아키텍처
퀀텀 수 하나 또는 여러 개 동일한 데이터베이스나 유저 인터페이스를 공유할 경우 전체 시스템의 퀀텀은 1이지만, 유저 인터페이스와 데이터베이스는 분리되어 연합될 수 있으므로 전체 시스템 내부에 여러 퀀텀이 생길 수 있음 그림 13-8 전자 제품 재활용 시스템의 퀀텀은 2임
배포성 ⭐️⭐️⭐️⭐️ 개별 배포되는 여러 도메인 서비스로 나누기 때문에 덩치 큰 모놀리스보다 덜 위험하게, 더 자주 배포할 수 있음
탄력성 ⭐️⭐️ 서비스를 나누는 단위가 크기 때문에 별점 2점 프로그램 방식으로 탄력성을 추구할 수 있지만 중복되는 기능이 많아 머신 리소스 및 비용 측면에서 효율적이지 않음 그리고 처리량이나 페일오버를 개선해야하는 요건이 따로 없다면 서비스 인스턴스는 1개임. 단일 인스턴스는 인메모리 캐시, 데이터베이스 커넥션 풀링 지원이 더 간편함
진화성 ⭐️⭐️⭐️ -
내고장성&가용성 ⭐️⭐️⭐️⭐️ 자기 완비형이고 데이터베이스와 코드를 공유하는 까닭에 서비스 간 통신이 거의 없고, 어느 도메인 서비스가 잘못돼도 다른 서비스는 옇양을 받지 않음
모듈성 ⭐️⭐️⭐️⭐️ -
전체 비용 ⭐️⭐️⭐️⭐️ 가장 구현하기 쉽고 비용면에서도 효율적인 분산 아키텍처로, 단순성과 전체 비용 측면에서 다른 분산 아키텍처와 차별화됨
성능 ⭐️⭐️⭐️ -
신뢰성 ⭐️⭐️⭐️⭐️ 도메인 서비스를 굵직하게 나누기 때문에 다른 분산 아키텍처에 비해 신뢰성이 우수함. 서비스 간 네트워크 트래픽이 적고 대역폭을 덜 사용하며, 분산 트랜잭션이 많지 않기 때문에 전반적으로 네트워크 측면에서 신뢰성이 좋음
확장성 ⭐️⭐️⭐️ 서비스를 나누는 단위가 크기 때문에 별점 3점 프로그램 방식으로 확장성을 추구할 수 있지만 중복되는 기능이 많아 머신 리소스 및 비용 측면에서 효율적이지 않음 그리고 처리량이나 페일오버를 개선해야하는 요건이 따로 없다면 서비스 인스턴스는 1개임. 단일 인스턴스는 인메모리 캐시, 데이터베이스 커넥션 풀링 지원이 더 간편함
단순성 ⭐️⭐️⭐️ 가장 구현하기 쉽고 비용면에서도 효율적인 분산 아키텍처로, 단순성과 전체 비용 측면에서 다른 분산 아키텍처와 차별화됨
시험성 ⭐️⭐️⭐️⭐️ 개별 배포되는 여러 도메인 서비스로 나누기 때문에 도메인 범위가 한정되므로 테스트 커버리지가 향상
민첩성 ⭐️⭐️⭐️⭐️ 개별 배포되는 여러 도메인 서비스로 나누기 때문에 신속한 변경이 가능함

13.7 언제 서비스 기반 아키텍처를 사용하는가

  • 단순성과 비용 측면에서 가장 실용적인 아키텍처
    • 이보다 더 강력한 분산 아키텍처 스타일도 있지만, 그 강력함은 곧 가파른 비용 상승을 동반하고 그렇게 까지 강력할 필요가 없음을 알게됨
  • 도메인 주도 설계와 궁합이 좋음
  • ACID 트랜잭션 사용 비율이 높음
    • 분산 아키텍처에서는 전통적인 ACID 트랜잭션이 아닌 최종 일관성에 의존하는 방식으로 수행되기 때문에 데이터베이스 트랜잭션을 관리하고 조율하는 일이 늘 골칫거리임
    • 그러나 서비스 기반 아키텍처의 도메인 서비스는 큼지막한 단위로 구성되므로 다른 분산 아키텍처에 비해 ACID 트랜잭션이 더 잘 보존됨
    • 물론, 유저 인터페이스나 API 게이트웨이가 둘 이상의 도메인 서비스를 오케스트레이션하는 경우도 있는데, 이럴 때에는 트랜잭션이 사가와 BASE 트랜잭션에 의존해야함
    • 그러나 대부분 트랜잭션은 특정 도메인 서비스에 한정되므로 전통적인 커밋/롤백 트랜잭션 기능을 그대로 사용할 수 있음
  • 아키텍처 모듈성
    • 복잡도와 세분도의 함정에 허우적거리지 않고도 모듈성을 괜찮은 수준으로 달성할 수 있음
    • 서비스를 더 잘게 나눌수록 [[오케스트레이션]] 및 [[코레오그래피]] 관련 이슈가 발생함. 여러 서비스를 조율해서 비즈니스 트랜잭션을 완성하려면 이 둘 다 필요함
    • 그러나 서비스 기반 아키텍처의 서비스는 더 큰 단위로 나뉘어지는 편이라서 다른 분산 아키텍처 만큼 정교한 조율이 필요하지 않음
반응형