레퍼런스 아키텍쳐 중 Common Architecture라고 할 수 있는 SOA 아키텍쳐에 대해서 정리
1. 서비스 지향 아키텍쳐 aka.SOA
MSA의 원조격이라고 볼 수 있는 아키텍쳐이다
Rest API 이전에 사용했으며 SOAP이라는 프로토콜을 사용했었다 (SOA는 아키텍쳐, Rest API는 통신 프로토콜)
SOA는 2000년대 초반에 많이 유행했던 아키텍쳐이다
기본적으로 MSA와 비슷하게 Rest API로 나눠진 서비스 분산 시스템이다
SOA의 등장 배경은 Business Agility이다. 즉, 비즈니스의 기동성을 높이기 위해 백엔드 단의 시스템을 변경이 용이하고 재사용이 쉬운 구조로 만들기 위해 등장
2. 서비스란?
서비스란 기본적으로 플랫폼에 종속되지 않는 표준 인터페이스(ex. Rest API)를 통해서 기업의 업무를 표현한 소프트웨어 컴포넌트이다 (비즈니스적인 측면이 있어야 함) → 기본적으로 그렇다는 것이고 상황에 따라 아닌 것도 해야하는 경우가 있을 수 있음, 항상 유연한 사고 방식
서비스 인터페이스는 Rest API를 의미한다고 보면 됨
서비스 사용 규약은 서비스 인터페이스를 사용하면서 주고 받는 데이터 양식 (예전에는 위 예시처럼 JSON이 아닌 특정 양식을 사용하기도 했음)
Vertical Slicing는 API에서부터 DB Access Layer까지 하나의 컴포넌트로 이루어진다는 것을 의미한다 (하나의 API로 API Interface부터 DB까지 이어진다는 의미)
Coarse Grained는 서비스를 너무 세분화하지 말라는 의미이다
Discoverable은 실제 IP를 찾아갈 수 있게 설계했느냐를 의미한다
예를 들어 Master DB와 레플리카 DB가 있다고 해보자. 레플리카는 오토스케일링이 가능하고 레플리카 엔드포인트를 제공해준다. 엔드포인트(DNS)를 통해서 라운드로빈을 통해 서버 IP를 얻을 수는 있다. 하지만 오토스케일리은 초 단위로 빠르게 확장하고 축소하는 것에 비해 DNS는 업데이트되는데 1분 이상이 걸린다.(심하면 1시간 이상). 이런 경우에 어떻게 하면 Discoverable mechanism을 구현할 수 있을까?
간단한 키벨류 스토어를 이용하면 된다. 1번, 2번, 3번 레플리카가 생길 때마다 키벨류 스토어에 저장해주는 식으로 사용하면 빠르게 서버 IP를 제공할 수 있다
이런 방식을 자주 사용하다보니 Service Discovery Pattern이라는 것으로 굳혀졌고 가장 대표적인 오픈소스가 HashCorp사의 Consul이라는 오픈소스이다. (Netflix Eureka란 것도 있음)
알게 모르게 Discovery Service가 많이 사용되고 있다. 쿠버네티스 내에도 Discovery Service를 제공해주는 서비스가 존재한다
SOA의 모든 서비스들은 기본적으로 Discovery Pattern에 의해 하나의 Dictionary Server에 등록되어 있기 때문에 Lookup이 가능하다. IP만 저장하는 것이 아니라 어떤 서비스인지도 저장하기 때문에 해당 서버의 정보를 빠르게 찾을 수 있다
요즘은 엔드포인트는 이런 Consul과 같은 오픈소스를 사용하고, 어떤 서비스인지에 대한 정보는 API 문서를 이용하는 추세이다 (보기 편하니까)
일반적으로 SOA에서 정의하는 서비스의 종류는 크게 두가지로 나누어진다
Task Centric Service → 실제 Task, 예를 들어 회원가입, 상품 주문 등
Data Centric Service → Data를 조회, 주문 조회, 사용자 조회 등
Data Fabric Architecture
Mysql, Elastic Search, Spark 등 여러가지 데이터베이스를 접근하려는 방법이 다 다르기 때문에 API 서버를 하나 만들어서 공통의 인터페이스를 제공하여 데이터베이스를 접근하려고 하는 개념
사실상 거의 불가능... 왜냐하면 각 데이터베이스끼리 요구하는 성능이 다르기 때문에 자칫 잘못하면 고성능 데이터베이스를 타깃으로 했던 수많은 API 요청이 저사양 데이터베이스로 가면 서버가 죽을 수도 있음. 물론 쓰로틀링 또는 접근 제어를 할 수는 있겠지만... 굳이...? 배보다 배꼽이 큼. 차라리 공통의 레이어를 두지말고 각각 API를 하고 말지...
Intermediary 서비스 : 새로운 기능이 추가될 때 기존의 프로세스는 유지하면서 기능만 추가하고 싶을 때 사용할 수 있다.
예를 들어 기존에는 구매 프로세스만 사용하다가 포인트 적립 프로세스를 추가하고 싶은데 기존 프로세스는 최대한 건드리지 않고 추가하고 싶다. 그러면 중간에 Intermediary 서비스를 둬서 구현할 수 있다. Intermediary는 중간에서 포인트 적립이 필요하지 않으면 그냥 구매 프로세스로 넘기고, 포인트 적립이 필요하면 포인트 적립 후 구매 프로세스를 넘기던지 할 수 있다 → Functional Adding
일반 고객이냐 VIP 고객이냐 또는 안드로이드 클라이언트? 아이폰 클라이언트? 글로벌 서비스 배포 중일 때 한국 고객? 미국 고객? 이런 식으로 라우팅할 수도 있다 → Routing
금융권에서 ATM 기기가 아직 옛날 프로토콜을 사용 중인데 백엔드를 Rest API로 바꿨을 때 굳이 시스템을 변경할 필요 없이 Intermediary를 통해 중간에서 프로토콜을 바꿀 수도 있다. 아니면 필드를 변경하던가 → Transformation
Process Centric 서비스 : 각각의 컴포넌트를 Use Case에 따라 묶어주는 서비스
즉, 각각의 API 서비스들을 호출해서 오케스트레이션 해주는 것
요즘은 프론트엔드 단에서 이 기능들을 수행하고 있다
Application 서비스 : 비즈니스 용도의 서비스 이외에 테크니컬적으로 필요한 서비스들, 예를 들어 서비스 디스커버리 같은 룩업 서비스나 오토스케일링을 트리거해주는 서비스던가 이런 것들
Public Enterprise 서비스 : 외부로 인터페이스해주는 서비스, 예를 들어 금융결제원, 신용평가원 등으로 인터페이스해주는 서비스
2-1. 서비스 종류 요약
보통 비즈니스 서비스랑 애플리케이션 서비스는 다 사용하고, 그 담에 퍼블릭 엔터프라이즈 서비스를 자주 사용할 것이다
3. SOA 아키텍쳐 발전 모델
3-1. Fundamental SOA
그냥 서비스들만 존재하고 서비스들과 애플리케이션을 조합하는 것
대부분의 Rest API 구조가 이것을 따른다
3-2. Networked SOA
Fundamental SOA은 서비스들 간의 의존성 문제 때문에 규모가 커지면 매우 복잡해짐. 그리고 장애 전파가 쉬움.
그래서 Networked SOA가 등장했다. 중간에 버스를 둠. 그리고 통신을 버스를 통해서만 진행 → 넷플릭스가 이런 구조를 사용 중이다
버스 안에 Intermediary를 두어 라우팅, 트랜스포메이션 등을 수행 가능
하지만!! 기능을 많이 넣을 수 있다고 사람들이 다 버스 안에 기능을 넣다보니 요구 사양이 높아지고, 자칫 잘못해서 버스가 먹통이 되면 서비스 전사 에러가 발생 → Single Failure Point
이런 단점을 개선하여 API Gateway가 나옴
Intermediary는 컨셉 자체는 굉장히 좋으나 경량화할 수 있는 방법을 고민해보고 도입해야 됨
3-3. Process Oriented SOA
대출 신청할 때 프로세스를 따로 따로 하는게 아니라 한번에!
중간에 결재를 받아야 하는 것이 있다면 그것까지 자동화 → SAP 같은 것임
BPA는 비즈니스 프로세스를 시뮬레이션해줌 → 어느 부분에서 얼마나 지연?, 인건비 얼마나 발생? 이런 것을 확인할 수 있음
BAM는 모니터링 서비스
4. SOA Reference Structure
Service Registry : 서비스가 어디있는지 찾을 수 있게 해주는 서비스
Data Adapter : Data Fabric 서비스와 같다고 생각하면 됨
EAI (Enterprise Application Integration) : ERP나 CRM과 같은 외부 서비스들을 연동
EAI에서는 서비스 간의 통합이기 때문에 각 팀간의 협업이 중요하다. 서로 통신 스키마를 맞추던지...그런... 요즘은 클라우드에 서비스가 많이 올라와 있어서 표준을 맞추기가 쉬운 편이다. 그래서 firetran 같은걸 사용하면 쉽게 통합할 수 있다. (이미 많은 서비스들이 올라와 있음) https://www.fivetran.com/connectors
온프렘 같은 경우에는 EAI를 할 때 그냥 Webmethod, Tibco 불러서 돈 주고 시키면 됨
굉장히 많은 서비스들이 있지만 결국에는 하나의 API 인터페이스로 통신한다
5. SOA 구현시 고려 사항
Task Centric Service와 Data Centric Service를 잘 구분할 것
특히 Application 서비스는 분리를 잘 해야 실제 아키텍쳐 디자인할 때 Task가 꼬일 수 있음
Intermediary 서비스는 단점 보완을 위해 API Gateway를 사용하는 방법이 있기는 하지만 양날의 검이다. 그래서 조직의 성숙도가 굉장히 높지 않으면 사용하지 않는 것이 권장된다
5-1. 트렌젝션 처리
완벽한 해결 방법이 없기 때문에 두 개의 DB를 엑세스할 수 있는 서비스를 따로 만드는 것이 가장 나은 방법이다 → XA (eXtended Architecture), XA를 사용하면 commit할 때 한쪽에 이상이 생기면 롤백하는 기능을 적용할 수도 있음
하지만 이렇게 하면 Vertical Slicing이 제대로 안되어서 시스템이 지저분 해보일 수 있음. 그리고 XA는 비용이 비쌈
트렌젝션 보장이 정말 필요한지를 먼저 생각해야한다 → 은행권 같은 경우에는 출금이 됐는데 db에 안찍히면? 매우 크리티컬한 상황이니까 트렌젝션 보장이 필수이지만, 예를 들어 쿠팡 같은 경우에 주문을 했는데 주문 오더가 업데이트가 안되는 상황이 1% 정도이고 XA를 도입하는데는 100억이 들어간다고 가정해보자. 이런 상황에서 트렌젝션 보장을 위해 100억을 투자하는 것이 합리적인 판단일까? 차라리 주문이 이상하게 들어간 고객에게 100만원짜리 쿠폰을 준다면? 이게 더 낫지않을까? → 항상 아키텍쳐를 설계할 때 유연한 사고 방식을 가져야 한다. 너무 기술에만 매몰되지 말자