편집자 – 총 7부로 구성된 이 연재 기사가 이제 완결되었습니다:
- 마이크로서비스 소개
- 마이크로서비스 구축: API 게이트웨이 사용
- 마이크로서비스 구축: 마이크로서비스 아키텍처의 프로세스 간 통신
- 마이크로서비스 아키텍처의 서비스 디스커버리
- 마이크로서비스를 위한 이벤트 기반 데이터 관리
- 마이크로서비스 배포 전략 선택
- 모놀리스를 마이크로서비스로 리팩터링하기(이 글)
전체 기사 모음과 NGINX Plus를 사용한 마이크로서비스 구현 정보를 전자책으로 다운로드할 수도 있습니다. 전자책 제목은 마이크로서비스: 설계부터 배포까지입니다. 또한 마이크로서비스 참조 아키텍처 시리즈와 마이크로서비스 솔루션 페이지도 확인해 보세요.
이 글은 마이크로서비스를 활용한 애플리케이션 구축에 관한 제 시리즈의 일곱 번째이자 마지막 글입니다. 첫 번째 글에서는 마이크로서비스 아키텍처 패턴을 소개하고 마이크로서비스 사용의 장단점을 살펴봅니다. 이어지는 글에서는 마이크로서비스 아키텍처의 다양한 측면인 API 게이트웨이 사용<.htmla>, 프로세스 간 통신, 서비스 디스커버리, 이벤트 기반 데이터 관리, 그리고 마이크로서비스 배포를 다룹니다. 이 글에서는 모놀리식 애플리케이션을 마이크로서비스로 마이그레이션하기 위한 전략을 살펴봅니다.
이 연재를 통해 마이크로서비스 아키텍처와 그 장단점, 그리고 언제 사용해야 하는지를 충분히 이해하셨기를 바랍니다. 어쩌면 마이크로서비스 아키텍처가 여러분의 조직에 적합할 수도 있습니다.
하지만 여러분은 규모가 크고 복잡한 모놀리식 애플리케이션을 다루고 있을 가능성이 상당히 높습니다. 매일 애플리케이션을 개발하고 배포하는 과정은 느리고 고통스럽습니다. 마이크로서비스는 멀게만 느껴지는 이상향처럼 보입니다. 다행히도 모놀리식 지옥에서 벗어나는 데 활용할 수 있는 전략이 있습니다. 이 글에서는 모놀리식 애플리케이션을 여러 마이크로서비스로 점진적으로 리팩터링하는 방법을 설명합니다.
마이크로서비스로 리팩터링하기 개요
모놀리식 애플리케이션을 마이크로서비스로 전환하는 과정은 애플리케이션 현대화의 한 형태입니다. 이는 개발자들이 수십 년 동안 해 온 작업입니다. 따라서 애플리케이션을 마이크로서비스로 리팩터링할 때 재활용할 수 있는 몇 가지 아이디어가 있습니다.
사용해서는 안 되는 전략 중 하나는 ‘빅뱅’ 방식의 재작성입니다. 이는 모든 개발 역량을 투입해 새로운 마이크로서비스 기반 애플리케이션을 처음부터 구축하는 방식입니다. 매력적으로 들릴 수 있지만 위험성이 매우 높으며 실패로 끝날 가능성이 큽니다. 마틴 파울러가 말한 것으로 알려졌듯이, “빅뱅 방식의 재작성이 보장하는 유일한 것은 빅뱅뿐입니다!”
빅뱅 방식으로 재작성하는 대신 모놀리식 애플리케이션을 점진적으로 리팩터링해야 합니다. 마이크로서비스로 구성된 새 애플리케이션을 단계적으로 구축하고 기존 모놀리식 애플리케이션과 함께 실행합니다. 시간이 지나면서 모놀리식 애플리케이션이 담당하는 기능은 점차 줄어들어 결국 완전히 사라지거나 하나의 마이크로서비스로 남게 됩니다. 이 전략은 시속 70마일로 고속도로를 달리면서 자동차를 정비하는 것과 같습니다. 쉽지는 않지만 빅뱅 방식의 재작성을 시도하는 것보다는 훨씬 위험이 적습니다.
Martin Fowler는 이 애플리케이션 현대화 전략을 교살자 애플리케이션이라고 부릅니다. 이 이름은 열대우림에서 발견되는 교살 덩굴(일명 교살 무화과)에서 유래했습니다. 교살 덩굴은 숲의 수관 위로 비치는 햇빛에 닿기 위해 나무를 감싸며 자랍니다. 때로는 나무가 죽고 나무 모양의 덩굴만 남기도 합니다. 애플리케이션 현대화도 이와 같은 패턴을 따릅니다. 레거시 애플리케이션 주위에 마이크로서비스로 구성된 새로운 애플리케이션을 구축하면, 결국 레거시 애플리케이션은 사라지게 됩니다.

