본문 바로가기

내 생각

클라우드 네이티브, 마이크로서비스 아키텍처(Cloud native MSA)

0. 잘못된 사용이 낳은 재난

몇 명의 경험이 부족한 개발자들이 대용량 서비스를 수용할 목적으로 쇼핑몰을 마이크로서비스로 만들었다. 하지만, 전체적인 마일스톤이나 설계가 없는 상태에서 개발을 진행하면서, 새로운 기능이 필요할 때마다 새로운 컨테이너로 만들고 새로운 데이터베이스를 만들어 쿠버네티스 클러스터에 배포하고 서비스의 안정성을 위해 많은 수의 ReplicaSet을 만들었다. 심지어, 구조에 대한 고민 없이 분리된 데이터베이스의 결과를 조합하는 컨테이너도 만들어 배포했다. 그 결과 수백 명밖에  사용하지 않는 서비스가 수백 개의 컨테이너와 수십 개의 노드를 사용해야만 하는 복잡한 시스템이 만들어졌고, 규모에 비해 엄청난 운영비와 많은 인력이 일하는 이상한 결과를 초래했다.

 

무엇이 문제일까?

 

원인을 파악하기에 앞서, 클라우드 기반 아키텍처의 설계 원칙을 살펴보자.

 

1. 클라우드 네이티브 아키텍처 (Cloud Native Architecture)

클라우드 플랫폼을 제공하는 회사마다 각각 다른 원칙을 제공하고 있지만, 3가지의 주요한 공통 원칙은 존재한다.

a. 자동화를 설계의 기본으로 삼는다.

자동화의 대상에는

  • 클라우드 인프라 자동화
  • CI/CD (Continuous Integration / Continuous Delivery)를 통한 개발/배포 자동화
  • 부하 분산(Load Balancing)과 오토스케일링 (Autoscaling)

이 모든 것을 처음부터 만족할 수는 없다면, 자동화를 할 수 없는 부분이 필요 없게 설계하는 것도 필요하다.

b. 가능하면 steteless

상태(state)에는

  • 사용자의 데이터와 같은 App내의 상태
  • App을 실행하는 미들웨어의 상태
  • 미들웨어가 실행되는 클라우드 인프라의 상태

가 있을 수가 있으며, 서비스를 운영하는 입장에서 가능하면 stateless, 피치 못한다면 상태(state)를 효과적으로 관리할 수 있어야 한다. stateless상태가 되면,

  • 스케일 업/다운(Scale up/down)이 쉽게 되며,
  • 쉽게 장애 복구가 가능하고,
  • 컴포넌트의 디플로이(deploy), 롤백(roll-back)이 쉽고,
  • 대용량 서비스를 위한 부하 분산이 쉬워진다.

백엔드 개발을 하면서 서비스를 최대한 stateless 하게 유지하려면, 설계 단계에서 많은 고민이 필요하다.

c. 끊임없는 변화, 진화

15년 전에 퍼블릭 클라우드 서비스를 만드는 회사에서 일할 때, AWS는 EC2, RDS, S3와 같은 비교적 단순한 서비스만을 제공했다. 하지만 지금은 쿠버네티스를 포함한 컨테이너 서비스, 서버리스 서비스와 수많은 매니지드 서비스가 같이 공존하고 있다. 인공지능 앱 개발만 해도, 현재는 구글이 만든 트랜스포머가 너무 강렬해서 변화가 정지된 것처럼 느껴지지만, 몇 년 전만 해도 매 해마다 새로운 딥러닝 모델과 백본이 만들어져서 해마다 새로운 라이브러리를 붙여야 할 판이었다. 그런데, 어떻게 몇 년 뒤를 예측해서 완벽하게 아키텍처를 설계하고 서비스를 개발할 수 있을까?

 

그래서, 현실에 충실한 아키텍처를 가져야 한다는 것이고, 대신, 미래에도 끊임없이 변화하려면, 끊임없이 설계를 변경하고, 끊임없이 아키텍처를 수정할 수 있어야 하고, 그에 따른 충격을 최소화할 수 있게 고민하는 것이 필요하다.

