본문 바로가기

엔지니어링(TA, AA, SA)/아키텍처

[MSA] "마이크로서비스 아키텍처 구축" 훑어보기

기존의 일반적인 애플리케이션 개발 방법을 그대로 적용하면 비용절감, 탄력성, 회복성, 배포 편의성과 같은 좋은 특성을 누리기 어렵다. 아키텍처 설계, 서비스 모델링, 실제 구현, 통합, 배포, 테스트, 모니터링, 확장에 포인트를 두면 클라우딩 컴퓨팅 환경에 걸맞는 서비스를 구축할 수 있다.

 

아키텍처 설계, 실제 구현, 운영 업무에 있어 새로운 관점을 갖게 한다. 미시적인 컴퓨터 프로그램이 부분에서 리팩토링이 기술 부채를 줄이는 수단이라면, 거시적인 서비스 개발과 운영 부문에서는 마이크로서비스가 기술 부채를 줄이는 강력한 수단이다.

 

아키텍처는 한번 잘못 설계하면 되돌리기 매우 어려운 만큼 처음부터 충분한 고민이 필요하다. 코드 그 이상의 주제를 제시한다. 마이크로서비스 아키텍처는, 커다란 모듈로 이뤄진 전통적인 모놀리식 방식이 아닌, 애플리케이션을 작은 서비스 단위로 설계하고 지속적 관리와 배포를 지향한다. 애플리케이션과 서비스 개발을 할때 아키텍처적 접근 방법을 숙지하고, 애플리케이션 수명주기 전반에 걸쳐 마이크로서비스를 실제로 적용할 때 고려할 사항을 본질적 관점을 갖는 것이 포인트이다.

 

경험이 많지 않거나, 비즈니스 도메인에 대한 이해가 낮다면 무리한 마이크로서비스의 도입보다는 모놀리스에서 시작해서 점진적으로 분해하는 것이 좋다. 마이크로서비스(설계, 개발, 통합, 배포, 테스팅, 모니터링, 보안, 운영, 조직)에 대한 이론 체계를 정립한 뒤에, 적용할 것을 추천한다.

 


1장 마이크로서비스

마이크로 서비스가 가져다주는 주요 혜택을 단점과 소개

 

2장 진화적 아키텍트

아키텍트로서 상충관계의 타협점을 찾는 괒어에서 직면하는 어려움을 논의하고 마이크로서비스에 대해 생각해야 하는 많은 사항을 구체적으로 다룬다.

 

3장 서비스 모델링하기

도메인 주도 설계 기술을 사용해서 마이크로서비스의 경계를 정의

 

4장 통합

어떤 서비스 협업 기술이 가장 도움이 될지 논의하여, 특정 기술의 구현체를 깊이 살펴본다.

 

5장 모놀리스 분해하기

대규모이며 변경이 어려운 모놀리식 시스템에 마이크로서비스가 대안이 될수 있다.

 

배포/테스팅...

 

8장 모니터링

출시 후에 문제가 발생한다면 운영 전에 수행한 테스트가 도움이 되지 않았다는 의미다. 세분화된 시스템을 모니터링하고 분산 시스템에서 출현하는 복잡성을 다루는 방법을 살펴본다.

 

9장 보안

사용자 대 서비스와 서비스 대 서비스 인증 및 권한 처리 방법을 고민한다. 

 

10장 콘웨이의 법칙과 시스템 설계

조직 구조와 아키텍처의 상호 작용에 중점을 둔다. 이 두가지가 서로 조화를 유지하지 못한다면 문제가 발생할 수 있다. 그 원인을 밝히고 팀의 구조와 시스템 설계를 맞추는 여러 방법을 고려한다.

 

11장 대규모 마이크로서비스

앞에서 다룬 모든 것을 대규모로 운영하기 위한 검토를 다룬다. 수많은 서비스와 늘어난 트래픽으로 인해 높아진 실패 가능성을 처리하는 방법을 알아본다.

 

마이크로서비스의 7원칙

 1. 비즈니스 개념에 따른 모델 / 2. 자동화 문서의 적용 / 3. 내부 세부 구현의 은폐 / 4. 모든 것을 분권화 / 5. 독립적인 배포 / 6. 장애 격리 / 7. 식별 가능한.

 


