(SDS 사내 기고) Microservices Architecture 란?

Microservices Architecture

모놀리틱 아키텍쳐(Monolithic Architecture)

우리가 전통적으로 SI나 솔루션을 개발하던 모습은 모든 기능을 패키지 단위로만 구분해서
하나의 프로젝트에 넣어서 관리하는 것이었습니다. 심지어 모든 개발팀이 공유해서 말이죠.
그리고 이 프로젝트 구성을 보면 뛰어난 SA들이 전체 구조를 잡고, 모든 기술 스택을 정하고, 개발 표준을 잡아둡니다.
개발자들은 이 틀 안에서 개발가이드대로 업무 로직만 작성하면 되는 것이죠. 원하는 기술을 마음대로 적용할 수 없는 것이죠..

다른 팀의 서비스나 데이터가 필요하면 어떻게 했나요?
아마도 바로 클래스 참조를 하거나 DB Table을 Join 해서 처리 했을 겁니다.
이 방식으로 개발하면 모든 서비스마다 같은 기술, 같은 환경을 사용하기 때문에
유지보수도 쉽고 테스트하기도 쉽고 배포도 쉬운 장점이 있습니다.

모놀리틱 아키텍쳐의 문제점

하지만, 소프트웨어는 시간이 지날수록 변경이 생기게 되어 있고,
규모가 점차 커지고 사용자가 많아지다 보면 문제가 생기게 됩니다.
이런 구조에서 다른 팀에서 오류 난 소스를 커밋하는 바람에 Jenkins 빌드가 안돼서
내가 수정한 소스가 반영이 안된 경험이 많이 있었죠.
(이문제로 프로젝트 내에 빌드관리자라는 특이한 역할자를 두기도 하죠..)

그 외에도 클래스를 직접 참조하다 보니 서비스간 의존성이 높아져서 수정하기 어려워지고,
서비스가 커질수록 빌드, 배포하는 시간이 오래 걸리는 등의 문제가 생기게 됩니다.
그리고 특정 서비스에 부하가 생겨서 해당 서비스의 인스턴스만 늘리고 싶더라도
모든 서비스가 하나의 WAS로 배포되기 때문에 전체 서비스를 함께 늘리는 방법 밖에 없습니다.

즉, 이런 방식은 프로젝트 관리는 용이 하지만 변화를 수용하는 것이 어려운 모델인 것입니다.
사람들은 이런 방식을 모놀리틱 아키텍처(Monolithic Architecture)라고 부릅니다.

우리가 만든 서비스를 사용하는 사용자는 점점 글로벌 해지고,
클라이언트 종류는 웹, 모바일 뿐만 아니라 수많은 센서로까지 확장되고 있습니다.
이처럼 다양한 사용자 및 클라이언트가 보내는 요청에 대해 서비스가 잘 반응해야 됩니다.
잘 반응해야 된다는 말을 다시 풀어보면, 요구사항 변경에 대해 빠르게 대처 할 수 있어야 되고,
요청 량에 따라서 서비스 별로 스케일 인/아웃이 되는 등
시스템이 변화를 수용 할 수 있는 구조여야 된다는 말입니다.
모놀리틱 아키텍처만으로는 한계가 있는 시대가 된 것이죠.

마이크로서비스 아키텍처(Micoservices Architecture)

그래서 새롭지만 새롭지 않은 마이크로서비스 아키텍처라는 용어가 나오게 되었습니다.
기존 CBD나 SOA를 접해본 사람이라면 새롭지 않을 것이고, 그렇지 않은 사람은 새로운 개념 일 것입니다.
서비스가 독립적으로 수행되고 재사용 가능해야 된다는 기본적인 사상아래
좀 더 대용량, 대규모 개발에 맞도록 경량화되고 변형된 아키텍처로 볼 수 있습니다.
그래도 말이 참 어렵고 잘 와 닿지가 안죠?

마이크로 서비스 아키텍처는 옆의 그림처럼 서비스는 각각 다른 WAS로 배포되고 DB도 분리되어 있습니다.
즉, 다른 서비스에 영향을 받지 않고 WAS 인스턴스를 늘리고 줄이거나 다른 서비스로 대체할 수 있는 것이지요.
각 서비스들은 자신이 가진 기능들을 REST API로 노출 시킵니다.
클라이언트나 다른 서비스들과는 정의된 API를 보고 통신을 할 뿐,
내부적으로 어떻게 구현되고, 어떻게 변경되든 신경을 쓰지 않아도 됩니다.
클래스를 직접 참조하거나 테이블 조인을 하고 있었다면 변경에 대응하기 쉽지 않았겠죠.

