티스토리 뷰

개요


# 참고

마이크로서비스 도입 이렇게 한다. (Monolith to Microservices) 

 

# 개요

MSA에 대해 이해하고, 모놀로식 아키텍처에서 마이크로서비스 아키텍처로 마이그레이션을 하며 고려해야할 지점에 대해 고민한다. 

 


3장. 모놀리스 분할

2장에서 마이크로서비스 아키텍처의 마이그레이션에 대해 살펴보았다. 새로운 아키텍처를 출시하고 올바른 방향으로 나아가기 위해 무엇을 해야 할지 알아보았다.

 

좋은 서비스란, 서비스가 작아질수록 왜 우리에게 더 유리한지도 살펴보았다. 이런 패턴을 따르지 않는 수많은 애플리케이션이 이미 존재할지도 모른다는 사실을 어떻게 해석해야 할까? 어떻게 하면 완전히 새로 고쳐 쓰는 작업에 차구하지 않고도 모놀리스 애플리케이션을 분해할 수 있을까?

 

3장에서는 다양한 마이그레이션 패턴과 팁을 살펴볼 것이다. 블랙박스 형태 소프트웨어, 레거시 시스템, 모놀리스 등에 적합한 패턴을 정리해본다. 

 

3-1. 모놀리스를 그대로 둘 것인가, 바꿀 거신가?

마이그레이션에서 고려할 첫 번째 사하은 기존 모놀리스를 변경할 계획이 있는지 여부 이다. 기존 시스템을 변경할 역량이 있다면, 다양한 패턴의 측면에서 유연성을 얻을 수 있다. 그러나 경우에 따라 엄격한 사황에 놓일 수도 있다. 예를 들어 기존 시스템이 소스 코드를 제공하지 않는 제조사가 만든 제품이거나 더 이상 보유하지 않는 기술로 작성된 것일지도 모른다. 현재 모놀리스가 너무나 견고해서 변경 비용이 많이 들 수도 있다. 하지만 손실을 줄이고자, 다시 시작하길 원하면 안된다.

 

나는 제공받은 라이브러리를 이용해서 계산 결과를 가져오는 업무를 담당하였다. 메모리 누수와 끔찍할 정도로 비효율적인 API설계는 문제를 해결하는데 엄청 오랜 시간이 걸린다. 하지만 이러한 꼼짝 못하는 상황에서도 여러 패터의 도움을 받을수 있다.

 

# 자랄 내기, 복사 또는 재구현?

새로운 마이크로서비스로 마이그레이션을 시작할 경우, 기존에 있는 코드를 옮겨야 할까?, 아니면 기능을 다시 구현해야 할까?

 

기존 모놀리스 코드베이스를 충분히 리팩터링하면, 코드 자체를 이동할 때 상당한 시간을 절약할 수 있따. 여기서 핵심은 모놀리스에서 코드를 복사하기를 원하지만, 최소한 당장 모놀리스 자체에서 이 기능을 제거하지 않는 다는 점이다. 일정기간동안 모놀리스 기능을 그대로 두면, 더 많은 선택지를 제공받을 수 있기 때문이다. 또한 마이그레이션이 성공적으로 완료되고 나면, 모놀리스를 제거 하면 된다.

 

#모놀리스 리팩터링

마이크로서비스를 위해 모놀리스에서 가져온 기존 코드를 재사용하는 과정에서 가장 큰 장벽은 기존 코드베이스가 전통적으로 비즈니스 도메인 개념(DDD)를 중심으로 구성되지 않았다는 문제이다. 이는 특히 새로운 시스템으로 비즈니스 도메인 기능을 이동하려 할 때 난관이 될 수 있다. 기존 코드베이스가 해당 분류와 일치하지 않아, 이동시키려는 코드를 찾으려는 시도조차 난관에 빠질수 있다.

 

이 책에서는 대안으로 봉합이라는 개념을 소개한다. 즉, 기존 동작 방식을 수정하지 않고서도 코드 변경이 가능한 장소를 정의한다. 특히 이 개념은 경계 컨텍스트와 매우 잘 맞아떨어진다. 도메인 주도 설계 개념을 직접적으로 설명하지 않을지라도, DDD를 활용해 코드를 조직화 할 수 있을 것이다.

 