이를 위한 다양한 전략을 살펴보겠습니다.
전략 1 – 더 이상 파고들지 않기
‘구덩이의 법칙’에 따르면 구덩이에 빠졌을 때는 더 이상 땅을 파지 말아야 합니다. 이는 모놀리식 애플리케이션을 감당하기 어려워졌을 때 따르기 좋은 조언입니다. 다시 말해, 모놀리스를 더 크게 만들지 말아야 합니다. 즉, 새로운 기능을 구현할 때 모놀리스에 코드를 더 추가해서는 안 됩니다. 대신 이 전략의 핵심은 새 코드를 독립형 마이크로서비스에 넣는 것입니다. 다음 다이어그램은 이 접근 방식을 적용한 후의 시스템 아키텍처를 보여 줍니다.

새 서비스와 레거시 모놀리스 외에도 두 가지 구성 요소가 더 있습니다. 첫 번째는 들어오는 (HTTP) 요청을 처리하는 요청 라우터입니다. 이는 이전 글<.htmla>에서 설명한 API 게이트웨이와 유사합니다. 라우터는 새로운 기능에 해당하는 요청을 새 서비스로 보내고, 레거시 요청은 모놀리스로 전달합니다.
다른 구성 요소는 서비스를 모놀리스와 통합하는 글루 코드입니다. 서비스는 단독으로 존재하는 경우가 드물며, 모놀리스가 소유한 데이터에 액세스해야 하는 경우가 많습니다. 모놀리스나 서비스 또는 양쪽 모두에 위치하는 글루 코드는 데이터 통합을 담당합니다. 서비스는 글루 코드를 사용하여 모놀리스가 소유한 데이터를 읽고 씁니다.
서비스가 모놀리스의 데이터에 액세스하는 데 사용할 수 있는 전략은 세 가지입니다:
- 모놀리스에서 제공하는 원격 API 호출
- 모놀리스의 데이터베이스에 직접 액세스
- 모놀리스의 데이터베이스와 동기화되는 자체 데이터 사본을 유지합니다
글루 코드는 때때로 손상 방지 계층이라고도 합니다. 글루 코드가 고유하고 온전한 도메인 모델을 가진 서비스가 레거시 모놀리스의 도메인 모델에 있는 개념으로 오염되는 것을 방지하기 때문입니다. 글루 코드는 서로 다른 두 모델 사이를 변환합니다. 손상 방지 계층이라는 용어는 에릭 에반스의 필독서인 도메인 주도 설계에서 처음 등장했으며, 이후 백서에서 더욱 구체화되었습니다. 손상 방지 계층을 개발하는 일은 결코 간단하지 않을 수 있습니다. 하지만 모놀리스 지옥에서 점진적으로 벗어나려면 반드시 만들어야 합니다.
새로운 기능을 경량 서비스로 구현하면 몇 가지 이점이 있습니다. 모놀리스가 더욱 관리하기 어려워지는 것을 방지할 수 있습니다. 해당 서비스는 모놀리스와 독립적으로 개발, 배포 및 확장할 수 있습니다. 새로운 서비스를 만들 때마다 마이크로서비스 아키텍처의 이점을 누릴 수 있습니다.
하지만 이 접근 방식으로는 모놀리스의 문제를 전혀 해결할 수 없습니다. 이러한 문제를 해결하려면 모놀리스를 분해해야 합니다. 이를 위한 전략을 살펴보겠습니다.
전략 2 – 프런트엔드와 백엔드 분리
모놀리식 애플리케이션의 규모를 줄이는 한 가지 전략은 프레젠테이션 계층을 비즈니스 로직 및 데이터 액세스 계층과 분리하는 것입니다. 일반적인 엔터프라이즈 애플리케이션은 적어도 세 가지 유형의 컴포넌트로 구성됩니다:
- 프레젠테이션 계층 – HTTP 요청을 처리하고 (REST) API 또는 HTML 기반 웹 UI를 구현하는 컴포넌트입니다. 정교한 사용자 인터페이스를 갖춘 애플리케이션에서는 프레젠테이션 계층이 상당한 양의 코드를 차지하는 경우가 많습니다.
- 비즈니스 로직 계층 – 애플리케이션의 핵심을 구성하고 비즈니스 규칙을 구현하는 컴포넌트입니다.
- 데이터 액세스 계층 – 데이터베이스 및 메시지 브로커와 같은 인프라 구성 요소에 액세스하는 구성 요소입니다.
일반적으로 프레젠테이션 로직과 비즈니스 및 데이터 액세스 로직은 명확하게 분리되어 있습니다. 비즈니스 계층에는 비즈니스 로직 컴포넌트를 캡슐화하는 하나 이상의 퍼사드로 구성된 굵은 입도의 API가 있습니다. 이 API는 모놀리스를 두 개의 더 작은 애플리케이션으로 분할하기에 적합한 자연스러운 경계입니다. 한 애플리케이션에는 프레젠테이션 계층이 포함되고, 다른 애플리케이션에는 비즈니스 및 데이터 액세스 로직이 포함됩니다. 분할 후에는 프레젠테이션 로직 애플리케이션이 비즈니스 로직 애플리케이션을 원격으로 호출합니다. 다음 다이어그램은 리팩터링 전후의 아키텍처를 보여 줍니다.

