도메인 주도 설계로 시작하는 마이크로서비스 개발

1.1 성공한 인터넷 기업들과 비즈니스 민첩성

11.6초, 아마존의 비즈니스 서비스가 배포되는 주기. 즉, 11.6초마다 아마존 쇼핑몰의 소스코드가 변경되어 배포. 비즈니스는 계속 변경되므로, 개선된 시스템도 계속 배포되어야 된다. 보통의 서비스는 기획, 분석, 설계, 구현 과정을 거쳐 빌드 되고 배포. 아마존 쇼핑몰은 전체 과정이 독립적으로 완료되어, 초당 1.5번씩 서비스가 변경, 개선되고 있다.

1.1.2. 클라우드 인프라의 등장

전형적인 시스템 인프라 구축 과정은 서버를 도입하고,네트워크를 구축한 뒤 각 서버마다 운영체제를 설치하고 서비스에 필요한 소프트웨어를 설치하는 과정으로 진행, 전과정을 완료하기까지 적게는 몇 주, 길게는 몇 달이 걸린다. 어떤 기업은 이 작업만 전담하는 인프라 조직이 있음.

-> 클라우드 서비스 등장으로 이러한 과정이 간소화 (AWS, AZURE 등)

1.1.3 클라우드 인프라에 어울리는 애플리케이션 조건

사용량 증가에 따른 성능 및 가용성을 높이는 방법으로 스케일 업 / 스케일 아웃이 존재

  • 스케일 업은 기존 시스템 자체의 물리적 용량을 증가시켜 성능 높이는 방법. 사용량이 많아진다는 것은 데이터 처리가 증가 했다는 것이고, 시스템을 담을 그릇도 커져야한다.

  • 스케일 아웃은 기존 시스템과 용량이 같은 다수의 장비를 병행 추가하여 가용성을 높이는 방법. 즉 사용량을 분산시켜 전체적으로 장애없이 운영

시스템 운영자가 타임세일 기간에 밀려올 트래픽에 대비하려면?

  1. 첫번째 단계는 스케일 업 / 전체 시스템의 트래픽 최대치를 계산하여 대용량 처리가 가능하도록 시스템 용량을 증설. 그럼에도 예상 트래픽을 초과해 시스템이 다운 가능

  2. 확장 탄력성을 보장하는 스케일 아웃을 설정. 이 경우 CPU나 메모리의 트래픽 양이 한계 수치에 도달하면 시스템의 인스턴스를 설정된 개수로 복제해서 증가시킨다. 즉, CPU 사용량이 70% 이상으로 증가하면 1개였던 쇼핑몰 인스턴스가 2개로 늘어난다. 그럼 사용량이 2대의 인스턴스로 철저히 분산된다.

  3. 1주일간의 세일 기간 중 정작 바쁜 업무를 분리해서, 이부분만 용량을 증설하고 트래픽에 반응해 복제되게 설정한다. 즉, 시스템을 작은 단위의 독립적인 서비스 연계로 구성해야한다.

클라우드 프렌들리와 클라우드 네이티브

큰 덩어리로 클라우드 환경에 올라갈 수 있게만 한 어플리케이션을 클라우드 친화 어플리케이션, 독립적으로 분리되어 배포될 수 있는 조각으로 구성된 어플리케이션을 클라우드 네이티브 -> 클라우드 프렌들리에서 클라우드 네이티브로 전이되어야 한다.

1.2 MSA란?

1.2.1 모노리스와 마이크로 서비스 비교

전통적인 시스템 구조인 모노리스는 하나의 단위로 개발되는 일체식 어플리케이션, 보통 3티어라 불리는 사용자 인터페이스, 데이터 베이스, AP 서버 3부분으로 나눠진다. AP 는 논리적인 단일체로서 아무리 작은 변화에도 새로운 버전으로 전체를 빌드해서 배포해야한다. 확장이 필요한 경우, 특정기능만 확장이 아닌, 전체 어플리케이션을 동시에 확장해야한다. (오버 스펙일 수 있다.) 보통은 로드 밸런서를 앞에 두고 여러 인스턴스 위에 큰 덩어리를 복제해 수평으로 확장한다.