# 모듈식 모놀리스

기존 코드베이스를 이해하기 시작했다면, 새로운 식별된 봉합을 가져와서 모놀리스를 모듈식 모놀리스로 만들기 위해 별도 모듈로 추출하는 단계를 고려하자. 배포 유닛은 하나뿐이지만, 배포된 유닛은 정적으로 링크된 여러 개의 모듈로 구성되어 있다. 이 모듈의 정확한 특성은 기반 기술 스택에 따라 다르며, 자바의 경우 모듈식 모놀리스는 여러 JAR 파일로 구성될 수 있다. 

 

모듈식 모놀리스는 독집적으로 개발 가능한 모듈로 모놀리스를 분해하면 마이크로서비스 아키텍처의 많은 문제를 극복하면서 다양한 이점을 얻을 수 있으며, 많은 조직에 최고의 해법이 될 수도 있다. 

 

# 잠재적인 재작성

나는 대체로 기능을 무작정 재구현하는 방법으로 문제를 풀기보다는 항상 먼저 기존 코드베이스를 살리려고 노력한다. 기존 코드 수정만으로 충분한 성과를 거두기에 애당초 마이크로서비스가 필요하지 않다는 사실을 깨닫게 된다. 그러나 실제로 마이크로서비스 전환에 앞서 모놀리스 리팩터링부터 먼저 진행하는 팀은 드물다. 그러나 기능을 재구현하기 시작하는 경우, 완전히 새로 고쳐 쓰는 빅뱅에 수반된 문제를 반복하는 위험에 처할 수 있다. 핵심은 한 번에 작은 기능만 재작성하고, 재작성된 기능을 고객에게 정기적으로 출시하면 많은 장점을 얻을 수 있다.

 

 

3-2. 패턴 : 교살자 무화과 어플리케이션

교살자 무화과는 숙주 나무의 위쪽 가지에 씨앗을 뿌리는 무화과 나무를 보고 영감을 얻었다. 숙주 나무에 씨를 뿌린 무화과는 뿌리를 내리기 위해 땅으로 뻗으며 점차 숙주 나무를 감싸게 된다. 처음에는 숙주 나무를 지지대로 사용하다, 마지막 단계에 이르면 숙주나무는 썩어 죽고, 무화과 나무만 남게 된다.

 

소프트웨어 맥락에서 보면, 기존 시스템이 새로운 시스템을 지원하고, 새로운 시스템이 기존 시스템을 감싸는 형태로 병행된다. 기존 시스템과 새로운 시스템이 공존할  수 있으므로, 새로운 시스템은 성장할 시간을 얻고, 잠재적으로 기존 시스템을 완전히 대체할 수 있게 된다.

 

이 패턴의 주요 장점은 새로운 시스템으로 점진적인 마이그레이션을 허용한다는 우리의 목표를 뒷받침한다. 또한 심지어 마이그레이션이 중간에 중단된다면 마이그레이션을 일시 중지하거나 심지어 중단할 능력도 우리에게 제공한다. 즉, 점진적으로 수행해온 각 단계를 쉽게 되돌릴 수 있도록 보장함으로써 점지넉 단계별로 발생할지도 모르는 위험을 줄여야 한다. 

 

# 작동 원리

교살자 무화과 패턴은 일반적으로 하나의 모놀리스 시스템에서 다른 모놀리스 시스템으로 마이그레이션하는 과정에 사용되어왔지만, 여기서는 모놀리스에서 마이크로서비스로 마이그레이션하는 과정을 살펴볼 것이다.

 

교살자 무화과 패턴은 3가지 단계에 의존한다.

1. 이동할 자산 파악 : 마이그레이션 하기 원하는 기존 시스템의 대상을 식별

2. 자산 이동 : 기능을 새로운 마이그로 서비스에 구현

3. 호출 리다이렉션 : 모놀리스에 대한 호출을 신규 마이크로서비스에 대한 호출로 전환하게끔 라우팅

마이크로서비스에 구현된 기능은 이동된 기능으로 리다이렉션되기 전까지, 운영 환경에 배포된 경우라 할지라도 새기능이 작동하지 않는다는 사실에 주목해야 한다. 

 