이러한 방식으로 모놀리스를 분리하면 두 가지 주요 이점이 있습니다. 두 애플리케이션을 서로 독립적으로 개발, 배포 및 확장할 수 있습니다. 특히 프레젠테이션 계층 개발자는 사용자 인터페이스를 빠르게 반복 개선하고 A/B 테스트 등을 손쉽게 수행할 수 있습니다. 이 접근 방식의 또 다른 이점은 개발한 마이크로서비스에서 호출할 수 있는 원격 API를 제공한다는 것입니다.
하지만 이 전략은 부분적인 해결책에 불과합니다. 두 애플리케이션 중 하나 또는 둘 다 관리하기 어려운 모놀리스가 될 가능성이 매우 높습니다. 남아 있는 모놀리스를 제거하려면 세 번째 전략을 사용해야 합니다.
전략 3 – 서비스 추출
세 번째 리팩터링 전략은 모놀리스 내의 기존 모듈을 독립형 마이크로서비스로 전환하는 것입니다. 모듈을 하나씩 추출해 서비스로 전환할 때마다 모놀리스는 작아집니다. 충분한 수의 모듈을 전환하고 나면 모놀리스는 더 이상 문제가 되지 않습니다. 완전히 사라지거나, 다른 서비스와 다를 바 없을 정도로 작아집니다.
서비스로 전환할 모듈의 우선순위 정하기
대규모의 복잡한 모놀리식 애플리케이션은 수십 개 또는 수백 개의 모듈로 구성되며, 이들 모두가 추출 대상이 될 수 있습니다. 어떤 모듈을 먼저 전환할지 결정하는 일은 쉽지 않은 경우가 많습니다. 좋은 접근 방식은 추출하기 쉬운 몇 개의 모듈부터 시작하는 것입니다. 이를 통해 전반적인 마이크로서비스와 특히 추출 프로세스에 대한 경험을 쌓을 수 있습니다. 그런 다음 가장 큰 이점을 얻을 수 있는 모듈을 추출해야 합니다.
모듈을 서비스로 전환하는 작업에는 일반적으로 많은 시간이 소요됩니다. 따라서 얻을 수 있는 이점을 기준으로 모듈의 우선순위를 정해야 합니다. 대개 변경이 잦은 모듈을 추출하는 것이 유리합니다. 모듈을 서비스로 전환하고 나면 모놀리스와 독립적으로 개발하고 배포할 수 있으므로 개발 속도가 빨라집니다.
모놀리스의 나머지 부분과 리소스 요구 사항이 크게 다른 모듈을 분리하는 것도 유용합니다. 예를 들어 인메모리 데이터베이스가 있는 모듈을 서비스로 전환하면 메모리 용량이 큰 호스트에 배포할 수 있습니다. 마찬가지로 연산 비용이 높은 알고리즘을 구현하는 모듈을 분리하면 해당 서비스를 CPU가 많은 호스트에 배포할 수 있으므로 유용할 수 있습니다. 특정 리소스 요구 사항이 있는 모듈을 서비스로 전환하면 애플리케이션을 훨씬 더 쉽게 확장할 수 있습니다.
어떤 모듈을 추출할지 결정할 때는 기존의 큰 단위 경계(일명 심(seam))를 찾아보는 것이 유용합니다. 이러한 경계를 활용하면 모듈을 더 쉽고 적은 비용으로 서비스로 전환할 수 있습니다. 그 예로 애플리케이션의 나머지 부분과 비동기 메시지를 통해서만 통신하는 모듈을 들 수 있습니다. 이러한 모듈은 비교적 쉽고 적은 비용으로 마이크로서비스로 전환할 수 있습니다.
모듈을 추출하는 방법
모듈을 추출하는 첫 단계는 모듈과 모놀리스 사이에 대단위 인터페이스를 정의하는 것입니다. 모놀리스에는 서비스가 소유한 데이터가 필요하고 서비스에도 모놀리스의 데이터가 필요하므로, 대부분 양방향 API가 됩니다. 모듈과 애플리케이션의 나머지 부분 사이에 복잡하게 얽힌 종속성과 세분화된 상호 작용 패턴이 존재하기 때문에 이러한 API를 구현하기는 쉽지 않은 경우가 많습니다. 도메인 모델 패턴을 사용해 구현한 비즈니스 로직은 도메인 모델 클래스 간에 수많은 연관 관계가 있어 리팩터링하기가 특히 어렵습니다. 이러한 종속성을 끊으려면 대개 코드를 상당히 많이 변경해야 합니다. 다음 다이어그램은 이 리팩터링을 보여 줍니다.
대단위 인터페이스를 구현한 다음에는 모듈을 독립형 서비스로 전환합니다. 이를 위해 모놀리스와 서비스가 프로세스 간 통신(IPC) 메커니즘을 사용하는 API를 통해 통신할 수 있도록 코드를 작성해야 합니다. 다음 다이어그램은 리팩터링 전, 도중, 후의 아키텍처를 보여 줍니다.

