다음을 통해 공유


마이크로 서비스 아키텍처 스타일

마이크로서비스는 복원력 있고 확장성이 뛰어나고 독립적으로 배포할 수 있고 신속하게 진화할 수 있는 애플리케이션을 빌드하는 데 널리 사용되는 아키텍처 스타일입니다. 성공적인 마이크로 서비스 아키텍처를 구축하려면 사고방식의 근본적인 변화가 필요합니다. 애플리케이션을 더 작은 서비스로 분해하는 것 이상입니다. 또한 시스템을 설계, 배포 및 운영하는 방법도 재고해야 합니다.

마이크로 서비스 아키텍처는 작은 자율 서비스 컬렉션으로 구성됩니다. 각 서비스는 독립적이며 제한된 컨텍스트 내에서 단일 비즈니스 기능을 구현해야 합니다. 제한된 컨텍스트는 비즈니스 내의 자연스러운 분할이며 도메인 모델이 존재하는 명시적 경계를 제공합니다.

마이크로 서비스 아키텍처 스타일의 논리적 다이어그램.

이 다이어그램은 Microsoft Azure에 배포된 마이크로 서비스 아키텍처를 보여 줍니다. 각각 주요 아키텍처 구성 요소를 나타내는 레이블이 지정된 8개의 섹션으로 구성됩니다. 레이아웃은 왼쪽에서 오른쪽으로, 위에서 아래로 흐릅니다. 맨 왼쪽에서 레이블이 지정된 클라이언트 아이콘은 애플리케이션에 대한 요청을 시작하는 사용자 또는 외부 시스템을 나타냅니다. 화살표는 클라이언트에서 API 게이트웨이로 가리킵니다. 요청은 API 게이트웨이를 통해 적절한 마이크로 서비스로 흐릅니다. 화살표는 API 게이트웨이에서 레이블이 지정된 마이크로 서비스 상자로 가리킵니다. 이 상자에는 도메인 서비스에 대한 아이콘 2개, 컴퍼지션 서비스 아이콘 1개, 서비스 아이콘 1개가 포함되어 있습니다. 화살표는 마이크로 서비스에서 도메인 데이터베이스로 레이블이 지정된 다른 상자를 가리킵니다. 이 상자에는 두 개의 SQL 데이터베이스와 NoSQL 데이터베이스를 나타내는 아이콘이 포함되어 있습니다. 또한 화살표는 마이크로 서비스에서 메시지 지향 미들웨어라는 레이블이 지정된 상자로 가리킵니다. 화살표에는 게시 또는 구독 및 이벤트 레이블이 지정됩니다. 다이어그램에는 관찰 가능성, 관리 및 오케스트레이션 및 DevOps를 나타내는 상자도 포함되어 있습니다.

마이크로 서비스란?

마이크로 서비스는 소규모 개발자 팀이 작성하고 유지 관리할 수 있는 작고 독립적이며 느슨하게 결합된 구성 요소입니다. 각 서비스는 별도의 코드베이스로 관리되므로 소규모 팀이 효율적으로 처리할 수 있습니다. 서비스를 독립적으로 배포할 수 있으므로 팀은 전체 애플리케이션을 다시 빌드하거나 다시 배포하지 않고도 기존 서비스를 업데이트할 수 있습니다. 중앙 집중식 데이터 계층이 있는 기존 모델과 달리 마이크로 서비스는 자체 데이터 또는 외부 상태를 유지합니다. 잘 정의된 API를 통해 통신하여 내부 구현을 다른 서비스에서 숨깁니다. 또한 이 아키텍처는 다중 글로트 프로그래밍을 지원하므로 서비스에서 동일한 기술 스택, 라이브러리 또는 프레임워크를 공유할 필요가 없습니다.

구성 요소