d. 그 외의 얘기들

이밖에도 클라우드 회사에서는 매니지드 서비스를 이용해서 보안을 포함한 관리 요소를 줄이고 수요에 능동적으로 대처하기를 권하고 있으며, 온프레미스가 아닌 점을 감안하여 여러 클라우드 보안 서비스를 이용해서 보안에 신경을 좀 더 쓸 것을 권했다. 반면, 소프트웨어 회사에서는 API 중심 설계를 권하고 있고, 한번 배포한 컴포넌트는 불변(immutable) 해야 하고, 마이크로서비스 아키텍처를 수용할 것을 권하고 있다.

 

다음으로, 마이크로서비스 아키텍처의 원칙에 대해 살펴보자.

 

2. 마이크로서비스 아키텍처 (MSA: Microservice Architecture)

마이크로서비스 아키텍처, MSA에 대해서도 회사마다 다른 원칙들을 내세우고 있지만, 공통적인 4가지 원칙이 존재한다.

a. 하나의 일을 위한 서비스

하나의 서비스는 하나의 일만 제공해야 한다. 예를 들어 카드 결제를 하는 서비스라면 카드 결제만을 처리해야 하고, 카드 결제를 위해 물건을 담는 카트기능은 가능하면 같은 서비스로 구현하지 말아야 한다는 것이다.

b. 의존적이지 않는 서비스

마이크로 서비스 간 의존성이 낮아야 한다. 예를 들어, 앞에서 언급한 카드 결제 서비스도 카트에 물건을 담을 때마다 카드결제 한도를 체크하여 사용자에게 알려주는 서비스라면, 서로 의존성이 너무 크기 때문에 카트와 카드 결제는 하나의 서비스로 만들 수 있을 것이다.

c. 분리가 가능한 구조

마이크로서비스는 개별적으로 배포가 가능한 구조여야 한다는 것을 의미한다. 이런 구조에는 리눅스나 도커의 컨테이너(Container), 웹어셈블리 바이너리(WebAssembly Binary), .NET DLL, 노드에서 하나의 패키지, 자바에서 하나의 JAR파일이 될 수도 있다. 또한 이 구조에 배포되는 소스코드도 분리되어야 하고 분리된 CI/CD 절차를 따를 것을 권하고 있다.

d. 가능하면 독립된 상태 머쉰

회사마다 각기 다른 용어로 이 부분을 정의하고 있지만, 내가 정리하기에는 하나의 마이크로서비스는 자신만의 상태(state)를 데이터베이스, 또는 독자적인 방법을 상태(state)를 유지할 수 있어야 한다. 이렇게 설계하면, 각 서비스는 다른 서비스에 영향을 받지 않고 온디멘드 스케일링이 가능하고 쉽게 장애 복구도 가능하다.

 

이 외에도 각 전문가, 회사마다 많은 원칙을 내세우고 있는데, Transportable, Failure ready, 등 많은 부분은 위의 4가지 원칙에 포함되지만, 한 번쯤은 다시 생각해 봐야 할 만한 원칙을 보면,

e. 하나의 서비스에 하나의 비즈니스

마이크로서비스들이 모두 모이면 회사에서 하는 모든 업무를 담당하지만, 하나의 마이크로서비스가 여러 개의 비스니스를 담당하지 않아야 하나의 마이크로서비스에 장애가 생겼을 때 회사의 비즈니스 영향도가 최소화된다.

f. 자동화

마이크로서비스 아키텍처, MSA가 되면, 전체 비즈니스에 필요한 수많은 서비스들이 존재하고, 이 많은 서비스들을 수작업으로 배포하고 운영한다는 것은 비효율적인 일이 되고, 많은 비용이 발생한다.

g. 모니터링

모니터링은 어디에서나 꼭 필요한 요소이다. 개발을 위한 모니터링도 필요하고 디멘드 자동화를 위한 모니터링도 필요하고, 무엇보다 서비스 안정성을 위한 장애 모니터링이 필요하다. MSA에 있는 많은 서비스가 효율적으로 운영되기 위해서는 체계화된 모니터링 방법이 필요하다.