여러개의 모노리스가 수평적으로 확장하면, 전부 다시 빌드하고 배포해야한다. 또한 확장시 애플리케이션이 병렬로 확장되어 사용량 증가에 대응할수 있지만, DB는 통합되어 탄력적으로 대응 할수 없다. 따라서 사전에 성능을 감당하기 위해 스케일 업을 통해 용량을 증설해야한다.

반면 마이크로 서비스는 서버 측이 여러개의 조각으로 구성돼 각 서비스가 별개의 인스턴스로 로딩된다. 즉 여러 서비스 인스턴스가 모여 하나의 비즈니스 애플리케이션을 구성한다. 또한, 각기 저장소가 다르므로 업무 단위로 모듈 경계가 명확하게 구분된다. 각 서비스가 독립적이여서 서로 다른 언어로 개발하는 것도 가능하므로 각 서비스의 소유권을 분리해 서로 다른팀이 개발 운영 가능

1.2.2 SOA와 마이크로서비스

소공에서 말하는 모듈화의 개념 흐름을 보면 단순히 기능을 하향식 분해새서 설계해 나가는 구조적 방법론으로 부터 시작해 객체 단위로 모듈화하기 위한 객체지향 방법론, 모듈화의 단위가 기능별로 재사용할수 있는 CBD 또한, 컴포넌트를 비즈니스적으로 의미있고 완결적인 서비스 단위로 모듈화하는 SOA(Service Oriented Architecture)로 이어지는 발전 과정을 거쳤다.

따라서 CBD와 SOA도 넓게보면 MSA와 비슷한데, SOA는 개념론이고 MSA는 넷플릭스나 클라우드 기술로 인하여 구체화되었다.

1.3. 마이크로 서비스를 위한 조건?

1.3.1 조직의 변화: 업무 기능 중심팀

역할 또는 기술별로 팀이 분리되는 것이 아니라, 업무 기능을 중심으로 기술이 다양한 사람들이 하나의 팀이 도어 서비스.(서버 개발팀 이런거 노노)

1.3.2 관리체계의 변화: 자율적인 분권 거버넌스 : 폴리글랏

중앙의 강력한 거버넌스를 추구하지 않고, 빠르게 서비스를 만드는 것을 최우선. 스스로 효율적인 방법론과 도구,기술을 찾아 적용한다.

1.3.3 개발 생명주기의 변화: 프로젝트가 아니라 제품 중심으로

기존에는 대부분의 애플리케이션 개발 모델이 프로젝트 단위. 그래서 필요한 기술을 사용하는 인력들이 한시적으로 모여 장기간의 프로젝트를 통해 개발을 완료하고 나면 이를 운영 조직에 넘기는 방식으로 진행. 즉, 개발 조직과 운영 조직이 분리

또한, 초기에 모든일정을 계획하여, 요구 사항 정의를 통해 개발할 기능을 나열하고, 이에 대한 설계를 진행하며 설계가 완료돼야 개발이 진행되고, 각 단계는 완료 데드라인이 있어 그 일정을 완료함으로써 최종 기능을 제공한다. 따라서, 프로젝트 기간 중에 발생한 변경이나 새로운 아이디어를 포용하지 못함.

MSA 개발은 비즈니스의 트렌드 변화에 유연하게 대처해야 하고 개발 뿐만아니라 운영을 포함한 소프트웨어의 전체 생명주기를 책임져야한다. 따라서 소프트웨어를 완성해야할 기능들의 집합이 아닌, 비즈니스를 제공하는 제품으로 바라보고, 우선 개발한 뒤 반응을 보고 개선하는 방식으로 소프트웨어를 개발한다. 2~3주 단위의 스프린트를 통해 소프트웨어를 개발 및 배포해서 바로 피드백을 받아 소프트웨어에 반영

1.3.4 개발환경의 변화: 인프라 자동화

MSA가 화려하게 등장한 배경에는 클라우드라는 가상 인프라 발전에 기인. 개발지원 환경을 자동화하는 데는 소스코드를 빌드하는 도구와 빌드와 동시에 테스트하는 도구, 가상화된 인프라에 배포하는 도구가 모두 필요하다. MSA팀이 단기간에 제품을 빨리 개발하고 피드백을 받기위해서는 이러한 개발지원환경의 자동화가 반드시 갖춰져야한다. -> 개발과 운영을 동시에 수행하는 데브옵스를 궁극적으로 가능