서비스 자체 외에도 다른 구성 요소는 일반적인 마이크로 서비스 아키텍처에 표시됩니다.

  • 관리 또는 오케스트레이션: 이 관리 구성 요소는 마이크로 서비스 오케스트레이션을 처리합니다. 노드 간에 서비스를 예약 및 배포하고, 오류를 감지하고, 실패에서 복구하고, 수요에 따라 자동 크기 조정을 사용하도록 설정합니다. Kubernetes와 같은 컨테이너 오케스트레이션 플랫폼은 일반적으로 이 기능을 제공합니다. 클라우드 네이티브 환경에서 Azure Container Apps와 같은 솔루션은 관리되는 오케스트레이션 및 기본 제공 크기 조정을 제공합니다. 이러한 도구는 배포 복잡성 및 운영 오버헤드를 줄입니다.

  • API 게이트웨이: API 게이트웨이는 클라이언트의 진입점 역할을 합니다. 클라이언트는 서비스를 직접 호출하는 대신 API 게이트웨이에 요청을 보냅니다. 게이트웨이는 해당 요청을 적절한 백 엔드 서비스로 전달합니다. 또한 인증, 로깅, 부하 분산과 같은 횡단 관심사도 처리합니다. 클라우드 네이티브 마이크로 서비스 아키텍처에서 Envoy 및 Nginx와 같은 간단한 서비스 프록시는 내부 서비스 간 통신을 지원합니다. 동서 트래픽이라고 하는 이러한 유형의 내부 트래픽은 고급 라우팅 및 트래픽 제어를 가능하게 합니다.

  • 메시지 지향 미들웨어: Apache Kafka 및 Azure Service Bus와 같은 메시징 플랫폼은 느슨한 결합을 촉진하고 높은 확장성을 지원하여 마이크로 서비스에서 비동기 통신을 가능하게 합니다. 이벤트 기반 아키텍처의 토대를 형성합니다. 이 방법을 사용하면 서비스가 실시간으로 이벤트에 반응하고 비동기 메시징을 통해 통신할 수 있습니다.

  • 관찰 가능성: 효과적인 관찰 전략으로 팀은 시스템 안정성을 유지하고 문제를 신속하게 해결할 수 있습니다. 중앙 집중식 로깅은 더 쉬운 진단을 지원하기 위해 로그를 함께 제공합니다. 애플리케이션 성능 모니터링 에이전트 및 OpenTelemetry와 같은 프레임워크를 사용한 실시간 모니터링은 시스템 상태 및 성능에 대한 가시성을 제공합니다. 분산 추적은 서비스 경계를 넘어 요청을 추적합니다. 이는 팀이 병목 상태를 찾고 성능을 향상시키는 데 도움이 됩니다.

  • 데이터 관리: 잘 디자인된 데이터베이스 아키텍처는 자율성과 확장성을 지원합니다. 마이크로 서비스는 종종 각 서비스의 특정 요구 사항에 따라 SQL 또는 NoSQL과 같은 다양한 데이터베이스 형식을 선택하여 다국어 지속성을 사용합니다. 이 방법은 DDD(도메인 기반 디자인) 및 제한된 컨텍스트의 개념과 일치합니다. 각 서비스는 해당 데이터 및 스키마를 소유합니다. 이 소유권은 서비스 간 종속성을 줄이고 서비스가 독립적으로 발전할 수 있도록 합니다. 이 분산형 모델은 유연성, 성능 및 시스템 복원력을 향상시킵니다.

혜택

  • 민첩성: 마이크로 서비스는 독립적으로 배포되므로 버그 수정 및 기능 릴리스를 관리하는 것이 더 쉽습니다. 전체 애플리케이션을 다시 배포하지 않고 서비스를 업데이트하고 문제가 발생하는 경우 업데이트를 롤백할 수 있습니다. 많은 기존 애플리케이션에서 애플리케이션의 한 부분에서 버그를 발견하면 전체 릴리스 프로세스를 차단할 수 있습니다. 예를 들어 버그 수정을 통합, 테스트 및 게시해야 하는 경우 버그가 새 기능을 중단시킬 수 있습니다.

  • 소규모의 포커스가 있는 팀: 마이크로 서비스는 단일 기능 팀이 빌드, 테스트 및 배포할 수 있을 만큼 작아야 합니다. 소규모 팀은 민첩성이 높습니다. 대규모 팀은 커뮤니케이션이 느리고 관리 오버헤드가 증가하고 민첩성이 감소하기 때문에 생산성이 떨어지는 경향이 있습니다.

  • 작은 코드 베이스: 모놀리식 애플리케이션에서 코드 종속성은 시간이 지남에 따라 얽히게 되는 경우가 많습니다. 새 기능을 추가하려면 코드베이스의 여러 부분에서 변경이 필요할 수 있습니다. 마이크로 서비스 아키텍처는 코드 또는 데이터 저장소를 공유하지 않음으로써 이 문제를 방지합니다. 이 방법을 사용하면 종속성을 최소화하고 새로운 기능을 더 쉽게 도입할 수 있습니다.

  • 기술의 혼합: 팀은 다양한 기술 스택을 적절하게 사용하여 서비스에 가장 적합한 기술을 선택할 수 있습니다.

  • 오류 격리: 개별 마이크로 서비스를 사용할 수 없게 되면 업스트림 마이크로 서비스가 오류를 올바르게 처리하도록 설계된 한 전체 애플리케이션이 중단되지 않습니다. 예를 들어 회로 차단기 패턴을 구현하거나 비동기 메시징 패턴을 사용하여 마이크로 서비스가 서로 통신할 수 있도록 솔루션을 디자인할 수 있습니다.

  • 확장성: 서비스는 독립적으로 확장할 수 있습니다. 이 방법을 사용하면 전체 애플리케이션을 확장하지 않고도 더 많은 리소스가 필요한 하위 시스템을 확장할 수 있습니다. Kubernetes와 같은 오케스트레이터를 사용하여 단일 호스트에 더 높은 수준의 서비스 밀도를 추가하여 리소스 사용 효율성을 높일 수 있습니다.

  • 데이터 격리: 하나의 마이크로 서비스만 영향을 받으므로 마이크로 서비스 아키텍처에서 스키마를 업데이트하는 것이 더 간단합니다. 반면, 모놀리식 애플리케이션은 여러 구성 요소가 동일한 데이터와 상호 작용하는 경우가 많기 때문에 스키마 변경을 복잡하게 만들 수 있습니다. 이 공유 액세스는 수정을 잠재적으로 위험하게 만듭니다.

