몇 년 전부터 떠오르기 시작한 소프트웨어 아키텍쳐이다. FullName은 MicroServiceArchitecture인데 단어 그대로 작은 서비스 단위의 설계다. 이 아키텍쳐가 유명해진 이유를 설명하려면 MonolithicArchitecture나 ServiceOrientedArchitecture 내용을 빠뜨릴 수 없다.
Mono라는 어원은 한 개 라는 의미가 있다. 즉, 서버를 하나로 돌린다는 이야기다. 그렇기에 MSA와 완전히 대비되는 모습이 있다. 두 아키텍쳐의 차이는 지향점부터 설계방식까지 정말 많이 다르다. MSA는 서비스의 분리를 굉장히 독립적으로 해둔 것이고, 모놀리식은 하나의 서버 안에 모든 기능이 들어간 것이다. 아래의 그림을 보면 조금 더 이해가 쉽다.
위 그림과 같은데, 실제 SSR 방식 프로젝트 개발 경험을 떠올려 보면, 장바구니 Service, 유저 인증인가 Filter, 유저 Service 등과 같은 방식으로 클래스, 패키지를 분리하여 개발했다면 MSA는 이러한 것들을 다 개별적 서버로 개발하는 것이다. 그렇게 각가의 독립적인 DB, Server 등을 가지고 있는 것이 MSA를 가장 간단히 설명한 것이다.
모놀리식
1. 개발이 빠르다. 이미 십 수년간 발달해온 기술이기 때문에 설계 패러다임이 많을 뿐더러 간단하다.
2. 한 서비스가 다운되면, 모든 서비스가 먹통이 될 수 있다.
3. 사용할 기술의 폭이 비교적 넓지 않다.
4. 트랜잭션 관리가 비교적 쉽다.
MSA
1. 서비스들 간의 통신 구축, 독립적 DB관리, 트란잭션 관리 등 고려사항이 많다.
2. 독립적으로 구성되어 예를 들자면 회원가입 서버가 막혀도 다른 기능은 모두 정상작동한다.
3. 사용할 기술의 폭이 넓다 서비스에 따라 다른 프레임워크 및 언어를 사용할 수도 있.
4. scale-out에 좋다. 예를 들어 모놀리식의 경우 결제 트래픽이 폭발하면, 모든 기능을 가진 서버 자체를 늘려야하지만, MSA의 경우 결제 시스템 서버만 늘리면 된다.
5. 독립적 개발 및 배포에 용이하다. 물론 부서간 소통은 필수이지만 팀별로 각각의 서비스를 개발 및 배포하기 용이하다.
정리하자면, 독립적으로 만듬으로써 각각 개별적으로 유지보수 및 개발 배포가 쉬워지고, 트래픽에 대응하기도 편하다는 것이다. 학습 곡선은 높지만 서비스별로 트래픽의 정도가 다르고, 개발속도가 다르다면 써야하는 아키텍쳐이다.
모놀리식의 경우 서버로 클라이언트가 직접 요청을 하지만, MSA는 클라이언트가 APIGATEWAY로 요청을 보낸다. 이 앞에는 로드밸런서가 생길 수도 있고, 다른 부가적인 설정들이 많이 필요하다. 어쨌든 대략적으로 보면 API-GATEWAY는 우리 서비스의 많은 서버에 대한 uri를 가지고있다. 그래서 요청이 들어왔을 때, 인증이 필요하면 인증서버, 장바구니가 필요하면 장바구니 서버로 요청을 보내게끔 해준다.
유저가 요청을 보내는건 위에서 이야기한 것처럼 APIGATEWAY로 요청이 가고, APIGATEWAY는 해당 요청을 서버로 보낸다고 했다. 돌아가서 MSA를 설계할 때 우리가 아무리 독립적으로 만들었어도 완전히 분리될 수 있을까?
온라인서점의 서비스
우리는 결제 시스템, 상품 관리 시스템을 분리했다. 각각 독립적으로 돌아가고 있다.
그럼 누군가 책 한 권을 결제 시스템을 통해서 샀을 때, 해당 책의 재고를 감소시켜야한다.
비행기 예약 서비스
비행기 예약을 비행기 좌석 조회와 예약 시스템이 나눠져 있다고 생각해본다.
그럼 우리가 예약을 했을 때 해당 좌석이 조회되면 안되지 않을까?
앞서 말했듯 MSA는 서비스별로 대개 서로 다른 DB를 사용한다. 그렇기에 우리는 서버간 통신이 필요하다. 예전 같았으면, 결제 비즈니스 로직 내부에 상품관리 관련 로직도 포함시켜 해결했을 수 있지만 MSA는 그렇지 않다.
그리고 해당 서버가 1:1로 연결된 관계가 아니다. 거의 1:N관계로 연결되어 있기 때문에 동기적 통신인 http프로토콜 사용도 조금 적절치 않을 수 있다. 그래서 Kafka와 RabitMQ 등 비동기적 이벤트큐와 같은 이벤트 기반 통신을 사용하게 됐다.
이벤트 기반 통신은 비동기적 처리를 말한다. 반대로 http통신은 동기적 처리인데 클라이언트가 응답을 기다려야한다. 하지만 이벤트 기반 통신은 응답을 기다리지 않고 일단 요청을 보내면 내부적으로 알아서 처리하고 응답을 보낸다. 그 사이에 클라이언트는 다른 일을 할 수 있다. 이때 사용하는게 메시지브로커라는 것이다.
KAFKA,RABBITMQ들이 모두 이벤트 기반 아키텍쳐에서 비동기적인 통신을 지원한다. 프로듀서와 컨슈머 간의 안정적인 메시지 전달을 보장하기 때문에 MSA 아키텍쳐에서 많이 사용된다.
메시지 브로커 모델 ( IBM 발췌 )
포인트-투-포이늩 메시징
메시지의 송신자와 수신자가 일대일 관계인 메시지 큐에서 사용되는 배포패턴이다. 큐의 각 메시지는 하나의 수신자에게만 전송되며, 오직 한 번만 이용된다. 메시지가 단 한 번만 실행되어야 하는 경우에 호출된된다. 이 메시징 스타일의 적합한 사용 사례로는 급여 및 재무 트랜잭션 처리를 들 수 있다. 이러한 시스템에서는 송신자와 수신자 모두 각 지불이 오직 한 번만 전송될 것이라는 보장이 필요하다.
발행/구독 메시징
이 메시지 배포 패턴에서 각 메시지의 생성자는 이를 토픽에 발행하고, 다수의 메시지 이용자는 메시지를 수신하고 싶은 토픽을 구독합니다. 어떤 토픽에 대해 발행된 모든 메시지는 이를 구독한 모든 애플리케이션에 배포됩니다. 즉, 메시지의 발행자와 이용자 사이에 일대다 관계가 형성되는 스타일의 배포 방법입니다.
이런 메시지 브로커를 이용한 통신 방식은 흔히 REST-API에서 사용하는 http프로토콜 기반 통신과는 확연히 다른 느낌이다. 이건 MSA아키텍쳐 특정상 자연스러운 일이다.
위에는 뭉뚱그려 설명해서 다시 추가하는 내용이다. 메세지 브로커를 통해 이 설계가 얻는 장점은 비동기 통신, 느슨한 결합, 확장성 등이 있다.
각 서버가 자신의 일만 딱딱 처리하게 해주는 장치인 셈이다. 이런 메세지 브로커가 없이 http 프로토콜로 서버간 통신을 하면 유저가 상품을 구매했을 때 결제 서버는 일을 끝냈는데도 재고관리 서버도 일을 끝내기를 기다려야 되는 것이다. 그래야 응답을 보낼 수 있으니 말이다.
이번 포스팅은 MSA의 통신 방식을 중점적으로 작성해봤다. 그닥 무겁고 세세한 내용은 없이 클라이언트의 요청부터 시작해서, 서버의 통신까지 어떻게 이뤄지는지 대략적인 개념들만 이야기 했다. 사실 상세히 들어가면 배포 운영 단계도 중요하고, CI/CD도 있겠지만 그 내용은 차차 정리하도록 하겠다. 일단 큰 그림은 그렸으니 다음에는 APIGATEWAY에 대해 조금 더 자세히 그리고 그 주변 것들에 대해 포스팅 하겠다.