Strategy 3 – Extract Services
(세번째 전략 : 서비스 추출)

세번째 리팩토링 전략은 monolith 내 기존 모듈들을 독립형 마이크로서비스로 변환하는 것이다. 모듈을 추출하여 서비스로 변환할 때마다, monolith는 작아진다. 일단 충분히 모듈로 변환하고 나면, monolith는 문제가 되지 않을 것이다. Monolith는 완전히 사라지거나 또다른 서비스가 될 만큼 충분히 작아지게 된다.

Prioritizing Which Modules to Convert into Services
(서비스 변환 대상 모듈 우선 순위화)

크고 복잡한 monolithic 어플리케이션은 수십, 수백개의 모듈들로 이루어져 있다. 그리고 그 모듈들은 모두 추출 대상이다. 우선 변환할 모듈을 알아내는 것은 도전적인 일이다. 좋은 접근 방법은 쉽게 추출할 수 있는 몇 가지 모듈로 시작하는 것이다. 이것은 일반적으로 마이크로서비스와 특히 추출 프로세스에 대한 경험을 제공해 준다. 그 이후에, 가장 큰 이익을 주는 모듈들을 추출해야 한다.

모듈을 서비스로 변환하는 것은 일반적으로 시간이 많이 걸린다. 여러분은 얻을 수 있는 이익을 기반으로 모듈에 대한 순위를 매기기를 원한다. 일반적으로는 자주 변경되는 모듈을 추출하는 것이 유익하다. 한번 모듈을 서비스로 변환하고 나면, monolith와는 독립적으로 개발하고 배포할 수 있기 때문에 개발을 가속화하게 될 것이다.

Monolith의 나머지와 크게 다른 리소스 요구사항을 가지는 모듈을 추출하는 것도 유익하다. 예를 들면, 인메모리 데이터베이스를 가진 모듈을 서비스로 변환하고, 대용량 메모리를 가진 호스트에 배포할 수 있다. 이와 유사하게, 계산하기에는 비싼 알고리즘을 구현하는 모듈을 추출하는 것은 많은 CPU를 가진 호스트에 배포할 수 있기 때문에 가치가 있다. 특정 리소스 요구사항을 가진 모듈을 서비스로 변환함으로써, 어플리케이션을 훨씬 쉽게 확장할 수 있다.

어느 모듈을 추출할지를 알고 나면, 이미 존재하는 대략적인 경계(이음새로 알려진)를 찾는 것이 유용하다. 모듈을 서비스로 더 쉽고 값싸게 한다. 그러한 경계의 한 예로는 비동기 메시지를 통해 나머지 어플리케이션과 커뮤니케이션하는 모듈을 들 수 있다. 상대적으로 싸고 쉽게 모듈을 마이크로서비스로 변환할 수 있다.

How to Extract a Module
(어떻게 모듈을 추출하는가)

모듈을 추출하는 첫번째 단계는 모듈과 monolith 사이에 대략적인 인터페이스를 정의하는 것이다. Monolith는 서비스가 소유한 데이터를 필요로 하고, 그 반대의 경우도 마찬가지이기 때문에 대부분 양방향 API일 것이다. 모듈과 나머지 어플리케이션들 사이의 얽혀 있는 의존성과 잘 정리되어 있는 상호작용 패턴 때문에 양방향 API를 구현하는 것은 종종 어려운 일이다. Domain Model 패턴을 사용하여 구현된 비즈니스 로직은 도메인 모델 클래스 간의 수많은 연관성 때문에 리팩토링하기에 특히 어렵다. 이러한 의존성을 깨기 위하여 종종 중요한 코드를 변경해야만 할 필요가 있다. 다음 다이어그램은 리팩토링에 대해서 보여준다.

대략적인 인터페이스를 일단 구현하고 나면, 모듈을 독립적인 서비스로 변환할 수 있다. 이렇게 하기 위해서, monolith와 서비스가 Inter-Process Communication(IPC : 프로세스간 통신) 메커니즘을 사용하는 API를 통해 서로 통신할 수 있는 코드를 작성해야만 한다. 다음 다이어그램은 리팩토링 전, 도중, 후의 아키텍처를 보여준다.


