본문 바로가기
마이크로서비스

마이크로서비스 개발 패턴

by 이상한나라의개발자 2024. 9. 10.

핵심 마이크로서비스 개발 패턴은 마이크로서비스 구축에 대한 기본 사항을 다룬다. 아래는 마이크로서비스를 구축하면서 고려해야 할 중요 항목이다. 

 

마이크로서비스를 설계할 때 고려사항

 

  • 서비스 세분화 : 비즈니스 도메인을 마이크로서비스로 분해하여 각 서비스가 적정 수준의 책임을 갖도록 하는 방법은 어떤 것이 있을까? 서비스를 서로 다른 비즈니스 문제 도메인의 책임과 중첩될 정도로 지나치게 크게 나누면 시간이 지나 유지 관리하고 변경하기 어렵다. 반면 서비스를 너무 세분화 하면 애플리케이션 복잡성이 전반적으로 높아지고 데이터 저장소에 액세스하는 것 외에 다른 로직이 없는 멍청한 서비스로 전락한다. ( 자세한 내용은 다음에...)
  • 통신 프로토콜 : 개발자는 서비스와 어떻게 통신할까? 첫 번째 단계는 동기와 비동기 프로토콜중 어떤 것이 필요한지 정하는 것이다. 동기 프로토콜의 경우 XML, JSON, 쓰리프트 같은 바이너리 프로토콜을 사용하는 HTTP 기반 REST가 가장 일반적인 통신이다. 비동기 프로토콜의 경우 RabbitMQ, Kafka, 아마존 SQS 같은 메시지 브포커를 통해 일대일 또는 일대다 통신을 하는 AMQP(Advanced Message Queuing Protocol)가 가장 일반적인 프로토콜이다. 
  • 인터페이스 설계 : 개발자가 서비스를 호출할 때 사용될 실제 서비스 인터페이스를 설계하는 가장 좋은 방법은 어떤 것이 있을까? 서비스를 구조화할 것인가? 모범 사례는 어떤 것이 있을까? 
  • 서비스 구성 관리 : 클라우드에 있는 서로 다른 환경 간 마이크로서비스의 구성을 호환하려면 어떻게 구성을 관리해야 할까?
  • 서비스 간 이벤트 처리 : 서비스 간 하드코딩된 의존성을 최소화하고 애플리케이션의 탄력성을 높이고자 이벤트를 사용하여 서비스를 분리하는 방법은 무엇인가?

 

마이크로서비스 라우팅 패턴

마이크로서비스 라우팅 패턴은 마이크로서비스를 사용하려는 클라이언트 애플리케이션이 서비스 위치를 발견하고 서비스로 라우팅하는 방법에 관한 것이다. 클라우드 기반 애플리케이션에는 수백개의 마이크로서비스가 실행될 수 있다. 보안과 콘텐츠 정책을 시행하려면 서비스의 물리적 IP를 추상화하고 서비스를 호출하는 단일 진입점이 필요하다. 어떻게 해야 할까? 

  • 서비스 디스커버리 : 서비스 디스커버리와 그 핵심 기능인 서비스 레지스트리를 사용하면 마이크로서비스를 탐색 가능하여 클라이언트 애플리케이션은 서비스 위치를 하드코딩하지 않아도 서비스를 찾을 수 있다. 서비스 디스커버리는 주로 넷플릭스 유레카를 사용하지만 아파치 주키퍼 (Apache Zookeeper) 같은 서비스 레지스트리도 있다. 또한 일부 시스템의 경우에는 명시적으로 서비스 레지스트리가 없지만 이를 대신하여 서비스 메시(service mesh)로 알려진 서비스 간 통신 인프라스트럭처를 사용한다.

 

서비스 디스커버리와 서비스 라우팅

 

