비즈니스 민첩성

⇒ 사용자 피드백을 반영해 끊임없이 서비스를 개선

⇒ 아마존의 배포 속도 : 초당 1.5번 배포

⇒ Cloud 인프라의 등장

  • 전형적인 시스템 인프라 구축 과정을 보면 서버를 도입하고 네트워크를 구축한 뒤 각 서버마다 운영체제를 설치하고 서비스에 필요한 소프트웨어를 설치하는 과정으로 진행되고 전 과정을 완료하기까지 적게는 며칠에서 몇 주 길게는 몇 달이 걸리기도 한다.
    애플리케이션을 개발해서 배포하는데 인프라 환경을 준비하는 작업은 간단하지 않다.
    서비스가 실패로 끝나게 되면 초기 투입된 인프라 비용을 건질 수 없다.
  • 위와 같은 문제를 Cloud 인프라의 등장으로 해결
    적당한 Cloud 벤더를 선택해서 필요한 시점에 몇 번의 클릭으로 손쉽게 개발 시스템 인프라를 마련할 수 있다.
    스타트업은 참신한 서비스를 빠르게 선보여야 하기 때문에 Cloud 인프라 사용이 거의 필수적

⇒ Cloud 인프라에 어울리는 애플리케이션의 조건

  • 쇼핑몰처럼 특정 시점에 트래픽이 집중되는 애플리케이션 : 스케일업이나 스케일아웃 스케일 다운을 주기적으로 반복해야 하는 애플리케이션

  • 특정 서비스만 탄력성 있게 확장해야 하는 애플리케이션 - 마이크로서비스로 구현된 애플리케이션
    레고 블록처럼 애플리케이션을 개발하면 특정 모듈만 용량을 증설하고 트래픽에 반응해 복제되게 설정할 수 있다.
    시스템을 작은 단위의 독립적인 서비스 연계로 구성

    { 예시 : CQRS를 구현할 때 DB하나에 각각 구현이 아닌 DB도 따로 구현한다. }

⇒ CLoud Friendly와 Cloud Native

  • 작은 단위의 서비스 연계로 시스템을 구성하지 않고 전체 시스템으로 하나의 덩어리로 만들어 Cloud 인프라에 올려도 비즈니스를 제공하는데 문제가 없지만 특정 기능만 확장하거나 배포할 수 없는 비효율을 감수해야 한다.
  • 전체 시스템을 하나의 덩어리로 만들어서 Cloud 환경에 올라갈 수 있도록 만든 애플리케이션을 Cloud Friendly Application이라고 하고 독립적으로 분리되어 배포될 수 있는 애플리케이션을 Cloud Native Application이라고 한다.

⇒ Monolithic과 Micro Service

  • Monolithic
    하나의 단위로 개발되는 일체식 애플리케이션

    보통 3 Tier로 구성을 많이 하는데 사용자 인터페이스, 데이터베이스 그리고 서버 쪽 애플리케이션으로 나누어 개발
    서버 측 애플리케이션이 일체 즉 논리적인 단일체로서 아무리 작은 변화에도 새로운 버전으로 전체를 빌드해서 배포해야 하고 일체식 애플리케이션은 단일 프로세스에서 실행되기 때문에 확장이 필요한 경우 특정 기능만 확장할 수 없고 반드시 전체 애플리케이션을 동시에 확장해야 하는데 로드밸런서를 앞에 두고 여러 인스턴스 위에 큰 덩어리를 복제해 수평으로 확장

    변경이 발생하면 단점이 극대화 되는데 여러 개의 Monolithic 시스템이 수평으로 확장된 상태이므로 전부 다시 빌드하고 배포해야 하고 확장 시 애플리케이션이 병렬로 확장되어 사용량 증가에 대응할 수 있지만 데이터베이스는 통합되어 하나이므로 탄력적으로 대응할 수 없기 때문에 사전에 성능을 감당하기 위해서 스케일 업을 통해 용량을 증가시켜야 한다.

  • Microservice
    서버 측이 여러 개의 조각으로 구성되어서 각 서비스가 별개의 인스턴스로 로딩 되는데 여러 서비스 인스턴스가 모여 하나의 비즈니스 애플리케이션을 구성하고 각기 저장소가 다르므로 업무 단위로 모듈 경계를 명확하게 구분

    확장 시에는 특정 기능별로 독립적으로 학장할 수 있고 특정 서비스를 변경할 필요가 있으면 해당 서비스만 빌드해서 배포하면 된다.

    각 서비스가 독립적이어서 서로 다은 언어로 개발하는 것(Polyglot)도 가능하므로 각 서비스의 소유권을 분리해서 서로 다른 팀이 개발 및 운영할 수 있다.