과제들

마이크로서비스의 이점은 절충점을 동반합니다. 마이크로 서비스 아키텍처를 만들기 전에 다음 과제를 고려합니다.

  • 복잡성: 마이크로 서비스 애플리케이션에는 동일한 모놀리식 애플리케이션보다 이동 부분이 더 많이 있습니다. 각 서비스는 더 단순하지만 전체 시스템이 더 복잡합니다. 애플리케이션을 디자인할 때 서비스 검색, 데이터 일관성, 트랜잭션 관리 및 서비스 간 통신과 같은 문제를 고려해야 합니다.

  • 개발 및 테스트: 다른 종속 서비스에 의존하는 소규모 서비스를 작성하려면 기존의 모놀리식 또는 계층화된 애플리케이션을 작성하는 것과는 다른 접근 방식이 필요합니다. 기존 도구가 항상 서비스 종속성을 사용하도록 설계되지는 않습니다. 서비스 경계를 벗어난 리팩터링은 어려울 수 있습니다. 특히 애플리케이션이 빠르게 진화하는 경우 서비스 종속성을 테스트하는 것도 어렵습니다.

  • 거버넌스 부족: 마이크로 서비스를 빌드하는 탈중앙화 접근 방식은 장점이 있지만 문제가 발생할 수도 있습니다. 언어와 프레임워크가 너무 많아서 애플리케이션 유지 관리가 어려워질 수 있습니다. 팀의 유연성을 지나치게 제한하지 않고 몇 가지 프로젝트 전체 표준을 적용하는 것이 유용할 수도 있습니다. 이 메서드는 특히 로깅과 같은 교차 절단 기능에 적용됩니다.

  • 네트워크 정체 및 대기 시간: 많은 소규모 세분화된 서비스를 사용하면 더 많은 서비스 간 통신이 발생할 수 있습니다. 또한 서비스 종속성 체인이 너무 길어지면(서비스 A는 C...를 호출하는 B를 호출) 추가 대기 시간이 문제가 될 수 있습니다. API를 신중하게 디자인해야 합니다. 지나치게 번잡한 API를 피하고, 직렬화 형식을 고려하고, Queue-Based 부하 평준화 패턴과 같은 비동기 통신 패턴을 사용할 장소를 찾습니다.

  • 데이터 무결성: 각 마이크로 서비스는 자체 데이터 지속성을 담당합니다. 따라서 여러 서비스에 대한 데이터 일관성은 어려울 수 있습니다. 서로 다른 서비스는 서로 다른 기술을 사용하여 서로 다른 시간에 데이터를 유지하며 잠재적으로 다른 수준의 성공을 거두고 있습니다. 둘 이상의 마이크로 서비스가 새 데이터 또는 변경된 데이터를 유지하는 데 관련된 경우 전체 데이터 변경이 ACID(원자성, 일관성, 격리 및 지속성) 트랜잭션으로 간주될 가능성은 거의 없습니다. 대신 이 기술은 기본적으로 사용 가능한 소프트 상태, 최종 일관성(BASE)에 더 맞춰집니다. 가능한 경우 결과적 일관성을 수용합니다.

  • 경영: 성공적인 마이크로 서비스 아키텍처에는 완성도 높은 DevOps 문화권이 필요합니다. 전체 서비스의 상관관계 로깅이 까다로울 수 있습니다. 일반적으로 로깅은 단일 사용자 작업에 대한 여러 서비스 호출을 상호 연결해야 합니다.

  • 버전 관리: 서비스에 대한 업데이트는 서비스에 의존하는 서비스를 중단해서는 안 됩니다. 언제든지 여러 서비스가 업데이트될 수 있으므로 신중하게 디자인하지 않으면 이전 버전 또는 이후 버전과의 호환성 문제가 발생할 수 있습니다.

  • 기술 집합: 마이크로 서비스는 고도로 분산된 시스템입니다. 팀이 성공을 위한 기술과 경험을 가지고 있는지 신중하게 평가합니다.