"도메인 주도 설계"는 실세계를 코드로 표현하는 일이 얼마나 중요한지 이해하는데 도움을 주었으며, 시스템을 모델링하는 더 나은 방법을 보여주었다.

 

지속적 배포는 체크인한 모든 것을 릴리스 후보로 대해야 한다는 생각을 우리에게 주입시켰고, 어떻게 하면 더 효과적이면서 효율적으로 소프트웨어를 양산할 수 있는지 보여주었다. 웹동작 원리를 이해함으로써 머신들이 통신할 수 있는 더 나은 방법을 개발하게 되었다.

 

육각형 아키텍처(Ports and Adapters 패턴 - 외부 세계와 인터페이스를 담당하는 프레임워크 계층, 비즈니스 로직의 애플리케이션 계층, 도메인 계층으로 분리하여 서비스의 이식성, 테스트 가용성, 변화를 최소화할 수 있는 아키텍처) 개념은 우리가 비즈니스 로직이 숨을 수 있는 계층형 아키텍처로부터 멀어지도록 안내했다.

 

가상화 플랫폼은 머신을 원하는 대로 프로비저닝(가상화된 인프라 자원 네트워크, 가상머신, OS, 소프트웨어, 설정 등을 사용자 또는 비즈니스 요구 사항에 맞게 할당, 배치, 배포, 구성하여 사용할 수 있도록 하는 일련의 작업)하고 규모를 조절하게 해주었다.

 

인프라스터럭처 자동화는 머신을 확장하는 방법과 확장 가능한 antifragile system(충격에 강하거나 탄력적이라는 의미보다는 충격으로 인해 더 단단해지고 강해진다는 개념?)을 구축하는 방법을 제공되고 있다.

 

도메인 주도 설계, 지속적 배포, on-demand virtualization, infrastructure automation, 작고 자율적인 팀, 대규모 시스템 등으로 마이크로서비스는 실사용을 기반하여 하나의 패턴으로 부상했다. 마이크로서비스란 작고 자율적으로 협업하는 서비스를 말한다. 

 

 

1) 작고, 한가지 일을 잘하는데 주력

명확하고 모듈화된 monolithic식(데이터 입력, 출력, 프로세싱, 에러 처리, UI와 같은 구분된 기능들이 분리되어 있지 않고 혼합된 구조의 시스템) 코드베이스를 추구하더라도 중간 경계의 어딘가가 빈번히 무너지기 시작하고, 버그를 고치거나 어려운 구현을 하는 과정에서 유사한 기능과 연관된 코드가 곳곳으로 퍼져나간다.

 

응집력, 즉 관련된 코드들을 함께 그룹화하려는 힘은 마이크로서비스의 중요한 개념이다. 마틴 파울러는 단일 책임 원칙에서 "같은 이유로 변경되는 것들은 한데 모으고, 서로 다른 이유로 변경되는 것들은 분리하라"고 강조했다.

 

마이크로서비스는 독립적인 서비스에 대해 동일한 접근 방식을 취한다. 주어진 기능과 관련 코드들이 명확히 제자리에 있도록 하면서 서비스 경계를 비즈니스 경계에 일치시킨다. 서비스의 명확한 경계를 지키면서 서비스가 지나치게 커지는 것에 대한 유혹을 회피한다.

 

서비스가 작아질수록 마이크로서비스 아키텍처의 혜택과 단점은 더 극대화되며, 서비스를 작게 만들면 만들수록 상호의존성에 의한 문제는 줄어든다. 더 많은 구성 요소를 추가해서 발생하는 복잡성을 다루는데 능숙해질수록 더 작은 서비스를 추구할 수 있다.

 

2) 자율성

마이크로서비스는 분리된 개체로 PaaS 상의 격리된 서비스이거나 운영체제 상의 프로세스가 될 수 있다. 여러 서비스를 동일 머신에 넣는 것은 피하려고 한다.

 

서비스 간의 분산도를 높이고 서비스 간에 밀접하게 연결되어 생기는 문제점을 줄이기 위해 서비스 사이의 모든 통신은 네트워크 호출을 통해 이루어진다. 이 서비스들은 서로 독집적으로 변경될 수 있어야 하고, consumer를 변경할 필요 없이 독립적으로 배포될 수 있어야 한다.

 