마이크로서비스 아키텍처의 장점

이처럼 마이크로서비스 아키텍처는 많은 장점을 가지고 있습니다.
서비스단위로 작게 개발되기 때문에 빌드 및 배포시간이 상대적으로 짧습니다.
서비스 별로 독립적으로 내렸다 올릴 수 있고, 요청 량에 따라 인스턴스를 늘리고 줄이기도 쉽습니다.
또한 서비스 별로 적절한 기술 스택을 선택할 수 있죠.
예를 들면 파일 관리하는 서비스라면 Java보다는 node.js 같은 기술을 사용하는 것이 좋을 것이고,
로그를 관리하는 서비스라면 RDBMS보다는 NoSQL DB를 사용하는 것이 좋겠죠.

마이크로서비스 아키텍처의 담점

반면에 단점 또한 존재합니다.
무엇보다 분산환경을 구성해야 되기 때문에 복잡합니다.
트랜잭션을 구현하는 것도 매우 어렵고, 서비스마다 다른 기술을 사용하기 때문에 운영관점에서 힘든 점도 많이 있죠.
그리고 서비스 별로 중복되는 라이브러리도 존재하고,
WAS도 여러 개 뜨다 보니 CPU나 메모리 같은 자원의 오버헤드도 존재합니다.
따라서 MSA는 상황에 맞게 장단점을 잘 고려해서 도입하는 것이 중요합니다.

마이크로서비스 아키텍처의 구현 기술

이제 실제 구현관점에서 패턴이나 관련 기술 대해 간략히 소개해 보겠습니다.
크리스 리차드슨의 블로그(http://microservices.io) 에 잘 정리 되어 있으니 한번 들어가보면 좋을 것 같습니다.
GitHub(https://github.com/cer) 를 통해 소스코드도 공유하고 있으니 같이 보면 좋을 것 같습니다.
MSA를 구현관점에서 고민한 흔적이 많이 보입니다.

각 서비스 별로 독립적인 WAS로 구동되어야 하기 때문에 JVM 기반이라면 Spring Boot 사용을 추천하고 있고,
DB처리를 위해서는 JPA기술을 사용 하고 있는 것을 볼 수 있습니다.
그리고 각 서비스가 사용하는 주소(IP, Port)는 주로 동적으로 할당 되기 때문에
서비스를 등록 관리하기 위한 Service Discovery 패턴도 소개하고 있습니다.
Spring Cloud의 Netflix OSS 중 유레카(Eureka)를 사용하면 쉽게 서비스를 관리 할 수 있습니다.

그리고 서비스 별로 다른 주소를 가지고 있기 때문에 클라이언트 입장에서 API를 호출하는 것이 쉽지 않습니다.
그래서 단일 엔드포인트를 제공하기 위해 다음 그림과 같은 API Gateway 패턴도 사용합니다.
WSO2 APIM이나 Netflix Zuul 등 오픈소스 API Gateway가 많이 있으니 잘 선택해서 사용 하면 될 것 같습니다.
배포 관점에서는 도커를 활용해서 서비스를 컨테이너화 해서 쉽게 배포하는 것도 좋은 방법일 것 같습니다.

지금까지 MSA에 대해서 짧게 나마 알아봤습니다.
사실 아키텍처라는 것이 개발자 입장에서는 크게 와 닿지 않는 분야지만 워낙 이슈가 되고 있는 개념이라 소개해봤습니다.
개발자 관점에서 바라보면 마이크로 서비스는 SOLID 원칙과 많이 닮아있습니다.
결국 적절한 책임에 따라 나누고 인터페이스(API)를 통해 서로 통신하라는 것입니다.
이를 통해 변경에 적절히 대처 할 수 있는 것이고요.

크리스가 강의 중에 서비스를 나누기 위한 Boundary Context나
데이터 관리를 위한 Eventually Consistent 등 강조한 개념이 많이 있는데,
지면상 급하게 마무리 해버린 것 같아 아쉬움이 남네요.
아래 링크를 통해 추가적인 내용을 보면 좋을 것 같습니다.
(Microservices Reading List : http://www.mattstine.com/microservices)

Share