사용자 삽입 이미지



이 예제에서, 모듈 Z는 추출할 후보 모듈이다. 그 구성요소들은 모듈 X에서 사용되고, 모듈 Y를 사용한다. (즉, X 모듈에서는 Z 모듈의 구성요소를 사용하고, Z 모듈의 구성요소들은 Y 모듈을 사용한다.) 첫번째 리팩토링 단계는 대략적인 API 쌍을 정의하는 것이다. 첫번째 인터페이스는 모듈 Z를 호출하기 위해서 모듈 X에서 사용하는 인바운드 인터페이스이다. 두번째는 모듈 Y를 호출하기 위해 모듈 Z에서 사용하는 아웃바운드 인터페이스이다. (인바운드 : 모듈 Z의 입장에서 요청이 들어오는 방향, 아웃바운드 : 모듈 Z의 입장에서 요청이 나가는 방향)

리팩토링의 두번째 단계는 모듈을 독립적인 서비스로 변환하는 것이다. 인바운드, 아웃바운드 인터페이스는 IPC 메커니즘을 사용하는 코드로 구현된다. 서비스 검색과 같은 Cross-Cutting Concern(AOP에서 여러 비즈니스 로직에 공통으로 필요하여 별도 모듈로 쉽게 분리할 수 없는 요구사항. 예:보안, 로깅, 트랜잭션, 등)을 다루는 Microservice Chassis framework와 모듈 Z를 결합하여 서비스를 빌드할 필요가 있다.

일단 모듈을 추출하고 나면, monolith와 다른 서비스들과는 별도로 개발, 배포, 확장하 ㄹ수 있는 또다른 서비스를 가지게 된다. 서비스를 처음부터 재작성하게 될 수도 있다. 이 경우에는, 서비스와 monolith를 통합하는 API 코드가 2개의 도메인 모델 사이를 변환하는 Anti-Corruption Layer(반부패 계층)이 된다. 서비스를 추출하는 경우마다 마이크로서비스의 방향으로 또 한 걸음 나아가는 것이다. 시간이 지날수록 monolith는 작아지고, 마이크로서비스는 늘어날 것이다.
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/784


Strategy 2 – Split Frontend and Backend
(두번째 전략 - Frontend와 Backend의 분리)

Monilithic Application을 축소시키는 전략은 비즈니스 로직과 데이터 액세스 레이어에서 프리젠테이션 레이어를 분리하는 것이다.

일반적으로 엔터프라이즈 어플리케이션은 최소한 3가지 다른 유형의 컴포넌트들로 이루어져 있다.

프리젠테이션 레이어 - HTTP 요청을 처리하고, (REST) API나 HTML 기반 Web UI를 구현하는 구성 요소. 정교한 사용자 인터페이스를 가지고 있는 어플리케이션에서 프리젠테이션 계층은 종종 상당한 코드로 구성되어 있다.
비즈니스 레이어 - 어플리케이션의 핵심 영역이며, 비즈니스 규칙을 구현하는 구성 요소.
데이터 액세스 레이어 - 데이터베이스나 메시지 브로커와 같은 인프라 구성 요소들에 액세스하는 구성 요소

일반적으로 프리젠테이션 로직 영역과 비즈니스, 데이터 액세스 로직 사이는 분명하게 분리되어 있다. 비즈니스 계층은 비즈니스 로직 컴포넌트들을 캡슐화하는 하나 이상의 facade(진입점 역할을 하는 인터페이스)로 이루어진 대단위 API를 가지고 있다. 이 API는 monolith를 2개의 더 작은 어플리케이션으로 나눌 수 있는 자연적인 솔기이다. 한 개의 어플리케이션은 프리젠테이션 레이어를 가지고 있다. 다른 어플리케이션은 비즈니스와 데이터 액세스 로직이 포함되어 있다. 이렇게 분리한 후, 프리젠테이션 로직 어플리케이션은 비즈니스 로직 어플리케이션을 원격으로 호출하게 된다. 다음 다이어그램은 리팩토링 전후의 아키텍처를 보여주고 있다.