Microservice

SOA와 Microservice

⇒ 소프트웨어 공학에서 말하는 모듈화의 개념의 발전 흐름을 보면 단순히 기능을 하향식 분해해서 설계해 나가는 구조적 방법론부터 객체 단위로 모듈화하는 객체 지향 방법론 그 다음에 모듈화의 단위가 기능 별로 재사용할 수 있는 좀 더 큰 컴포넌트가 되는 CBD(Component Based Develpoment) 그리고 컴포넌트를 모아서 비즈니스 적으로 의미있고 완결된 서비스 단위로 모듈화 하는 SOA(Service Oriented Architecture)로 이어지는 발전 과정을 거친다.

⇒ CBD와 SOA도 넓게 보면 단위 컴포넌트나 서비스를 구성해서 시스템을 만드는 개념이므로 Microservice 시스템의 구조와 유사

⇒ 넓게 보면 여러 개의 응집된 비즈니스 서비스의 집합으로 시스템을 개발한다는 점에서 SOA와 MSA는 개념적으로는 큰 차이가 없지만 SOA는 구체적이지 않고 이론적이며 실제 비즈니스 성공 사례가 많지 않았는데 MSA는 Cloud 인프라 기술의 발전과 접목되어 아마존과 넷플릭스와 같은 기업에서 구체화되고 비즈니스 성공 사례로 널리 공유되었는데 이상적이었던 SOA가 Cloud Infra의 등장으로 하드웨어를 유연하게 다룰 수 있게 되면서 비로소 실현되어 성공적으로 구현된 것이 MSA

⇒ 아마존과 넷플릭스로 이어진 비즈니스 성공 과정에서의 Microservice 정의

  • 여러 개의 작은 서비스 집합으로 개발하는 접근 방법
  • 각 서비스는 개별 프로세스에서 실행되고 HTTP 자원 API 같은 가벼운 수단을 사용해서 통신
  • 비즈니스 기능 단위로 구성되고 자동화 된 배포 방식을 이용해서 독립적으로 배포
  • 서비스에 대한 중앙 집중 관리는 최소화하고 각 서비스는 서로 다른 언어와 데이터 저장 기술을 사용할 수 있다.

⇒ CBD나 SOA가 미흡했던 저장소의 분리 등을 실현한 것이 MSA

  • 서비스 별 저장소를 분리해서 다른 서비스가 저장소를 직접 호출하지 못하도록 캡슐화 하는데 다른 서비스의 저장소에 접근하는 수단은 API 밖에 없다.
  • REST API 같은 가벼운 개방형 표준을 사용해서 각 서비스가 느슨하게 연계되고 누구나 쉽게 사용할 수 있다.

Microservice를 위한 조건

⇒ 조직의 변화 : 업무 기능 중심 팀

  • 업무 기능 중심 팀은 역할 또는 기술 별로 팀을 분리시키지 않고 업무 기능을 중심으로 기술이 다양한 사람들이 하나의 팀이 되어 서비스를 만드는 것
  • 이 팀은 같은 공간, 같은 시간을 공유하기 때문에 의사소통도 원활하고 의사 결정도 빠르게 진행될 수 있다.

⇒ 관리 체계의 변화 : 자율적인 분권 거버넌스, 폴리글랏

  • 아마존에서는 다기능 팀이 개발과 운영을 책임진다고 했는데 이러한 조직 문화를 you built it you run it 이라는 모토로 표현하는데 우리가 만들고 우리가 직접 운영한다라는 의미
  • 중앙의 강력한 거버넌스를 추구하지 않기 때문에 중앙의 강력한 표준이나 절차 준수를 강요하지 않는다.
  • 빠르게 서비스를 만드는 것을 최우선 목적으로 하고 스스로 효율적인 방법론과 도구, 기술을 찾아 적용
  • 자신의 서비스 성격에 맞는 최적의 언어와 저장소를 자율적으로 선택

