마이크로 서비스 아키텍처는 작은 자율 서비스 컬렉션으로 구성됩니다. 각 서비스는 독립적이며 제한된 컨텍스트 내에서 단일 비즈니스 기능을 구현해야 합니다. 제한된 컨텍스트는 비즈니스 내의 자연스러운 분할이며 도메인 모델이 존재하는 명시적 경계를 제공합니다.
마이크로 서비스란?
마이크로 서비스는 작고, 독립적이며, 느슨하게 결합되어 있습니다. 하나의 소규모 개발자 팀이 작성하고 유지 관리할 수 있습니다.
각 서비스는 작은 개발 팀이 관리할 수 있는 개별 코드베이스입니다.
서비스를 독립적으로 배포할 수 있습니다. 팀이 전체 애플리케이션을 다시 빌드한 후 재배치하지 않고도 기존 서비스를 업데이트할 수 있습니다.
서비스가 해당 데이터 또는 외부 상태를 유지해야 합니다. 이는 별도의 데이터 레이어가 데이터 지속성을 처리하는 기존 모델과의 차이점입니다.
서비스가 잘 정의된 API를 사용하여 서로 통신합니다. 각 서비스의 내부 구현 세부 정보는 다른 서비스에서 숨겨집니다.
다중저장소 프로그래밍을 지원합니다. 예를 들어 서비스가 동일한 기술 스택, 라이브러리 또는 프레임워크를 공유할 필요가 없습니다.
서비스 자체 외에도 다음과 같은 몇 가지 다른 구성 요소가 기존 마이크로 서비스 아키텍처에 나타납니다.
관리/오케스트레이션. 이 구성 요소는 노드에 서비스 배치, 실패 식별, 노드 간에 서비스 부하 조정 등의 작업을 담당합니다. 일반적으로 이 구성 요소는 사용자 지정 빌드가 아니라 Kubernetes와 같은 기성 기술입니다.
API 게이트웨이. API 게이트웨이는 클라이언트의 진입점입니다. 클라이언트는 서비스를 직접 호출하는 대신, 호출을 백 엔드의 적절한 서비스에 전달하는 API 게이트웨이를 호출합니다.
API 게이트웨이를 사용할 경우의 장점은 다음과 같습니다.
클라이언트와 서비스가 분리됩니다. 모든 클라이언트를 업데이트하지 않고도 서비스 버전을 관리하거나 서비스를 리팩터링할 수 있습니다.
서비스가 웹 우호적이 아닌 AMQP 등의 메시징 프로토콜을 사용할 수 있습니다.
API 게이트웨이는 인증, 로깅, SSL 종료, 부하 분산 등의 다른 교차 기능을 수행할 수 있습니다.
제한, 캐싱, 변환 또는 유효성 검사와 같은 즉시 사용 가능한 정책.
이점
민첩성. 마이크로 서비스는 독립적으로 배포되기 때문에 버그 수정 및 기능 릴리스를 관리하기가 더 쉽습니다. 전체 애플리케이션을 다시 배포하지 않고 서비스를 업데이트할 수 있고, 문제가 발생하면 업데이트를 롤백할 수 있습니다. 기존의 많은 애플리케이션의 경우, 버그가 애플리케이션의 한 부분에서 발견되면 전체 릴리스 프로세스를 차단할 수 있습니다. 버그 수정이 통합, 테스트 및 게시될 때까지 새로운 기능은 보류될 수 있습니다.
집중화된 소규모 팀. 마이크로 서비스는 규모가 작아서 한 기능 팀에서 충분히 구축, 테스트 및 배포할 수 있습니다. 소규모 팀은 민첩성이 높습니다. 대규모 팀은 커뮤니케이션의 속도가 느리고, 관리 오버헤드가 증가하며, 민첩성이 감소되기 때문에 생산성이 떨어지는 경향이 있습니다.
소규모 코드 기준. 모놀리식 애플리케이션의 경우 시간이 경과하면서 코드 종속성이 얽히는 경향이 있습니다. 새 기능을 추가하려면 여러 지점의 코드를 손봐야 합니다. 마이크로 서비스 아키텍처는 코드나 데이터 저장소를 공유하지 않으므로 종속성이 최소화되며 그 결과 새로운 기능을 추가하기 쉽습니다.
기술의 혼합. 팀은 혼합된 기술 스택을 적절히 사용하여 서비스에 가장 적합한 기술을 선택할 수 있습니다.
결함 격리. 개별 마이크로 서비스를 사용할 수 없게 되더라도, 장애를 제대로 처리하도록 업스트림 마이크로 서비스를 설계하면 전체 애플리케이션에 방해가 되지 않습니다. 예를 들어 회로 차단기 패턴을 구현하거나 마이크로 서비스가 비동기 메시징 패턴을 사용하여 서로 통신하도록 솔루션을 디자인할 수 있습니다.
확장성. 서비스는 별도로 확장될 수 있어 전체 애플리케이션 규모를 확장하지 않고도 리소스가 더 많이 필요한 하위 시스템의 규모를 확장할 수 있습니다. Kubernetes와 같은 오케스트레이터를 사용하면 더 높은 수준의 서비스를 단일 호스트에 압축하여 리소스를 보다 효율적으로 활용할 수 있습니다.
데이터 격리. 단일 마이크로 서비스만 영향을 받기 때문에 스키마 업데이트를 수행하는 것이 훨씬 쉽습니다. 모놀리식 애플리케이션에서는 스키마 업데이트가 매우 어려울 수 있습니다. 애플리케이션의 다양한 부분이 모두 동일한 데이터에 영향을 미칠 수 있어서 스키마를 변경하는 것이 위험하기 때문입니다.
과제
마이크로 서비스의 이점은 무료로 제공되지 않습니다. 마이크로 서비스 아키텍처를 시작하기 전에 고려해야 할 몇 가지 과제가 있습니다.
복잡성. 마이크로 서비스 애플리케이션에는 동등한 모놀리식 애플리케이션보다 작동 부분이 더 많습니다. 각 서비스는 더 단순하지만 전체 시스템이 더 복잡합니다.
개발 및 테스트. 다른 종속 서비스에 의존하는 소규모 서비스를 작성하려면 기존의 모놀리식 또는 계층화된 애플리케이션을 작성하는 것과 다른 접근 방식이 필요합니다. 기존 도구는 항상 서비스 종속성 작업에 맞게 설계되지 않습니다. 서비스 경계를 벗어난 리팩터링은 어려울 수 있습니다. 특히 애플리케이션이 빠르게 발전하는 경우 서비스 종속성을 테스트하기도 어렵습니다.
통제 부족. 마이크로 서비스 빌드에 대한 분산 접근 방법에는 장점이 있지만 문제가 발생할 수도 있습니다. 언어와 프레임워크가 너무 많아서 애플리케이션 유지 관리가 어려워질 수 있습니다. 팀의 유연성을 지나치게 제한하지 않고 몇 가지 프로젝트 전체 표준을 적용하는 것이 유용할 수도 있습니다. 특히 로깅과 같은 교차 기능에 해당합니다.
네트워크 정체 및 대기 시간. 다수의 작고 세분화된 서비스를 사용하면 서비스 간 통신이 증가할 수 있습니다. 또한 서비스 종속성 체인이 너무 길어질 경우(서비스 A가 B를 호출하고, B가 C를 호출하고...) 추가 대기 시간이 문제가 될 수 있습니다. API를 신중하게 디자인해야 합니다. 통신량이 과도한 API를 피하고, 직렬화 형식을 고려하고, 큐 기반 부하 평준화와 같은 비동기 통신 패턴을 사용할 영역을 찾아보세요.
데이터 무결성. 자체 데이터 지속성을 담당하는 각 마이크로 서비스입니다. 따라서 여러 서비스에 대한 데이터 일관성은 어려울 수 있습니다. 서로 다른 서비스는 서로 다른 기술을 사용하여 서로 다른 시간에 데이터를 유지하며 잠재적으로 다른 수준의 성공을 거두고 있습니다. 둘 이상의 마이크로 서비스가 새 날짜 또는 변경된 날짜를 유지하는 데 관련된 경우 전체 데이터 변경이 ACID 트랜잭션으로 간주될 가능성은 거의 없습니다. 대신, 이 기술은 BASE(기본적으로 사용 가능, 소프트 상태 및 최종 일치)에 더 정렬됩니다. 가능한 경우 결과적 일관성을 수용합니다.
관리. 마이크로 서비스에 성공하려면 성숙한 DevOps 문화가 필요합니다. 전체 서비스의 상관관계 로깅이 까다로울 수 있습니다. 일반적으로 로깅은 단일 사용자 작업에 대한 여러 서비스 호출을 상호 연결해야 합니다.
버전 관리. 서비스 업데이트로 인해 종속된 서비스가 손상되지 않아야 합니다. 언제든지 여러 서비스가 업데이트될 수 있으므로 신중하게 디자인하지 않으면 이전 버전 또는 이후 버전과의 호환성 문제가 발생할 수 있습니다.
기술 수준. 마이크로 서비스는 고도로 분산된 시스템입니다. 팀이 성공을 위한 기술과 경험을 가지고 있는지 신중하게 평가합니다.
모범 사례
비즈니스 도메인을 중심으로 서비스를 모델링합니다.
모든 것을 분산합니다. 개별 팀이 서비스 디자인 및 빌드를 담당합니다. 코드 또는 데이터 스키마를 공유하지 않도록 합니다.
데이터 스토리지가 데이터를 소유하는 서비스의 프라이빗용이어야 합니다. 각 서비스 및 데이터 형식에 가장 적합한 스토리지를 사용합니다.
서비스가 잘 디자인된 API를 통해 통신합니다. 구현 세부 정보가 누출되지 않도록 합니다. API는 서비스의 내부 구현이 아니라 도메인을 모델링해야 합니다.
서비스 간의 결합을 피합니다. 결합의 원인에는 공유 데이터베이스 스키마, 엄격한 통신 프로토콜 등이 포함됩니다.
인증, SSL 종료 등의 교차 문제를 게이트웨이에 오프로드합니다.
도메인 정보를 게이트웨이에서 숨깁니다. 게이트웨이는 비즈니스 규칙 또는 도메인 논리를 몰라도 클라이언트 요청을 처리하고 라우트해야 합니다. 그러지 않으면 게이트웨이가 종속성이 되며 서비스 간에 결합이 발생할 수 있습니다.
서비스에 느슨한 결합 및 높은 기능 응집력이 있어야 합니다. 함께 변경될 가능성이 큰 기능은 함께 패키지하고 배포해야 합니다. 개별 서비스에 상주할 경우, 한 서비스가 변경되면 다른 서비스를 업데이트해야 하므로 해당 서비스가 긴밀하게 결합됩니다. 두 서비스 간의 과도한 통신량은 긴밀한 결합과 낮은 응집력의 증상일 수 있습니다.
실패를 격리합니다. 복원 전략을 사용하여 한 서비스 내의 실패가 계단식으로 연속되지 않도록 합니다. 복원력 패턴 및 신뢰할 수 있는 애플리케이션 디자인을 참조하세요.
다음 단계
Azure에서 마이크로 서비스 아키텍처를 빌드하는 방법에 대한 자세한 지침은 Azure에서 마이크로 서비스 설계, 구축 및 운영을 참조하세요.