서비스는 애플리케이션 프로그래밍 인터페이스(Application Programming Interface)를 공개하며, 이 API를 통해 상호 협업하는 서비스들과 통신한다. 다양한 기술을 선택할 수 있도록 기술 중립적인 API를 선택할 수 있어야 한다. 즉, 구현 방식에 영향받지 않는 좋은 API의 중요성이 강조된다. 결합을 없애지 않고는 모든것은 소용이 없다. 서비스를 잘 분리하려면 서비스를 올바르게 모델링하고 API를 제대로 만들어야 한다.

 


마이크로 서비스가 제공하는 주요 혜택

1) 기술 이기종성

다수의 협업 서비스로 구성된 시스템에서는 각 서비스가 다른 기술을 사용하도록 결정할 수 있다. 최소한의 공통점만을 지닌 표준화된, 만능의 접근 방식을 선택하기보다 각 작업에 적합한 도구를 선택하게 해준다.

 

시스템 특정 부분의 성능을 높이려 할때, 요구되는 성능 수준을 만족하는데 유리한 다른 기술 스택을 고려해야 할 수도 있고 변환할 데이터를 어떻게 저장할지 결정해야 할 수도 있다.

 

모놀리식 애플리케이션에서 새로운 프로그래밍 언어, 데이터베이스 또는 프레임워크를 시도하면 그 변경은 시스템에 큰 영향을 미칠 것이다. 하지만 다양한 독립 서비스로 구성된 시스템에는 새로운 기술 분야를 시험해볼만한 곳이 많다. 여러 기술을 함께 사용하면 문제가 전혀 없을 수는 없다. 몇몇 기업은 프로그래밍 언어 선택에 일부 제한을 걸어둔다. 예를 들어 넷플릭스와 트위터는 대부분 자바 가상 머신(JVM)을 플랫폼으로 상요하는데, 이는 JVM의 신뢰성과 성능을 매우 잘 이해하고 있기 때문이다. 또한 대규모 시스템의 운영을 더 수비게 만드는 JVM용 라이브러리와 도구를 개발하고 있지만 자바 기반이 아닌 서비스와 클라이언트로는 어려움이 더 많다.

 

2) 회복성

'Resilience Engineering'의 핵심 개념은 'bulkhead(격벽)'이다. 한 시스템의 컴포넌트에 장애가 발생하더라도 그 장애가 전파되지 않는다면 해당 문제를 격리하고 나머지 시스템을 계속 작동시킬 수 있다. 서비스의 경계야말로 명확한 격벽인 셈이다. 모몰리식 서비스에서는 한서비스가 고장나면 모든 것이 작동을 멈춘다. 모놀리식 시스템은 장애 가능성을 낮추기 위해 수많은 머신 상에서 실행되어야 하지만, 마이크로서비스에서는 서비스의 전체 장애를 차단하고 기능을 적절히 저하(degrade)시키는 시스템을 구축할 수 있다.

 

하지만, 분산 시스템이 마주한 새로운 장애 요인들을 이해해야 한다. 네트워크도 머신처럼 장애가 발생할 수 있는 만큼 이것을 다루는 방법을 이해해야 하며, 소프트웨어의 최종 사용자에게 어떤 영향을 미치는지도 알아야 한다.

 

3) 확장성

하나의 큰 모놀리식 서비스에서는 항상 모든 것을 함께 확장해야 한다. 만약 전체 시스템에서 작은 한 부분만 성능이 떨어지는데, 해당 동작이 거대한 모놀리식 애플리케이션에 묶여 있다면 전체를 한 덩어리처럼 확장해야 한다. 그러나 만약 작은 서비스들로 구성되어 있다면 필요한 서비스만 확장하고, 나머지 서비스를 더 작고 낮은 사양의 하드웨어에서 실행할 수 있다.

 

2007년부터 2009년까지 모놀리식 레일즈 애플리케이션으로 작성된 길트 시스템은 유입되는 부하를 충분히 처리할 수 없었다. 하지만 시스템의 코어 부분을 불리하면서부터는 급등하는 트래픽을 더 잘 처리할 수 있게 되었다. 현재 450개 이상의 마이크로버시스가 분리된 많은 머신에서 동작중이다.

 

AWS에서 제공하는 것과 같은 주문형 프로비저닝 시스템을 도입하면 필요한 곳에 이 주문형 확장 기술을 적용할 수 있다.

 