⇒ 개발 생명 주기의 변화 : 프로젝트가 아니라 제품 중심

  • 기존 방식은 프로젝트 단위로 애플리케이션을 개발했기 때문에 필요한 기술을 사용하는 인력들이 한시적으로 모여 장기적으로 프로젝트를 통해 개발을 완료하고 나면 이를 운영 조직에 넘기는 방식으로 진행되어서 개발 조직과 운영 조직이 분리되어 있었다.
  • 초기에 모든 일정을 계획했는데 요구사항 정의를 통해 개발할 기능을 나열하고 이에 대한 설계를 진행하며 설계가 완료되면 개발이 진행되고 각 단계는 완료 데드라인이 있어서 그 일정을 완료함으로써 최종 기능을 제공하기 때문에 프로젝트 기간 중에 발생한 변경이나 새로운 아이디어를 포용하지 못했다.
  • 마이크로 서비스에서는 비즈니스의 갑작으러운 트렌드 변화에 유연하게 대처해야 하고 개발 뿐 아니라 운영을 포함한 소프트웨어의 전체 생명주기를 책임져야 하기 때문에 소프트웨어를 완성해야 할 기능들의 집합으로 보는 것이 아니라 비즈니스를 제공하는 제품으로 바라보고 개발한 뒤에 반응을 보고 개선하는 방식으로 소프트웨어를 개발
  • 소프트웨어를 개발하는 방식 측면에서 폭포수 모델 또는 빅뱅 방식으로 진행하는 것이 아니라 점진 반복적인 모델 제품 중심의 agile 개발 방식을 채용하는데 이 방식은 2~3주 단위의 Sprint를 통해 소프트웨어를 개발 및 배포해서 바로 피드백을 받아 소프트웨어에 반영할 수 있도록 해주기 때문에 소프트웨어를 한시적 프로젝트를 통해 고객의 고정된 요건을 받아 이 기능이 만족되면 제공 및 전달하는 개념으로 보지 않고 요건에 변화에 따라 지속적으로 개선되고 발전 시킬 제품으로 바라본다.
  • 계속 피드백을 받아서 지속적으로 변화하고 개선되고 향상되는 존재

⇒ 개발 환경의 변화 : 인프라 자동화

  • Microservice는 독립적으로 배포

  • Monolithic의 경우는 수동으로 배포하는 것도 크게 문제가 없지만 Microservice처럼 여러 개로 쪼개진 상태에서는 수동으로 배포하는 방식은 빠르게 배포하기 위한 방법이 필요

  • 전체 소프트웨어를 구현하는 과정은 개발 환경을 준비하는 과정, 실제로 소프트웨어를 개발하는 과정, 개발 완료된 소프트웨어를 빌드, 테스트, 배포하는 과정으로 구분

  • 첫 단계인 개발 환경을 준비하는 과정에서 Cloud 인프라를 활용하면 쉽고 빠르게 개발환경을 준비할 수 있어서 팀의 개발 속도가 높아진다.

  • 개발 지원 환경의 속도를 높이는 가장 좋은 방법은 자동화

  • 개발 지원 환경을 자동화하는데는 소스 코드를 빌드하는 도구와 빌드와 동시에 테스트하는 도구, 가상화된 인프라에 배포하는 도구

  • 이 같은 환경은 개발과 운영을 동시에 수행하는 DevOps를 궁극적으로 가능하게 하므로 데브옵스 개발환경이라 속칭하기도 하며 이러한 개발 환경, 지원 환경을 자동화하는 것을 통틀어 인프라 자동화라고 하기도 하는데 인프라 자동화는 Microservice 개발 과정의 필수 요건

  • 배포 파이프라인의 자동화
    컴파일, 유닛 테스트(빌드) → 기능 테스트(개발환경 배포) → 통합 테스트(테스트 환경 배포) → 인수 테스트(스테이징 환경 배포) → 운영환경에 배포

    소스코드 빌드 → 개발 환경 배포 → Staging(운영 환경과 거의 동일한 환경을 만들어 놓고 운영환경으로 이전하기 전에 Security, 성능, 장애 등의 비기능적 부분을 검증하는 환경) 배포 → 운영환경 배포

  • 빌드/배포 파이프라인 프로세스는 도구를 통해 자동화해야 하는데 최근에는 배포 환경이 Microservice 개수에 따라 급격하게 늘어나기 떄문에 이를 효율적으로 관리하기 위해 인프라 구성과 자동화를 마치 소프트웨어처럼 코드로 처리하는 방식인 Infrastructure as Code(IaC)가 각광받고 있다.

  • IaC란 코드를 이용해서 인프라 구성부터 애플리케이션 빌드, 배포를 정의하는 것을 의미하는데 이렇게 되면 수많은 하드웨어 리소스 설정을 동일하게 통제할 수 있으며 상황에 따른 검증되고 적절한 설정을 쉽게 복제하고 누구한테나 공유할 수 있게 돼서 인프라를 효율적으로 관리할 수 있다.

