이 참조 가이드는 마이크로서비스 설계, 빌드, 배포에 대한 4부로 구성된 시리즈의 첫 번째 문서입니다. 이 시리즈에서는 마이크로서비스 아키텍처의 다양한 요소를 설명하며, 마이크로서비스 아키텍처 패턴의 이점과 단점 및 적용 방법이 포함되어 있습니다.
- 마이크로서비스 소개(이 문서)
- 모놀리식을 마이크로서비스로 리팩터링
- 마이크로서비스 설정의 서비스 간 통신
- 마이크로서비스 애플리케이션의 분산 추적
이 시리즈는 모놀리식 애플리케이션을 마이크로서비스 애플리케이션으로 리팩터링하는 마이그레이션을 설계 및 구현하는 애플리케이션 개발자 및 설계자를 대상으로 합니다.
모놀리식 애플리케이션
모놀리식 애플리케이션이란 여러 모듈이 단일 프로그램으로 결합된 단일 계층 소프트웨어 애플리케이션입니다. 예를 들어 전자상거래 애플리케이션을 개발하는 경우, 이 애플리케이션은 객체 지향 프로그래밍(OOP) 원칙에 맞는 모듈식 아키텍처를 가져야 합니다. 다음 다이어그램은 다양한 모듈로 구성되어 있는 전자상거래 애플리케이션의 설정 예시입니다. 모놀리식 애플리케이션에서는 프로그래밍 언어 구조체(예: 자바 패키지)와 빌드 아티팩트(예: 자바 JAR 파일)를 조합하여 모듈을 정의합니다.
그림 1. 프로그래밍 언어 구조체의 조합을 사용하는 여러 모듈이 있는 모놀리식 전자상거래 애플리케이션의 다이어그램
그림 1에서 전자상거래 애플리케이션의 다양한 모듈은 결제, 배송, 주문 관리를 위한 비즈니스 로직에 해당합니다. 이러한 모든 모듈은 단일 논리 실행 파일로 패키징 및 배포됩니다. 실제 형식은 애플리케이션의 언어 및 프레임워크에 따라 달라집니다. 예를 들어 많은 자바 애플리케이션이 JAR 파일로 패키징되고 Tomcat 또는 Jetty와 같은 애플리케이션 서버에서 배포됩니다. 마찬가지로 Rails 또는 Node.js 애플리케이션은 디렉터리 계층 구조로 패키징됩니다.
모놀리식의 이점
모놀리식 아키텍처는 애플리케이션을 빌드하는 기존 솔루션입니다. 다음은 애플리케이션을 위해 모놀리식 디자인을 채택할 때의 몇 가지 장점입니다.
- Selenium과 같은 도구를 사용하여 모놀리식 애플리케이션의 엔드 투 엔드 테스트를 구현할 수 있습니다.
- 패키징된 애플리케이션을 서버에 복사하기만 하면 모놀리식 애플리케이션을 배포할 수 있습니다.
- 모놀리식 애플리케이션의 모든 모듈은 메모리, 공간, 리소스를 공유하므로 단일 솔루션을 사용하여 로깅, 캐싱, 보안과 같이 여러 모듈을 포괄하는 문제점을 해결할 수 있습니다.
- 모놀리식 접근 방식은 모듈이 서로를 직접 호출할 수 있으므로 성능상의 이점을 제공할 수 있습니다. 반면에 마이크로서비스는 일반적으로 서로 통신하기 위해 네트워크 호출이 필요합니다.
모놀리식의 문제점
복잡한 모놀리식은 빌드, 디버그, 구조 파악이 점점 더 어려워지는 경우가 많습니다. 어느 시점부터는 장점보다 단점이 더 커집니다.
- 일반적으로 시간이 지나면서 애플리케이션이 점점 커집니다. 여러 모듈이 긴밀하게 결합된 크고 복잡한 애플리케이션에서는 변경사항을 구현하기가 복잡할 수 있습니다. 모든 코드 변경이 전체 시스템에 영향을 주므로 변경사항을 철저하게 관리해야 합니다. 변경사항 관리로 인해 전반적인 개발 및 테스트 프로세스가 마이크로서비스 애플리케이션의 경우보다 훨씬 오래 걸립니다.
- 대규모 모놀리식에서는 지속적 통합 및 배포(CI/CD)를 달성하기가 복잡할 수 있습니다. 이러한 복잡성의 원인은 애플리케이션의 일부만 업데이트하는 경우라도 전체 애플리케이션을 다시 배포해야 하기 때문입니다. 또한 회귀 검사를 위해 전체 애플리케이션을 광범위하게 수동으로 테스트해야 할 가능성이 높습니다.
- 모놀리식 애플리케이션은 여러 모듈의 리소스 요구사항이 서로 충돌할 경우 확장하기 어려울 수 있습니다. 예를 들어 한 모듈은 CPU 사용량이 높은 이미지 처리 로직을 구현하는데, 다른 모듈은 단순한 인메모리 데이터베이스일 수 있습니다. 이러한 모듈이 함께 배포되므로 하드웨어 선택 시 절충이 필요합니다.
- 모든 모듈이 동일한 프로세스 내에서 실행되므로 메모리 누수와 같은 모듈의 버그로 인해 전체 시스템이 다운될 가능성이 있습니다.
- 모놀리식 애플리케이션은 새로운 프레임워크와 언어를 채택하려는 경우에 복잡성이 가중됩니다. 예를 들어 기존보다 우월한 새 프레임워크를 사용하기 위해 전체 애플리케이션을 다시 작성하느라 많은 시간과 비용이 소요됩니다.
마이크로서비스 기반 애플리케이션
마이크로서비스는 일반적으로 고유한 특성 또는 기능 집합을 구현합니다. 각 마이크로서비스는 자체 아키텍처와 비즈니스 로직이 있는 미니 애플리케이션입니다. 예를 들어 일부 마이크로서비스는 다른 마이크로서비스 또는 애플리케이션의 클라이언트에서 사용하는 API를 노출합니다(예: 결제 게이트웨이 및 물류와의 타사 통합).
그림 1은 여러 모듈이 포함된 모놀리식 전자상거래 애플리케이션이었습니다. 다음 다이어그램은 전자상거래 애플리케이션을 마이크로서비스로 분할한 예입니다.
그림 2. 여러 기능 영역을 마이크로서비스로 구현한 전자상거래 애플리케이션의 다이어그램
그림 2에서 전용 마이크로서비스는 전자상거래 애플리케이션의 각 기능 영역을 구현합니다. 각 백엔드 서비스는 API를 노출할 수 있으며 서비스는 다른 서비스에서 제공하는 API를 사용합니다. 예를 들어 웹페이지를 렌더링하기 위해 UI 서비스는 결제 서비스 및 기타 서비스를 호출합니다. 서비스는 비동기식 메시지 기반 통신을 사용할 수도 있습니다. 서비스가 서로 통신하는 방법에 대한 자세한 내용은 이 시리즈의 세 번째 문서인 마이크로서비스 설정의 서비스 간 통신을 참조하세요.
마이크로서비스 아키텍처 패턴은 애플리케이션과 데이터베이스 간의 관계를 크게 변경합니다. 단일 데이터베이스를 다른 서비스와 공유하는 대신 각 서비스의 요구사항에 가장 적합한 자체 데이터베이스가 있는 것이 좋습니다. 서비스마다 데이터베이스가 하나씩 있는 경우 모든 데이터 요청이 공유 데이터베이스를 직접 사용하지 않고 서비스 API를 통과하기 때문에 서비스 간에 느슨하게 결합해야 합니다. 다음 다이어그램은 각 서비스에 자체 데이터베이스가 있는 마이크로서비스 아키텍처 패턴을 보여줍니다.
그림 3. 각 서비스에 자체 데이터베이스가 있는 마이크로서비스 아키텍처
그림 3에서 전자상거래 애플리케이션의 주문 서비스는 실시간 검색 기능이 있는 문서 중심 데이터베이스를 사용하여 원활하게 작동합니다. 결제 및 전송 서비스는 관계형 데이터베이스의 강력한 원자성, 일관성, 격리, 내구성(ACID) 보장에 의존합니다.
마이크로서비스의 이점
마이크로서비스 아키텍처 패턴은 이전 모놀리식 과제 섹션에서 설명한 복잡성 문제를 해결합니다. 마이크로서비스 아키텍처의 이점은 다음과 같습니다.
- 전체 기능을 그대로 유지하면서 마이크로서비스를 사용하여 애플리케이션을 관리 가능한 여러 부분 또는 서비스로 분리합니다. 각 서비스의 경계는 RPC 또는 메시지 기반 API 형식으로 명확히 정의됩니다. 따라서 개별 서비스의 개발 속도가 빨라지고 구조 파악 및 유지보수가 쉬워질 수 있습니다.
- 자율적인 여러 팀이 개별 서비스를 독립적으로 개발할 수 있습니다. 제품의 기술적 기능이 아닌 비즈니스 경계를 기준으로 마이크로서비스를 구성할 수 있습니다. 소프트웨어에서 할당된 부분에 대해 개발부터 테스트, 배포, 유지보수, 모니터링까지 전체 수명 주기를 단독으로 책임지는 독립된 팀을 조직하세요.
- 독립적인 마이크로서비스 개발 프로세스를 통해 개발자는 각 마이크로서비스를 서로 다른 프로그래밍 언어로 작성하여 다언어 애플리케이션을 개발할 수도 있습니다. 각 마이크로서비스에 가장 효과적인 언어를 사용하면 애플리케이션 개발 속도를 높이고 애플리케이션을 최적화하여 코드 복잡성 감소, 성능 향상, 기능 개선을 이룰 수 있습니다.
- 모놀리식에서 각 기능을 분리하면 독립적인 팀에서 마이크로서비스를 독립적으로 출시할 수 있습니다. 독립적인 출시 주기는 팀의 업무 속도를 높이고 제품 TTM(time to market)을 단축하는 데 도움이 될 수 있습니다.
- 마이크로서비스 아키텍처를 사용하면 각 서비스를 독립적으로 확장할 수도 있습니다. 용량 및 가용성 제약조건을 충족하는 각 서비스의 인스턴스 수를 배포할 수 있습니다. 서비스의 리소스 요구사항에 가장 적합한 하드웨어를 사용할 수도 있습니다. 서비스를 독립적으로 확장하면 전체 시스템의 가용성과 안정성을 높이는 데 도움이 됩니다.
다음은 모놀리식에서 마이크로서비스 아키텍처로 마이그레이션하는 것이 유용할 수 있는 몇 가지 구체적인 예입니다.
- 확장성, 관리성, 민첩성 또는 출시 속도 향상을 구현합니다.
- 새로운 비즈니스 수요를 충족하기 위해 대규모 레거시 애플리케이션을 최신 언어 및 기술 스택을 사용하여 점진적으로 다시 작성합니다.
- 여러 기능을 포괄하는 비즈니스 애플리케이션 또는 서비스를 여러 채널에서 재사용할 수 있도록 추출합니다. 재사용할 서비스의 예로는 결제 서비스, 로그인 서비스, 암호화 서비스, 항공편 검색 서비스, 고객 프로필 서비스, 알림 서비스 등이 있습니다.
- 기존 모놀리식의 특정 기능에 맞게 구축된 언어나 프레임워크를 채택합니다.
마이크로서비스의 문제점
마이크로서비스에는 모놀리식과 비교하여 다음과 같은 몇 가지 문제점이 있습니다.
- 마이크로서비스의 주요 과제는 애플리케이션이 분산 시스템이기 때문에 발생하는 복잡성입니다. 개발자는 서비스 간 통신 메커니즘을 선택하고 구현해야 합니다. 또한 이러한 서비스는 업스트림 서비스의 부분적인 장애와 가용성 부족도 처리해야 합니다.
마이크로서비스의 또 다른 문제점은 여러 마이크로서비스 간의 트랜잭션, 즉 분산 트랜잭션을 관리해야 한다는 것입니다. 비즈니스 작업은 여러 비즈니스 항목을 업데이트하는 경우가 많으며, 일반적으로 모든 작업이 적용되거나 모든 작업이 실패하는 원자적 방식으로 적용됩니다. 여러 작업을 단일 데이터베이스 트랜잭션으로 래핑하면 원자성이 보장됩니다.
마이크로서비스 기반 애플리케이션에서는 비즈니스 작업이 여러 마이크로서비스에 분산될 수 있으므로 서로 다른 서비스가 소유한 여러 데이터베이스를 업데이트해야 합니다. 장애가 발생하면 다른 마이크로서비스의 호출 성공 또는 성공 여부를 추적하고 상태를 롤백하는 것이 쉽지 않습니다. 최악의 경우 장애로 인한 상태 롤백이 제대로 수행되지 않아 서비스 간에 데이터가 일관되지 않을 수 있습니다. 서비스 간 분산 트랜잭션을 설정하는 다양한 방법에 대한 자세한 내용은 이 시리즈의 세 번째 문서인 마이크로서비스 설정의 서비스 간 통신을 참조하세요.
마이크로서비스 기반 애플리케이션의 포괄적인 테스트는 모놀리식 애플리케이션 테스트보다 복잡합니다. 예를 들어 모놀리식 전자상거래 서비스에서 주문을 처리하는 기능을 테스트하려면 항목을 선택하여 장바구니에 추가한 후 결제합니다. 마이크로서비스 기반 아키텍처에서 동일한 흐름을 테스트하려면 프런트엔드, 주문, 결제 등 여러 서비스가 서로를 호출하여 테스트 실행을 완료합니다.
마이크로서비스 기반 애플리케이션 배포는 모놀리식 애플리케이션 배포보다 더 복잡합니다. 마이크로서비스 애플리케이션은 일반적으로 여러 서비스로 구성되며, 각 서비스에는 여러 런타임 인스턴스가 있습니다. 또한 서비스가 통신해야 하는 다른 서비스의 위치를 검색할 수 있게 해주는 서비스 검색 메커니즘을 구현해야 합니다.
모니터링 및 경고할 서비스가 많기 때문에 마이크로서비스 아키텍처에 작업 오버헤드가 추가됩니다. 또한 마이크로서비스 아키텍처에서 서비스 간 통신 지점이 증가하여 장애 지점도 더 많아집니다. 모놀리식 애플리케이션은 소규모 애플리케이션 서버 클러스터에 배포될 수 있습니다. 마이크로서비스 기반 애플리케이션에는 여러 언어 및 환경에서 빌드, 테스트, 배포, 실행을 위한 수십 개의 개별 서비스가 있을 수 있습니다. 장애 조치 및 복원력을 위해 이러한 모든 서비스는 클러스터링해야 합니다. 마이크로서비스 애플리케이션을 생성하려면 고품질 모니터링 및 운영 인프라가 필요합니다.
마이크로서비스 아키텍처에서는 서비스가 분할되어 있으므로 애플리케이션이 동시에 더 많은 기능을 수행할 수 있습니다. 그러나 여러 모듈이 격리된 서비스로 실행되므로 서비스 간 네트워크 호출로 인해 응답 시간에 지연이 발생합니다.
모든 애플리케이션이 마이크로서비스로 분할될 만큼 큰 것은 아닙니다. 또한 일부 애플리케이션은 구성요소 간의 긴밀한 통합(예: 실시간 데이터의 빠른 스트림을 처리해야 하는 애플리케이션)이 필요합니다. 서비스 간 통신 레이어가 추가되면 실시간 처리 속도가 느려질 수 있습니다. 서비스 간의 통신을 사전에 고려하면 서비스 경계를 명확하게 표시하는 데 유용한 정보를 얻을 수 있습니다.
애플리케이션에 마이크로서비스 아키텍처가 적합한지 여부를 판단할 때는 다음 사항을 고려하세요.
- 마이크로서비스에는 서비스별 데이터베이스가 권장됩니다. 애플리케이션의 데이터 모델링을 수행할 때 서비스별 데이터베이스가 애플리케이션에 적합한지 확인하세요.
- 마이크로서비스 아키텍처를 구현할 때는 병목 현상을 식별하고, 장애를 감지 및 방지하고, 진단을 지원할 수 있도록 환경을 계측하고 모니터링해야 합니다.
- 마이크로서비스 아키텍처에서는 각 서비스에 별도의 액세스 제어가 있습니다. 보안을 강화하려면 환경 내에서뿐 아니라 API를 소비하는 외부 애플리케이션에서도 각 서비스에 대한 액세스를 보호해야 합니다.
- 동기식 서비스 간 통신은 일반적으로 애플리케이션의 가용성을 떨어뜨립니다. 예를 들어 전자상거래 애플리케이션의 주문 서비스가 다른 서비스 업스트림을 동기식으로 호출했을 때 해당 서비스를 사용할 수 없으면 주문을 만들 수 없습니다. 따라서 비동기의 메시지 기반 통신을 구현하는 것이 좋습니다.
모놀리식 애플리케이션을 마이크로서비스로 마이그레이션해야 하는 경우
모놀리식을 이미 성공적으로 운영하고 있는 상황에서 마이크로서비스를 채택하려면 팀에 상당한 투자 비용이 발생합니다. 마이크로서비스의 원칙은 팀에 따라 다양한 방식으로 구현됩니다. 마이크로서비스의 크기 또는 필요한 마이크로서비스 수는 엔지니어링 팀마다 다르게 도출됩니다.
애플리케이션에 마이크로서비스가 가장 적합한 접근 방식인지 확인하려면 먼저 해결해야 할 주요 비즈니스 목표 또는 어려움을 파악합니다. 더 간단하게 목표를 달성하거나 식별한 문제를 해결할 수 있습니다. 예를 들어 애플리케이션을 더 빠르게 확장하려는 할 때 자동 확장이 더 효율적인 솔루션일 수 있습니다. 프로덕션 환경에서 버그를 발견한 경우 단위 테스트 및 지속적 통합(CI)을 구현하면서 시작할 수 있습니다.
마이크로서비스 방식이 목표를 달성하는 가장 좋은 방법이라고 생각되면 모놀리식에서 하나의 서비스를 추출하고 프로덕션에서 개발하고 테스트하며 배포합니다. 자세한 내용은 이 시리즈의 다음 문서인 모놀리식을 마이크로서비스로 리팩터링을 참고하세요. 하나의 서비스를 추출하여 프로덕션에서 실행한 후에는 다음 서비스 추출을 시작하고 각 주기에서 계속 학습합니다.
마이크로서비스 아키텍처 패턴은 시스템을 독립적으로 배포 가능한 서비스 집합으로 분해합니다. 모놀리식 애플리케이션을 개발할 때는 소프트웨어 개발 속도를 저하시킬 수 있는 대규모 팀을 조정해야 합니다. 마이크로서비스 아키텍처를 구현하면 규모가 작고 자율적인 팀이 병렬로 작동하도록 하여 개발 속도를 높일 수 있습니다.
이 시리즈의 다음 문서인 모놀리식을 마이크로서비스로 리팩터링에서는 모놀리식 애플리케이션을 마이크로서비스로 리팩터링하는 다양한 전략에 대해 알아봅니다.
다음 단계
- 이 시리즈의 다음 문서를 읽고 마이크로서비스 분해를 위한 애플리케이션 리팩터링 전략에 대해 알아보세요.
- 이 시리즈의 세 번째 문서를 읽고 마이크로서비스 설정의 서비스 간 통신에 대해 알아보세요.
- 이 시리즈의 마지막인 네 번째 문서를 읽고 마이크로서비스 간 요청 분산 추적에 대해 알아보세요.