4) 배포 용이성

거대한 모놀리식 애플리케이션에서는 한 줄만 수정하더라도 해당 변경을 릴리스하기 위해 전체 애플리케이션을 배포해야 한다. 마이크로서비스를 이용하면 하나의 서비스만 변경할 수 있고, 나머지 시스템과 독립적으로 배포할 수 있다. 코드를 더 신속히 배포할 수 있고, 문제가 발생하더라도 손쉽게 개별 서비스만 rollback 함으로써 해당 문제를 격리할 수 있다.

 

5) 조직 부합성

더 작은 팀이 더 작은 코드베이스로 일할때 더 생산적일 수 있다. 마이크로서비스를 이용하면 아키텍처를 조직 구조에 맞게 더 적절히 정렬할 수 있고, 최적의 팀 크기와 생산성을 위해 하나의 코드베이스에서 일하는 인원을 최소화할 수 있다.

 

6) 조합성

분산 시스템과 서비스 지향 아키텍처의 주요 장점 중 하나는 기능을 재사용할 기회가 많다는 것이다. 마이크로서비스를 통해 다양한 방법과 목적으로 우리가 제공하는 기능이 소비되도록 할 수 있다. 외부에서 직접 접근할 수 있는 시스템의 접합부(seam)을 마이크로서비스로 개방한다고 생각해보자. 환경이 바뀌면 다른 방식으로 구축할 수 있다. 모놀리식 애플리케이션은 외부에서 사용할 수 있는 하나의 큰 접합부를 가지고 있다. 그 하나의 접합부를 끊어내 외부에서 접근하기 더 유용한 것을 만들려면 전체 시스템을 변경해야 할것이다. 반면, 마이크로서비스는 재사용 및 재구성에 유용한 아키텍처이다.

 


서비스 지향 아키텍처란

SOA(service-oriented architecture)란 서비스의 최종능력 집합을 제공하는 여러 서비스가 서로 협업하도록 하는 설계 접근 방식이다. 여기서 서비스란 일반적으로 완전히 분리된 운영시스템의 프로세스를 의미한다. 서비스간 통신은 네트워크 호출로 이루어진다.

 

대규모 모놀로식 애플리케이션의 도전에 대한 대응으로 출현한 SOA는 소프트웨어의 재사용성 장려를 목표로 한다. SOA는 본래 매우 훌륭한 아이디어지만, 강력한 대안을 제시하는 것에는 실패했다고 보여진다.

 

SOA 문제 중에는 통신 프로토콜(예를 들면 SOAP), 벤더 미들웨어, 서비스 세분화(granularity)에 대한 지침 부족, 분리할 시스템 선정에 대한 잘못된 지침과 같은 것이 있다. SOA는 큰 시스템을 어떻게 작게 나눌 수 있는지 고민하는데 도움이 되지 않았다. 게다가 얼마나 커야 큰 것인지 설명하지 않고, 서비스가 지나치게 결합되지 않도록 하는 현실적이고 실질적인 방법을 충분히 다루지 않았다.

 

마이크로서비스는 SOA에 적합한 시스템과 아키텍처를 더 잘 이해할 수 있게 해준다. XP와 스크럼이 애자일 소프트웨어 개발의 특정 접근법으로 여겨지듯이, 마이크로서비스는 SOA에 대한 특정 접근법으로 보아야 한다.

 

마이크로서비스 기반 아키텍처의 수많은 이점은 마이크로서비스가 가진 세분화 특성과 문제 해결을 위한 더 많은 선택의 기회를 제공하는 데서 비롯되다.

 


마이크로서비스는 분산 시스템과 연관된 모든 종류의 복잡성을 내포하고 있으며, 분산 시스템을 적절히 다루는 방법을 익히더라도 여전히 어려운 것은 사실이다. 만약 모놀리식 시스템 관점에서 접근하고 있다면 지금까지 언급했던 혜택들을 얻기 위해서는 배포, 테스트, 모니터링을 훨씬 더 잘 다루어야 할 것이다. 또한 시스템을 확대하고 회복력을 유지하는 방법에 대해 다르게 생각해야 할 것이다. 분산 트랜잭션이나 CAP 정리와 같은 것들은 특히 골치 아픈 부분 이다.