서비스 디스커버리와 서비스 라우팅은 모든 대규모 마이크로서비스 애플리케이션에서 핵심인 부분이다. 위 그림에서 서비스 디스커버리와 서비스 라우팅이 하드코딩된 이벤트 순서로 처리하는 것처럼 보이지만(서비스 라우팅을 거친 후 서비스 디스커버리에 전달), 두 패턴은 서로 종속되지 않는다. 예를 들어, 서비스 라우팅 없이도 서비스 디스커버리를 구현할 수 있고, 구현하기 더 어렵지만 서비스 디스커버리 없이도 서비스 라우팅을 구현할 수 있다.

 

마이크로서비스 클라이언트 회복성 패턴

마이크로서비스 아키텍처는 고도로 분산되어 있어 하나의 서비스의 문제가 연쇄적으로 서비스 소비자까지 전파되는 것을 막는데 매우 신중해야 한다. 이를 위해 네 가지 클라이언트 회복성 패턴이 존재한다.

 

  • 클라이언트 부하 분산 패턴 : 마이크로서비스의 여러 인스턴스에 대한 호출이 정상 인스턴스에 분산되도록 서비스 인스턴스 위치를 캐싱하는 방법이다.
  • 회로 차단기 패턴 : 실패 중이거나 성능 문제를 겪고 있는 서비스를 계속 호출하지 않도록 하는 방법이다. 서비스가 느려지면 클라이언트가 호출하는 자원을 오래 소비한다. 이러한 호출 클라이언트가 더 신속하게 반응하고 적절한 행동을 취하도록 마이크로서비스 호출을 빠르게 실패한다.
  • 폴백 패턴 : 마이크로서비스 호출이 실패할 때 호출되는 마이크로서비스가 아닌 다른 수단으로 서비스 클라이언트가 작업을 수행하도록 플러그인 매커니즘을 제공하는 방법이다.
  • 벌크헤드(격벽) 패턴 : 마이크로서비스 애플리케이션은 작업을 수행하는 데 많은 분산 자원을 사용한다. 이 패턴은 한 서비스와 오작동 호출이 애플리케이션의 다른 곳에 나쁜 영향을 미치지 않도록 호출을 격리하는 방법을 설명한다.

 

마이크로서비스를 사용하면 제대로 동작하지 않는 서비스로부터 서비스 호출자를 보호할 수 있고, 느리거나 다운된 서비스는 인접 서비스뿐 아니라 시스템을 붕괴시킬 수 있다.

 

마이크로서비스 보안 패턴

대중에게 마이크로서비스 노출을 피하려면 적절한 자격 증명을 가진 승인된 요청만 서비스를 호출할 수 있도록 다음 보안 패턴 아키텍처를 적용하는 것이 중요하다. 다음은 마이크로서비스를 보호할 수 있는 인증 서비스를 구축하는 세 가지 보안 패턴 구현 방법을 보여 준다.

 

  • 인증 : 서비스를 호출하는 서비스 클라이언트가 누구인지 확인하는 방법이다.
  • 인가(권한 부여) : 마이크로서비스를 호출하는 서비스 클라이언트가 수행하려는 행동에 대한 수행 자격 여부를 확인하는 방법
  • 자격 증명 관리와 전파 : 서비스 클라이언트가 한 트랜잭션에서 여러 서비스를 호출할 때 계속해서 자격 증명을 제시하지 않는 방법이다. 사용자를 인증 및 인가하고자 서비스 호출 간 전달되는 토큰을 발급받을 수 있는 OAuth2와 JWT 같은 토큰 기반의 보안 표준을 사용한다.

 

마이크로서비스 로깅과 추적 패턴