빌드 - 개발 환경 배포 - 테스트 환경 배포 - 스테이징 환경 배포 - 운영 환경 배포

Infrasturcture as Code

코드를 이용해 인프라 구성부터 애플리케이션 빌드, 배포를 정의하는 것을 의미하는데, 이렇게 되면 수많은 하드웨어 리소스 설정을 동일하게 통제할 수 있으며, 상황에 따른 검증되고 적절한 설정을 쉽게 복제하고 누구한테나 공유할 수 있게 되서 인프라를 매우 효율적으로 관리할 수 있다.

1.3.5 저장소의 변화: 통합 저장소가 아닌 분권 데이터 관리

단일 데이터 베이스를 유지하는 방식은 과거 스토리지 가격 및 네트워크 속도에 따른 데이터의 안정성과 효율성을 추구한 결과. 따라서 데이터를 잘 정리하는 정규화가 반드시 추구해야 할 가치였다. -> 지금은 필요 없음

MSA는 폴리글랏 저장 접근법을 선택하며, 서비스 별로 데이터베이스를 갖도록 설계. 즉, 각 저장소가 서비스별로 분산돼 있어야 하며, 다른 서비스의 저장소를 직접 호출할수 없고, API를 통해서만 접근해야한다는 의미이다.

그런데, 이러한 구조에서는 비즈니스 처리를 위해 일부 데이터의 복제와 중복 허용이 필요하다. 여기서 반드시 등장하는 문제는 바로 각 마이크로서비스의 저장소에 담긴 데이터의 비즈니스 정합성을 맞춰야하는 데이터 일관성 문제

데이터 일관성 처리를 위해서는 보통 2단계 커밋 같은 분산 트랜잭션 기법을 사용하는데, 각각 다른 서비스를 하나의 트랜잭션으로 묶다보면 각 서비스의 독립성도 침해되고 NoSQL 저장소처럼 2단계 커밋을 지원하지 않는 경우도 있다. 따라서 마이크로서비스는 데이터 일관성 문제를 처리하기 위해 두 서비스를 단일 트랜잭션으로 묶는 방법이 아닌 비동기 이벤트 처리를 통한 협업을 강조한다.(Kafka)

이를 가리켜 결과적 일관성이라는 개념으로 표현하는데, 간단히 말하면 두 서비스의 데이터가 일시적으로 불일치하는 시점에 있고 일관성이 없는 상태지만 결국에는 데이터가 같아진다는 개념. 즉, 여러 트랜잭션을 하나로 묶지 않고 별도의 로컬 트랜잭션을 각각 수행하고, 일관성이 달라진 부분은 체크해서 보상 트랜잭션으로 일관성을 맞춘다.

  1. 주문 서비스가 주문 처리 트랜잭션을 수행한다.

    1. 동시에 주문 이벤트를 발행한다.

    2. 주문 이벤트가 메시지 큐로 전송

    3. 배송 서비스가 주문 이벤트를 인식

  2. 배송 서비스가 주문 처리에 맞는 배송 처리 트랜잭션을 수행(비즈니스 일관성 만족)

  3. 배송 처리 트랜잭션 중 오류로 트랜잭션을 실패한다.

    1. 배송 처리 실패 이벤트를 발행한다.

    2. 배송 처리 실패 이벤트가 이벤트 큐로 전송된다.

    3. 주문 서비스가 배송 처리 실패 이벤트를 인식한다.

  4. 주문 서비스는 주문 취소(보상트랜젝션)을 수행한다.(비즈니스 일관성 만족)

1.3.6 위기 대응 방식의 변화: 실패를 고려한 설계

시스템은 언제나 실패할수 있으며 실패해서 더는 진행할수 없을떄도 자연스럽게 대응 할수 있도록 설계해야한다.

예전 시스템 아키텍쳐는 결함이나 실패 무결성을 추구 -> 다양한 실패에 대비해 완벽히 테스트 할수 있는 환경 마련및 시스템의 실패를 감지하고 대응하기 위해 실시간 모니터링 체계도 갖춰야한다. Ex) Circuit break pattern, Chaos Monkey

Last updated