교살자 애플리케이션 접근 방식의 핵심은 새로운 기능을 신규 시스템으로 점진적으로 마이그레이션할 수 있을 뿐만 아니라 필요한 경우 변경사항을 매우 쉽게 되돌릴 수 있다는 점이다. 우리는모두 실수를 하다는 사실을 기억해야 한다. 우리는 실수를 하더라도 복귀비용이 저렴할 뿐만 아니라 신속하게 실수를 해결할 수 있는 기술이 필요하다.

 

 

# 적용대상

교살자 무화과 패턴을 사요하면 기존 시스템을 건드리거나 변경하지 않고도 새로운 서비스 아키텍처로 기능을 이동할 수 있다. 이는 경합을 줄이는데 도움이 되므로, 기존 모놀리스 자체를 대상으로 작업할 경우에 유리하다. 또한 모놀리스가 외부에서 만들어진 서드파티 소프트웨어이거나 SaaS서비스의 경우인 블랙박스 시스템일 때도 매우 유용하다.

 

소규모로 시작하고 싶다면, 더 얕은 추출을 고려해야 할지도 모른다. 여기서 모놀리스 내부에 남아 있는 다른 기능을 사용함에도 불구하고, 급여 기능을 추출하고 있다. 또한 사용자 통지 기능을 재구현하는 대신, 사용자 통지 기능을 모놀리스에서 외부에 공객하는 방법으로 새로운 마이크로서비스에 노출시킨다. 그러나 교살자가 작동하려면, 인바운드 호출을 이동하려는 대상 자산에 대해 관심있는 기능으로 명확하게 매핑할 수 있어야 한다. 우리는 고객에게 사용자 통지를 보내는 기능을 새로운 서비스로 이동하고 싶다. 그러나 기존 모놀리스에 대한 인바운드 호출의 결과로 통지가 발생한다. 따라서 시스템 외부에서일어나는 호출을 명확하게 리다이렉션 할 수 없다.

 

또한 기존 시스템에 대한 인바운드 호출의 성격도 고려해야 할 것이다. HTTP 같은 프로토콜은 리다이렉션에 상당히 적합하다. HTTP 자체에는 투명한 리다이렉션 개념이 내장되어 있으며, 인바운드 요청의 특성을 명확하게 이해해서 방향을 변경하려면 프록시를 사용해야 한다. 이런 제약에도 불구하고, 교살자 무화과 애플리케이션은 매우 유용한 마이그레이션 기법임을 스스로가 끊임없이 입증해왔다. 가볍게 수행하는 능력과 점진적인 변화를 다루는 손쉬운 접근 바법을 고려해본건대, 시스템 마이그레이션 방법을 찾으려 할 때 내게 최선의 선택지는 교살자 무화과 패턴이다.

 

# HTTP 리버스 프록시

HTTP에는 몇 가지 흥미로운 기능이 있다. 그중 하나로, 호출하는 시스템에 투명하게 보이는 방법으로서, 호출을 가로채고 리다이렉션하기가 매우 쉽다는 점을 들 수 있다. 이는 HTTP 인터페이스를 제공하는 기존 모놀리스를 교살자 무화과 패턴을 사용해 마이그레이션하기가 적합하다는 사실을 의미한다. 

 

1단계 : 프록시 삽입

재사용 가능한 적절한 HTTP 프록시가 아직 없는 경우에는 HTTP 프록시를 배치하는 방식을 권장한다. 1단계 프록시는 모든 호출을 변경 없이 통과 시키기만 하면 된다. 적절한 프록시와 네트우어크를 사용하면, 대기 시간에 최소의 영향만 미칠 것이다. 하지만 그렇지 않다고 판명된 경우에는 더 진행하기 전에 작업을 중지하고 문제를 조사할 수도 있다.

 

2단계 : 기능 마이그레이션

새로운 마이크로서비스 추출을 시작할 수 있다. 2단계는 여러 단계로 분해할 수 있다. 먼저, 아무 기능도 구현하지 않고 기본 서비스를 준비하고 실행하자. 여러분이 만든 서비스는 일치하는 기능에 대한 호출을 받아들여야 하지만, 2단계에서는 501오류만 반환할 수 있다. 나라면 2단계에서도 이 서비스를 운영환경에 배포할 것이다. 이렇게 하면 운영 배포 프로세스에 익숙해질 수 있고, 현장에서 서비스를 테스트할 수 있다.

 