사용자 삽입 이미지



이 방법으로 monolith를 분할하는 것은 2가지 주요 장점이 있다. 서로간에 독립적으로 2개의 어플리케이션을 개발, 배포, 확장할 수 있다. 특히, 프리젠테이션 레이어 개발자는 사용자 인터페이스를 빠르게 반복하여 개발할 수 있다. 그리고 예를 들면, 쉽게 A|B 테스트를 수행할 수 있다. 이 접근방법의 또다른 장점은 개발한 마이크로서비스에서 호출할 수 있는 원격 API를 제공한다는 것이다.

그러나, 이 전략은 단지 부분적인 해결책일 뿐이다. 한 두개의 관리할 수 없는 monolith 어플리케이션에 대한 해결책일 공산이 크다. 나머지 monolith를 제거하기 위해서는 3번째 전략을 사용하는 것이 필요하다.
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/783


이번 기사는 Microservice로 Application을 작성하는데 있어서 7번째이자, 마지막 글이다. 첫번째 글에서는 Microservice Architecture 패턴에 대해서 소개하고, Microservice를 사용하는 장단점에 대해서 논의했다. 다음 글에서는 API Gateway 사용, Inter-process communication, 서비스 검색, Event-Driven 데이터 관리, Microservice 배포 등의 다양한 측면에 대해서 논의했다. 이번 글에서는 monolithic application을 microservice로 마이그레이션(전환)하는 전략에 대해서 살펴 보려고 한다.

이 시리즈 기사들을 통해서 microservice architecture와 장단점, 언제 사용하는지에 대해 이해할 수 있도록 돕고자 한다. Microservice Architecture가 여러분의 조직에 적합할 수도 있다.

그러나, 크고 복잡한 monolithic application을 작성하는 정말 좋은 기회가 있다. Application 개발과 배포에 대한 일상적인 경험은 느리고 고통스럽다. Microservice는 머나먼 너바나(열반, 해탈)처럼 보인다. 다행스럽게도 Monolithic Hell에서 벗어나는데 사용할 수 있는 전략이 있다. 이 기사에서는, Monolithic Application을 Microservice로 점진적으로 리팩토링하는 방법에 대해서 설명할 것이다.

Overview of Refactoring to Microservices
(Microservice로 리팩토링하기 개요)

Monolithic Application을 Microservice로 변환하는 과정은 Application 현대화의 한 형태이다. 개발자들이 수십년동안 해왔던 일이기도 하다. 결과적으로, Application이 Microservice로 리팩토링할 때, 재사용할 수 있는 몇 가지 아이디어들이 있다.

사용하지 않는 전략 중 한가지는 "Big Bang" 재개발이다. Big Bang은 아무런 사전 준비 없이 새로운 Microservice 기반 Application을 개발하는데 모든 역량을 집중해야 한다. 호소력 있는 것처럼 들리지만, 극도로 위험하고 실패로 끝나기 쉽다. Martin Fowler가 리포트에서 말하는 것처럼, "Big Bang 재개발을 보장하는 유일한 방법은 Big Bang 뿐이다."

Big Bang 재개발 대신에, Monolithic Application을 점진적으로 리팩토링해야 한다. 점차적으로 Microservice를 구성하는 신규 Application을 개발하여 monolithic application과 함께 실행한다. 시간이 지나면, monolithic application으로 구현된 기능의 양은 완전히 사라지거나 또다른 microservice가 될 때까지 줄어든다. 이 전략은 고속도로에서 시속 70마일로 운전하는 도중에 자동차 정비하는 것과 유사한 도전이지만, Big Bang 재개발보다 훨씬 덜 위험하다.