모범 사례

  • 비즈니스 도메인을 중심으로 서비스를 모델링합니다. DDD를 사용하여 바인딩된 컨텍스트를 식별하고 명확한 서비스 경계를 정의합니다. 복잡성을 높이고 성능을 줄일 수 있는 지나치게 세분화된 서비스를 만들지 마세요.

  • 모든 것을 분산합니다. 개별 팀은 엔드엔드 서비스를 설계하고 빌드할 책임이 있습니다. 코드 또는 데이터 스키마를 공유하지 마세요.

  • 사용하는 언어 및 프레임워크 수를 제한하여 기술 선택을 표준화합니다. 로깅, 모니터링 및 배포를 위한 플랫폼 전체 표준을 설정합니다.

  • 데이터 스토리지는 데이터를 소유한 서비스에 대해 비공개여야 합니다. 각 서비스 및 데이터 형식에 가장 적합한 스토리지를 사용합니다.

  • 서비스는 잘 설계된 API를 통해 통신합니다. 구현 세부 정보가 누출하지 않도록 방지합니다. API는 서비스의 내부 구현이 아니라 도메인을 모델링해야 합니다.

  • 서비스 간의 결합을 방지합니다. 결합의 원인에는 공유 데이터베이스 스키마 및 엄격한 통신 프로토콜이 포함됩니다.

  • 서비스 간 암호화에 mTLS(상호 전송 계층 보안)를 사용하여 보안을 개선합니다. 역할 기반 액세스 제어를 구현하고 API 게이트웨이를 사용하여 정책을 적용합니다.

  • 인증 및 SSL 종료와 같은 횡단 관심사를 게이트웨이에 오프로드합니다. Dapr과 같은 서비스 메시 및 프레임워크는 mTLS 인증 및 복원력과 같은 일반적인 교차 절단 문제에도 도움이 될 수 있습니다.

  • 게이트웨이에서 도메인 정보를 유지합니다. 게이트웨이는 비즈니스 규칙 또는 도메인 논리에 대한 지식 없이 클라이언트 요청을 처리하고 라우팅해야 합니다. 그렇지 않으면 게이트웨이가 종속성이 되어 서비스 간에 결합을 일으킬 수 있습니다.

  • 서비스에는 느슨한 결합과 높은 기능적 응집력이 있어야 합니다. 함께 변경될 가능성이 있는 함수는 함께 패키지 및 배포해야 합니다. 별도의 서비스에 상주하는 경우 한 서비스의 변경으로 인해 다른 서비스를 업데이트해야 하기 때문에 이러한 서비스는 긴밀하게 결합됩니다. 두 서비스 간의 지나치게 수다스러운 통신은 긴밀한 결합과 낮은 응집력의 증상일 수 있습니다.

  • CI/CD(지속적인 통합 및 지속적인 배포) 파이프라인을 사용하여 테스트 및 배포를 자동화합니다. 서비스를 독립적으로 배포하고 롤아웃 상태를 모니터링합니다.

  • 오류를 격리합니다. 복원력 전략을 사용하여 서비스 내의 오류가 연속되지 않도록 방지합니다. 자세한 내용은 복원력 패턴 및신뢰할 수 있는 애플리케이션 설계를 참조하세요.

  • 비정상 상황 엔지니어링을 사용하여 마이크로 서비스 아키텍처 및 종속성의 복원력을 테스트합니다. 시스템이 부분 오류를 처리하는 방법을 평가하고 개선합니다.

  • 중앙 집중식 로깅, 분산 추적(OpenTelemetry) 및 메트릭 컬렉션을 구현하여 관찰 가능성을 보장합니다.