3단계 : 호출 리디렉션

모든 기능이 마이크로서비스로 이동을 완료하고 나서야 호출을 리다이렉션하기 위해 프록시를 재구성한다. 어떤 이유로든 이 작업이 실패하면 리다이렉션을 되돌릴 수 있다. 대다수의 프록시의 경우, 리다이렉션을 되돌리는 작업은 매우 빠르고 쉬운과정이므로 신속한 복원이 가능하다.

 

 

# 점진적인 배포

점진적 배포 기법을 활용하면 일련의 작은 단계를 통해 아키텍처를 변경할 수 있으며, 각 단계는 시스템의 다른 작업과 함께 수행할 수 있다. 전환하는 작업이 방대하다는 생각이 든다면, 더 작은 기능으로 분할할 수 있따. 예를 들어 급여 기능의 일부만 마이그레이션하고 호출을 적절히 변경해, 모놀리스와 미이크로서비스의 양쪽 기능이 동일한 데이터 집합에 접근해야 한다면 공유 데이터베이스가 필ㅇ요하며, 이로 인해 다양한 문제가 발생할 가능성이 높다. 엄청나게 많은 시스템을 최종적으로 하나로 합치는 빅뱅도, 라인을 멈추는 재플랫포뫄도 필요하지 않다. 점진적으로 배포함으로써 새로운 기능을 배포하는 동시에 아키텍처를 점진적으로 변경하는 작업을 수행하자!

 

# 서비스 메시

스퀘어(기업)에서는 이 문제를 해결하기 위해 하이브리드 접근법을 채택했다. 스퀘어에서는 서비스 간 통신 목적으로 직접 제작한 RPC 메커니즘에서 벗어나기 위해, 매우 폭넓은 생태계를 토대로 풍부한 지원이 가능한 오픈소스 RPC 프레임워크인 gRPC를 채택하기로 결정했다. 고충을 최소로 경감시키기 위해, 각 서비스에 필요한 변경량을 줄이고자 서비스 메시를 선택하게 되었다.

 

서비스 메시를 사용하면, 각 서비스 인스턴스는 독자적인 전용 로컬 프록시를 통해 다른 서비스 인스턴스와 통신한다. 각 프록시 인스턴스는 파트너가 되는 서비스 인스턴스에 맞춰 특별히 구성할 수 있다. 또한 제어 평면을 사용해 이런 프록시에 대한 주앙화된 제어와 모니터링을 제공하 수도 있다. 중앙 프록시 계층이 없기 때문에, '똑똑한' 파이프를 유지하는 과정에서 부딪히는 위험을 피할 수 있다. 따라서 각 서비스는 필요한 경우 서비스 간의 독자적인 파이프를 효과적으로 소유할 수 있다.

 

# 메시지 가로채기

지금까지 동기식 호출을 가로채는 방법을 살펴봤지만, 모놀리스가 다른 형태의 프로토콜, 즉 메시지 브로커를 통해 메시지를 수신하는 경우에는 어떻게 될까? 기본 패턴은 동일하다. 호출을 가로채 새로운 마이크로서비스로 리다이렉션하는 수단이 필요하다. 주요 차이점은 프로토콜 자체의 특성이다.

 

# 콘텐츠 기반 라우팅

모놀리스는 수 많은 메시지를 수신하는데, 그중 일부를 가로채야 한다. 간단한 접근 방법은 다운스트림 모놀리스를 위해 의도된 모든 메시지를 가로채고 해당 메시지를 필터링해 적절한 장소로 모내는 것이다. 이는 기본적으로 많이 사용하는 콘텐트 기반 라우터 패턴의 구현이다. 

 