Martin Fowler는 이러한 Application 현대화 전략을 Strangler Application(교착 상태 응용 프로그램)이라고 한다. 그 이름은 열대 우림에서 발견되는 strangler vine (a.k.a strangler fig - 알려진 것처럼, 다른 나무에 기생하여 그 나무를 감고 올라가 말려 죽이는 나무의 한 종류. 직역하면, 교살 포도 나무)에서 비롯되었다. 가끔은 나무가 죽어서 포도 나무 모양을 남긴다. Application 현대화도 같은 패턴을 따른다. Legacy Application 주위에  Microservice로 구성된 새로운 Application을 구축하고, 결국 Legacy Application은 사라질 것이다.

사용자 삽입 이미지


이제, 다른 전략을 살펴보자.

Strategy 1 – Stop Digging
(첫번째 전략 - 채굴 금지)

홀의 법칙(Law of Hole)은 구멍에 있을 때마다 채굴하는 것을 멈춰야 한다는 것을 알려주고 있다. 이것은 monolithic application을 관리할 수 없을 때, 따라야할 훌륭한 조언이다. 다른 말로 하면, monolithic application을 더 크게 만드는 것을 멈춰야만 한다. 이것은 신규 기능을 구현할 때, monolithic에 코드를 추가하지 않아야 한다는 것을 의미한다. 대신에 이 전략의 커다란 아이디어는 독립형 microservice에 새로운 코드를 넣는 것이다. 다음 다이어그램은 이러한 접근법을 적용한 시스템 아키텍처를 보여준다.

사용자 삽입 이미지


새로운 서비스와 legacy monolith 뿐만 아니라, 2가지 구성 요소들이 있다. 첫번째는 HTTP 요청을 처리하는 Request Router이다. 앞서 기사에서 설명한 API Gateway와 유사하다. Router는 새로운 기능에 대한 요청을 새로운 서비스로 보낸다. Legacy 요청은 monolith로 전송한다.

다른 구성 요소는 Glue Code이다. "Glue Code"는 Monolith에 통합되어 있다. 서비스는 격리되어 있지 않고, 종종 Monolith에서 보유하고 있는 데이터에 접근해야 한다. Monolith나 서비스 혹은 양쪽 모두에 있는 "Glue Code"가 데이터 통합을 담당한다. 서비스는 Monolith에 있는 데이터를 읽거나 쓰는데 Glue Code를 사용한다.

서비스가 monolith 데이터에 접근하는데 3가지 전략이 있다.

1. Monolith에서 제공하는 원격 API 호출
2. Monolith의 데이터베이스에 직접 접근
3. Monolith의 데이터베이스와 동기화된 자체 복사본 데이터 유지

Glue Code는 때때로 Anti-corruption Layer(반부패 계층)로 불리기도 한다. 왜냐하면 본래의 도메인 모델을 가진 서비스가 Legacy Monolith 도메인 모델이 갖는 개념에 의해 오염되는 것을 Glue Code가 방지하기 때문이다. Glue Code는 2가지 다른 모델들 사이에 변환된다. Anti-corruption Layer라는 용어는 읽어야만 하는 책, 이후 백서로 개량된 Eric Evans의 Domain Driven Design에서 처음 나타났다. Anti-corruption Layer를 개발하는 것은 사소한 일이 될 수도 있다. 그러나, monolithic hell에서 벗어나기 원한다면, 하나를 창조하는 것이 필수적이다.

가벼운 서비스로써 새로운 기능을 구현하는 것은 몇 가지 장점이 있다. Monolith가 더 관리할 수 없게 되는 것을 방지한다. 서비스를 monolith와 독립적으로 개발, 배포, 확장할 수 있다. 신규로 만드는 서비스마다 Micorservice Architecture의 장점을 경험할 수 있다.

그러나, 이러한 접근 방법이 monolith의 모든 문제점을 해결하는 것은 아니다. 이러한 문제들을 해결하려면 monolith를 분해할 필요가 있다. 그렇게 하기 위한 전략을 살펴 보자.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/782