이 예에서 모듈 Z는 추출 대상 모듈입니다. 이 모듈의 구성 요소는 모듈 X에서 사용되며, 이 모듈은 모듈 Y를 사용합니다. 리팩터링의 첫 번째 단계는 한 쌍의 대단위 API를 정의하는 것입니다. 첫 번째 인터페이스는 모듈 X가 모듈 Z를 호출하는 데 사용하는 인바운드 인터페이스입니다. 두 번째 인터페이스는 모듈 Z가 모듈 Y를 호출하는 데 사용하는 아웃바운드 인터페이스입니다.
두 번째 리팩터링 단계에서는 모듈을 독립형 서비스로 전환합니다. 인바운드 및 아웃바운드 인터페이스는 IPC 메커니즘을 사용하는 코드로 구현됩니다. 대부분의 경우 모듈 Z를 마이크로서비스 섀시 프레임워크와 결합하여 서비스를 구축해야 합니다. 이 프레임워크는 서비스 디스커버리와 같은 횡단 관심사를 처리합니다.
모듈을 추출하면 모놀리스 및 다른 모든 서비스와 독립적으로 개발, 배포, 확장할 수 있는 또 하나의 서비스가 생깁니다. 이 서비스를 처음부터 다시 작성할 수도 있습니다. 이 경우 서비스를 모놀리스와 통합하는 API 코드는 두 도메인 모델 사이를 변환하는 부패 방지 계층이 됩니다. 서비스를 하나씩 추출할 때마다 마이크로서비스 아키텍처에 한 걸음 더 가까워집니다. 시간이 지날수록 모놀리스는 축소되고 마이크로서비스의 수는 점점 늘어납니다.
요약
기존 애플리케이션을 마이크로서비스로 마이그레이션하는 과정은 애플리케이션 현대화의 한 형태입니다. 애플리케이션을 처음부터 다시 작성하는 방식으로 마이크로서비스로 전환해서는 안 됩니다. 대신 애플리케이션을 점진적으로 리팩터링하여 일련의 마이크로서비스로 전환해야 합니다. 사용할 수 있는 전략은 세 가지입니다. 새로운 기능을 마이크로서비스로 구현하거나, 프레젠테이션 구성 요소를 비즈니스 및 데이터 액세스 구성 요소와 분리하거나, 모놀리스의 기존 모듈을 서비스로 전환하는 것입니다. 시간이 지남에 따라 마이크로서비스의 수가 늘어나고 개발 팀의 민첩성과 개발 속도도 향상될 것입니다.
편집자 – 총 7부로 구성된 이 연재 기사가 이제 완결되었습니다:
- 마이크로서비스 소개
- 마이크로서비스 구축: API 게이트웨이 사용
- 마이크로서비스 구축: 마이크로서비스 아키텍처의 프로세스 간 통신
- 마이크로서비스 아키텍처의 서비스 디스커버리
- 마이크로서비스를 위한 이벤트 기반 데이터 관리
- 마이크로서비스 배포 전략 선택
- 모놀리스를 마이크로서비스로 리팩터링하기(이 글)
전체 기사 모음과 NGINX Plus를 사용한 마이크로서비스 구현 정보를 전자책으로 다운로드할 수도 있습니다. 전자책 제목은 마이크로서비스: 설계부터 배포까지입니다. 또한 마이크로서비스 참조 아키텍처 시리즈와 마이크로서비스 솔루션 페이지도 확인해 보세요.
객원 블로거 Chris Richardson은 최초의 CloudFoundry.com을 설립했습니다. 이 서비스는 Amazon EC2용 초기 Java PaaS(서비스형 플랫폼)였습니다. 현재 그는 여러 조직을 대상으로 애플리케이션 개발 및 배포 방식을 개선할 수 있도록 컨설팅하고 있습니다. 또한 마이크로서비스에 관한 글을 https://microservices.io
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.