이 기법을 사용하면 모놀리스를 건드리지 않고 요청 경로에 다른 대기열을 배치할 수 있지만, 대기 시간이 늘어날 수 있으며 곤리해야 할 항목도 추가로 생긴다. 또 다른 문제는 메시징 계층에 '똑똑한 기능'을 몇 개 배치해야 하냐는 질문이다. 서비스 간 네트워크에서 똑똑한 기능을 너무 많이 사용하는 시스템으로 인해 발생되는 문제를 설명한 바있다. 이런 경우에는 시스템을 이해하기 어렵고 변경하기도 더 어려워 진다. 이 책에서 계속 언급한 "똑똑한 종단점, 멍청한 파이프"라는 격언을 여러분이 반드시 받아들이길 권고한다. 콘텐트 기반 라우터는 시스템 간에 호출이 라우팅되는 측면에 복잡성을 추가해 똑똑한 파이프로 인해 복잡한 구조가 될 수 있다.

 

# 선택적 소비

위에서의 문제에 대한 대안이라면, 모놀리스를 변경해서 새로운 서비스가 수신해야 할 메시지를 무시하게 만드는 방법이 있다. 새로운 서비스와 모놀리스가 동일 대기열을 공유하며 지역적으로 일종의 패턴 일치 프로세스를 사용해 관심있는 메시지를 수신하기 위해 대기한다. 이런 종류의 필터링은 메시지 기반 시스템에서 매우 일반적인 요구사항이다.

 

이와 같은 필터링 접근 방식은 추가 대기열을 만들 필요성을 줄여주지만 몇 가지 문제가 있다.

1. 우선 메시징 기술은 단일 대기열 구독을 공유하도록 허용할 수도, 허용하지 않을 수도 있다. 

2. 호출을 리다이렉션하고 싶다면 두가지 변경사항을 조정해야 한다. 모놀리스가 새로운 서비스를 위한 호출을 하지 못하게 막아야 하고, 새로운 서비스가 이 호출을 받아들이게 만들어야 한다.

동일한 대기열에 대해 더 많은 유형의 컨슈머가 있고 필터링 규칙이 복잡해질수록, 문제가 많이 발생한다. 이런 이유로 적은 수의 컨슈머 또는 간단한 필터링 규칙 집합마능로 선택적 소비를 사용하는 방식을 고려해야 할 것이다. 잠재적인 단점, 특히 '똑똑한 파이프' 문제에 빠지는 단점을 인식해야 하지만, 콘텐츠 기반의 라우팅 접근 방식은 컨슈머 유형의 수가 증가함에 따라 더 타당할 것이다.

 

# 교살자 무화과 패턴의 다른 예

교살자 무화과 패턴은 기존 시스템을 점진적으로 재구축하려는 모든 상황에서 매우 유용하며, 마이크로서비스 아키텍처를 구현하는 팀에만 사용이 국한되지는 않는다.

 

 

 

3-3. 기능을 마이그레이션하는 동안 동작 방식 변경하기 

마이크로서비스 아키텍처로 점진적으로 마이그레이션하기 위해 사용 가느한 패턴을 특별히 선별해서 소개한다. 교살자 무화과 패턴을 사용하는 시나리오를 상상해보자. 고객에게 새로운 급여 서비스를 출시하고 문제가 발견되면 급여 기능에 대한 호출을 기존 시스템으로 다시 저노한할 수 있었다. 이는 모놀리스와 마이크로서비스가 기능적으로 동등한 경우에는 잘 작동하지만, 마이그레이션의 일부로 급여기는이 작동하는 방식을 변경하는 경우에는 어떻게 될까?

 

급여 마이크로서비스의 동작 방식에 몇 가지 버그 수정이 적용되었지만 모놀리스의 동등한 기능으로 역이식 되지 않는 경우, 복원으로 인해 해당 버그가 시스템에 다시 나타날 수도 있다. 급여 마이크로서비스에 새로운 기능을 추가하면 문제가 더 커질 수 있는데, 보원하고 나면 고객이 사용하는 기능은 사라질 것이다.

 

이 문제를 해결할 간단한 묘책은 없다. 마이그레이션이 완료되기 전에 기능 변경을 허용하면 복원을 더 어렵게 마든다는 사실을 인정해야 한다. 마이그레이션이 완료될 때까지 변경을 허용하지 않는 편이 훨씬 더 수월하다. 마이그레이션에 시간이 오래 걸릴수록 시스템에서 '기능 동결'을 강제하는 것이 더 어려워진다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함