마이크로 서비스에 대한 안티패턴

마이크로 서비스를 설계하고 구현할 때 이 아키텍처 스타일의 이점을 훼손할 수 있는 특정 문제가 자주 발생합니다. 이러한 안티패턴을 인식하면 팀이 비용이 많이 드는 실수를 방지하고 복원력 있고 유지 관리 가능한 시스템을 구축할 수 있습니다. 다음 안티패턴을 사용하지 마십시오.

  • 비즈니스 도메인에 대한 깊은 이해 없이 마이크로 서비스를 구현하면 서비스 경계가 제대로 조정되지 않으며 의도한 이점을 저해합니다.

  • 과거 또는 미래의 이벤트에 종속된 이벤트를 디자인하는 것은 원자성 및 자체 포함 메시징의 원칙을 위반합니다. 이 종속성은 소비자가 대기하도록 강제하고 시스템 안정성을 감소시킵니다.

  • 데이터베이스 엔터티를 이벤트로 사용하면 내부 서비스 세부 정보가 노출되고 올바른 비즈니스 의도를 전달하지 못하는 경우가 많으며, 이로 인해 긴밀하게 결합되고 명확하지 않은 통합이 발생합니다.

  • 모든 비용에서 데이터 중복을 방지하는 것은 안티패턴입니다. 구체화된 뷰와 같은 패턴을 사용하여 로컬 복사본을 유지 관리하면 서비스 자율성이 향상되고 서비스 간 종속성이 줄어듭니다.

  • 일반 이벤트를 사용하면 소비자가 메시지를 해석하고 필터링할 수 있습니다. 이 방법은 불필요한 복잡성을 더하고 이벤트 기반 통신의 명확성을 줄입니다.

  • 마이크로 서비스 간에 공통 라이브러리 또는 종속성을 공유하면 긴밀한 결합이 발생하므로 변경 내용이 위험하고 광범위하며 자체 포함 서비스의 원칙에 어긋나게 됩니다.

  • 마이크로 서비스를 소비자에게 직접 노출하면 긴밀한 결합, 확장성 문제 및 보안 위험이 발생합니다. API 게이트웨이를 사용하면 깨끗하고 관리 가능하며 안전한 진입점을 제공합니다.

  • 구성 값을 마이크로 서비스 내부에 유지하면 특정 환경과 긴밀하게 결합되어 배포가 더 어려워집니다. 그러나 구성을 외부화하면 유연성과 환경 이식성이 향상됩니다.

  • 마이크로 서비스 내에서 직접 토큰 유효성 검사와 같은 보안 논리를 포함하면 코드 및 유지 관리가 복잡합니다. 또는 전용 구성 요소에 대한 보안을 오프로드하면 서비스가 집중되고 더 깨끗해집니다.

  • 일반적인 마이크로 서비스 작업을 추상화하지 못하면 반복적이고 오류가 발생하기 쉬운 코드가 생성되고 유연성이 제한됩니다. 또는 Dapr과 같은 추상화 프레임워크를 사용하면 비즈니스 논리를 인프라 문제와 분리하여 개발을 간소화할 수 있습니다.

마이크로 서비스 아키텍처 빌드

다음 문서에서는 마이크로 서비스 아키텍처를 설계, 빌드 및 운영하기 위한 구조화된 접근 방식을 제공합니다.

도메인 분석 사용: 마이크로 서비스를 디자인할 때 일반적인 문제를 방지하려면 도메인 분석을 사용하여 마이크로 서비스 경계를 정의합니다. 다음 단계를 수행합니다.

  1. 도메인 분석을 사용하여 마이크로서비스 모델링.
  2. 전술적 DDD를 사용하여 마이크로서비스 설계.
  3. 마이크로서비스 경계 식별.

서비스 디자인: 마이크로 서비스에는 애플리케이션을 설계하고 빌드하는 데 분산되고 민첩한 접근 방식이 필요합니다. 자세한 내용은 마이크로 서비스 아키텍처 디자인을 참조하세요.

프로덕션 환경에서 작동: 마이크로 서비스 아키텍처는 배포되므로 배포 및 모니터링을 위한 강력한 작업이 있어야 합니다.