⇒ 저장소의 변화 : 통합 저장소가 아닌 분권 데이터 처리

  • 저장소를 여러 개 사용하게 되면 각 서비스에 담긴 데이터의 비즈니스 정합성을 맞춰야 하는 데이터 일관성 문제가 발생할 수 있다.

  • 데이터 일관성 처리를 위해서는 보통 2단계 커밋 같은 분산 트랜잭션 기법을이용하는데 각각 다른 서비스를 하나의 트랜잭션으로 묶다 보면 서비스의 독립성도 침해되고 NoSQL 저장소처럼 2단계 커밋을 지원하지 않는 경우도 있다.
    마이크로 서비스에서는 데이터 일관성 문제를 해결하기 위해서 비동기 이벤트 처리를 통한 협업을 강조하는데 이를 가리켜 결과적 일관성이라는 개념으로 표현하는데 두 서비스의 데이터가 일시적으로 불일치하는 시점에 있고 일관성이 없는 상태지만 결국에는 두 데이터가 같아진다는 개념

  • 여러 트랜잭션을 하나로 묶지 않고 별도의 로컬 트랜잭션으로 각각 수행하고 일관성이 달라진 부분은 체크해서 보상 트랜잭션으로 일관성을 맞추는 개념

  • 주문 서비스와 배송 서비스가 하나로 묶여야 하는 서비스를 개발
    { 여러개 들어와도 하나 실패하면 모든 것이 롤백되서 좋지 않다. 중간에 큐(메시지 큐)를 추가해서 실패한 동작만 삭제하게 바꾼다.(비동기)(kafka 사용) }

    주문 서비스가 주문 처리 트랜잭션을 수행
    주문 이벤트를 발행해서 주문 이벤트가 메시지 큐로 전송
    구독하고 있던 배송 서비스가 주문 이벤트를 인식

    배송 서비스가 주문 처리에 맞는 배송 처리 트랜잭션을 수행

    배송 처리 트랜잭션 중 오류로 트랜잭션을 실패
    배송 처리 실패 이벤트를 발행
    배송 처리 실패 이벤트가 메시지 큐로 전송
    주문 서비스가 배송 처리 실패 이벤트를 인식

    주문 서비스는 주문 취소(보상 트랜잭션)를 수행

⇒ 위기 대응 방식의 변화 : 실패를 고려한 설계

  • 소프트웨어는 언제든 실패할 수 있으며 실패해서 더는 진행할 수 없을 때도 자연스럽게 대응할 수 있도록 설계해야 한다는 의미로 이런 성질을 fault tolerance라고 한다.
  • 다양한 실패에 대비해서 완벽히 테스트 할 수 있는 환경을 마련해야 하고 시스템의 실패를 감지하기 위해 실시간 모니터링 체계도 갖춰야 한다.
  • 서킷 브레이커(circuit breaker) 패턴
    회로 차단기처럼 각 서비스를 모니터링하고 있다가 한 서비스가 다운되거나 실패하면 이를 호출하는 서비스의 연계를 차단하고 적절하게 대응하는 것을 의미
    서비스가 긴급 장애 상황에 빠르고 유연하고 탄력적으로 대응할 수 있게 한다.
  • 넷플릭스에는 카오스 몽키라는 장애를 일부러 발생시키는 도구를 만들어 이러한 탄력적인 아키텍쳐가 제대로 동작하는지 점검

MSA 이해