h. CQRS (Common Query Responsibility Segregation)

이건 아마도 RDB를 많이 고민하는 전문가들이 만들어낸 원칙으로 보이는데, read와 write를 분리하자는 것이 내용이다. 이론상으로는 write가 read보다 많은 cost가 필요한 것은 맞지만, 이것을 해결하는 다른 많은 방법도 있기에 앞에서 언급했듯이 현시점에 필요한지 설계하면서 결정해야 할 것으로 보인다.

 

이외에도 많은 원칙을 제시하고 있는데, 일부는 또 개발을 잘하는 방법과도 겹치는 부분이 있는 것 같아 생략하기로 한다.

 

3. 무엇이 문제일까?

대학에서 프로그램을 처음 배우면, 정렬(Sorting) 알고리즘에 대해 배운다. 그리고 무엇이 빠른지에 대해 논한다.

 

Selection, Bubble, Insert, Shell, Quick, Merge, Heap, Tree, Timsort, Bucket, Radix, Cubesort,...

 

만일, 회사의 새로운 프로젝트가 새로운 개발환경을 사용하는데 이 환경에 정렬알고리즘 라이브러리가 없어 개발해야 한다는 요구가 생겼다고 가정하자. 덧붙여서 개발은 빠른 시간 내에 이루어져야 하고 업무에 효율적인 정렬알고리즘으로 만들어야 한다는 요구도 있다. 자주 프로젝트를 접한 개발자라면 빠르게 결정할 수 있겠지만, 사실 어떻게 개발할 것인가에 대한 답은 생각보다 단순하지 않다.

 

정렬을 할 데이터의 크기는?, 데이터의 성격은?, 데이터의 정렬정도는?, 처리하는 컴퓨터의 성능은?, 메모리 용량은?, 프로젝트에서 알고리즘을 개발하는 데 사용할 수 있는 시간은?, 개발자의 능력은?,...

 

이 글의 처음에 제시한 문제도 과연 클라우드 네이티브이면서 마이크로서비스 아키텍처 기반으로 개발을 해야 했는지, 또 전문가들이 제시하는 원칙을 무모하게 지키면서 만들어야 했는지 생각할 필요가 있다. 경험이 많지 않은 개발자들은 인터넷에 있는 많은 원칙들을 준수하려고 많은 시간과 인력, 비용을 사용했을 것이지만, 이것조차 우선순위도 이유도 모른채 적용했다면 개발 속도는 많이 느려졌을 것이고, 운영 노하우가 없으니 필요이상으로 많은 자원을 만들어 많은 비용을 지출했을 것이고, 간단하게 처리할 수 있는 서비스는 무척 복잡하게 만들어 졌을 것이다.

 

클라우드 네이티브 MSA의 많은 원칙들은 궁극적으로는 실리콘 밸리의 성공적인 스타트업을 대상으로 서비스하는 클라우드 플랫폼 기업들이 만들어 왔다. 실리콘밸리의 성공적인 스타트 기업을 짐작해 볼 수 있는 몇 가지 정보를 보면...

  • 6년 전에 실리콘밸리에서 만난 성공한 스타트업인 LinkedIn의 직원이 알려준 회사의 개발자 수는 만 명이 넘었다.
  • 8년 전에 만난 실리콘밸리의 클라우드 회사가 고객사를 위해 개발하는 대용량 트래픽용 API목표는 10T / sec였다.

스타트업이 클라우드를 이용해야 하는 궁극적인 이유는 지금 당장은 적은 비용으로 개발하고 서비스를 오픈하더라도 비즈니스가 요구하면 언제든 클라우드 기술을 사용해서 인프라를 확장할 수 있기 때문이다. 이런 요구사항을 충족시키기 위해 클라우드와 클라우드 네이티브 MSA와 같은 기술이 끊임없이 진화하고 있다.

 

오늘 우리가 개발하고 있는 시스템이 위의 모든 원칙을 준수하는 클라우드 네이티브 MSA 기반으로 개발해야 할지 생각해 본다.

 

스타업인 우리 회사 서비스의 올해 KPI는 무엇일까?