마이크로서비스 아키텍처의 단점은 간단한 동작 하나에 수많은 마이크로서비스 호출이 발생할 수 있기 때문에 문제를 디버깅하고 추적 및 모니터링하기가 휠씬 어렵다는 것이다. 이를 위해 스프링 클라우드 슬루스, 집킨, ELK 스택을 활용한 분산 추적 구현방법 적용해야 한다. 분산 추적을 달성하는 세 가지 핵심 로깅 및 추적 패턴을 보자

 

  • 로그 상관관계 : 사용자의 한 트랜잭션에 대해 여러 서비스에서 생성된 모든 로그를 함께 연결하려면 어떻게 해야 할까? 이 패턴을 상관관계 ID를 구현하는 방법을 알아야한다. 이 ID는 한 트랜잭션 내 고유 식별자로 모든 서비스 호출에 전달되고 서비스가 출력하는 로그 항목을 함께 연결하는 데 사용된다.
  • 로그 수집 : 이 패턴을 사용하여 마이크로서비스(모든 인스턴스)가 출력한 모든 로그의 질의(query) 가능한 단일 데이터베이스로 수집하고 트랜잭션 내 서비스 성능 특성을 이해할 수 있다.
  • 추적 : 트랜잭션과 관련된 모든 서비스 간 클라이언트 트랜잭션 흐름을 시각화 한다.

 

로깅과 추적 전략

 

 

애플리케이션 지표 패턴

애플리케이션 지표 패턴은 애플리케이션이 지표를 모니터링하는 방법과 애플리케이션의 가능한 실패 원인을 경고하는 방법을 다룬다. 이 패턴은 서비스의 잠재적인 성능 문제를 방지하고자 지표 서비스가 비즈니스와 연관된 데이터 수집(스크래핑), 저장, 질의하는 방법을 보여준다. 이 패턴은 다음 세 가지 주요 구성 요소가 포함된다.

  • 지표 : 애플리케이션 상태에 대해 중요한 정보를 생성하고 이 정보의 지표를 노출하는 방법이다.
  • 지표 서비스 : 애플리케이션 지표를 저장하고 질의하는 곳이다.
  • 지표 시각화 제품군 : 애플리케이션과 인프라스트럭처에 대해 비즈니스와 연관된 시계열 데이터를 시각화한다.

지표 모니터링은 마이크로서비스 아키텍처의 필수적이며, 마이크로서비스의 높은 분산성으로 인해 이러한 종류의 아키텍처에 대한 모니터링 요구 사항은 모놀리식 구조보다 더 높은 경향이 있음을 이해하는 것이 중요하다.

 

 

마이크로서비스 빌드/배포 패턴

마이크로서비스 아키텍처의 핵심 부분 중 하나는 한 마이크로서비스의 각 인스턴스가 모두 동일해야 한다는 것이다. 서버가 배포된 후 서버의 변경 사항으로 발생되는 구성 불일치는 애플리케이션의 안정성을 해칠 수 있어 발생을 막아야 한다.

 

이 패턴의 목표는 인프라스트럭처 구성을 빌드/배포 프로세스에 통합하여 자바 WAR이나 EAR 파일 등 소프트웨어 산출물을 이미 실행중인 인프라스트럭처에 더 이상 배포하지 않는 것이다. 그 대신 빌드 프로세스 일부로 수행 중인 마이크로서비스와 가상 서버 이미지를 빌드하고 컴파일한다. 그런 다음 마이크로서비스가 배포되면 서버에서 실행 중인 전체 머신 이미지가 배포된다. 아래는 전체 과정에 대한 요약이다.

  • 빌드 및 배포 파이프라인 : 조직의 모든 환경에서 원 버튼 클릭 빌드와 배포를 중시하는 반복적인 빌드 및 배포 프로세스를 구축하는 방법이다.
  • 코드형 인프라스트럭처 : 소스 제어로 실행되고 관리되는 서비스 프로비저닝 처리 방법이다.
  • 불변 서버 : 마이크로서비스 이미가 생성되고 배포된 후 절대 변경되지 않도록 하는 방법이다.
  • 피닉스 서버 : 개별 컨테이너를 실행하는 서버가 정기적으로 분해되어 불변 이미지로 재생성 되도록 하는 방법이다. 서버가 오래 될수록 구성 불일치 발생 가능성은 높아진다. 구성 불일치는 시스템 구성 정보에 대한 임의적 변경 사항이 기록되지 않을 때 발생한다.