⇒ 리액티브 선언 : 현대 애플리케이션이 가져야 할 속성들

  • Responsive(응답성) : 사용자에게 신뢰성 있는 응답을 빠르고 적절하게 제공
  • Resilient(탄력성) : 장애가 발생하거나 부분적으로 고장나더라도 시스템 전체가 고장나지 않고 빠르게 복구하는 능령
  • Elastic(유연성) : 시스템 사용량에 변화가 있더라도 균일한 응답성을 제공하는 것을 의미하며 시스템 사용량에 따라 자원을 늘리거나 줄이는 능력
  • Message Driven(메시지 기반) : 비동기 메시지 전달을 통해 위치 투명성, 느슨한 결합, 논블로킹 통신(요청을 보냈다고 해서 결과가 올 때 까지 멈춰 서 있지 않는 통신)을 지향하는 것을 의미

⇒ 강결합 시스템에서 느슨한 결합의 아키텍처로 변환

  • 애플리케이션을 레이어 별로 분리
    애플리케이션 개발 - sping, jenkins, sonarqube 등
    오케스트레이션 - kubernetes
    런타임 - docker
    프로비저닝 - terraform

MSA 구성 요소

⇒ 인프라 구성 요소

  • public cloud, private cloud, 베어메탈(가상화 사용하지 않는 것)

  • VM와 Container

  • 컨테이너 오케스트레이션 : kubernetes

  • Backing Service : 데이터
    Persistence Store : RDBMS, NoSQL
    Cache : 데이터 캐시를 정의(redis)
    Message Broker : Queue 등을 이용해서 메시지 전달과 방법(RabbitMQ, Kafka)

  • Telemetry
    마이크로 서비스는 각 서비스들이 분리되어 있기 때문에 각 서비스 간의 로그를 한데 모아야 하는 이유, 각 서비스가 어떻게 호출 되는지 추적해야 하는 이슈, 각 서비스에 대한 모니터링 이슈가 있다.
    Telemetry는 이러한 Logging, Trace, Monitoring을 의미

    Logging : ELK, EFK
    Trace : sluth/zipkin
    Monitoring : prometheus/grafana

  • CI/CD : Nexus, Habor, Helm, Jekins, Git gradle, maven, JUnit 등을 사용

⇒ 플랫폼 패턴

  • 개발 지원 환경 : 데브옵스 인프라 구성

  • 빌드/배포 파이프라인 설계

  • 서비스 단일 진입을 위한 API Gateway 패턴

  • BFF 패턴(Backend For Frontend) 패턴 : Frontend 별로 서버를 별도로 두는 방식

  • 외부 구성 저장소 패턴 : 접속해야 하는 저장소의 설정 내용을 별도의 파일로 만들어서 보관

  • 인증/인가 패턴
    각 서비스가 모두 인증/인가를 중복으로 구현한다면 비효율적

    중앙 집중식 세션 관리
    Monolithic에서는 서버 세션에 사용자의 로그인 정보 및 권한 정보를 저장하고 이를 통해서 애플리케이션의 인증/인가를 판단했는데 마이크로 서비스는 수시로 수평 확장할 수 있고 로드밸런싱 처리가 되기 때문에 세션 데이터가 손실 될 수 있고 각 서비스에 세션을 전부 저장해야 하는 번거로움이 발생할 수 있기 때문에 각자의 서비스에 세션을 저장하지 않고 공유 저장소에 세션을 저장하고 모든 서비스가 동일한 사용자 데이터를 얻게 하는데 이 때 세션 저장소로 Redis나 Memcached를 사용

    클라이언트 토큰
    세션은 중앙 서버에 저장되고 토큰은 사용자의 브라우저에 저장되는데 토큰에 사용자의 신원 정보를 저장하고 있고 서버로 요청을 보낼 때 이 토큰 정보를 가지고 인가 처리를 하는데 JWT(Json Web Token)는 토큰 형식을 정의하고 암호화해서 다양한 언어에 라이브러리를 제공하는 공개 표준

    API Gateway를 이용한 클라이언트 토큰

    • 장애 및 실패 처리를 위한 서킷 브레이커 패턴
    • 모니터링과 추적 패턴
    • 중앙화 된 로그 집계 패턴
    • 서비스 매시 패턴 : Istio
profile
클라우드로 안정적이게, 자동화로 더 편하게 — 개발자 김준태입니다.

0개의 댓글