오늘은 Cloud Native의 중요한 요소 중 하나인 Microservice Architecture에 대해 알아보겠습니다
핵심 용어
Microservice
Service
Monolithic
Microservice라는 건 마이크로 하게 작은 서비스를 의미하는 것 같죠
서비스라는 것을 한번 생각해봅시다
흔히 우리가 하는 개발은
앱을 통해 사용자들에게 어떤 '서비스'를 제공하기 위해서입니다
간단한 예로 보자면
- 카카오톡 : 메신저 서비스
- 인스타그램 : SNS 서비스
- 스노우 : 카메라 필터 & 편집 서비스
- 각종 은행 : 금융 서비스
초창기의 어플들은 한두 가지의 서비스를 목표로 개발되었으나
점차 사용자가 많아지면서 몸집이 많이 커지고 더 다양한 서비스를 제공하고 있죠?
즉, 서비스는 사용자에게 제공하는 어떤 기능의 집합이라 생각할수 있습니다
일반적으로 서비스가 기능보다 더 포괄적인 개념인 것이죠
하지만 실제로 서비스란 단어는 그보다 유연하게 받아들여지고 있습니다
여러 기능을 포괄하는 카테고리(금융)의 의미가 될 수도 있고,
한 가지 기능(계좌 조회)을 의미할 수도 있죠
어떻게 묶느냐 따라 달라지는 마법의 단어입니다
작은 서비스가 모여 큰 서비스를 이룰 수도 있겠죠!
금융 서비스는 여러 서비스 [입출금 서비스, 계좌조회 서비스]의 집합이라고도 할 수 있습니다
아하! 그렇다면 마이크로 한 서비스들이 협업하여 하나의 큰 서비스를 이룰 수 있겠네요!
소프트웨어는 어떻게 구현되어 왔을까요?
기존(옛날)에는 Monolithic Architecture 방식으로 구현했습니다
단어 그대로 하나의 덩어리로 이루어진 프로그램이 만들어집니다
(우리가 일반적으로 개발한 프로그램을 생각해봅시다ㅎ)
개발자들이 이런저런 이유로 설계하면서
내부적으로 모듈 등의 단위로 기능이 나눠져 있지만
하나의 앱에서 전체 기능이 동작합니다
위와 같이 모놀리식 아키텍쳐 방식은 여러 기능을 수행하는 하나의 앱입니다
모듈(기능)들은 서로 밀접한 관계를 갖고 있어 확장성을 가지기에 적합하진 않아요
확장성 : 소프트웨어의 3가지 중요 요소 중 하나
/*
소프트웨어를 개발하는데 3가지의 중요 요소가 있으며 이를 지키고 더 향상하기 위해 항상 노력합니다
요약
- 신뢰성 : 소프트웨어가 믿을 수 있게 동작하는가?
- 확장성 : 추가 기능 구현이나 리소스의 확장이 유연한가?
- 유지보수성 : 소프트웨어의 결함이 발견된 경우, 어렵지 않게 변경이 가능한가?
(사실 꽤 많은 얘기가 있는 내용이지만 간단히...)
개발자들은 항상 이 세 가지에 대해 깊은 고찰을 하며 소프트웨어를 설계합니다
*/
이게 무슨 말이냐!
예를 들면 위의 구조에서 다른 서버와 합병을 위해 새로운 DB를 추가한다고 생각해봅시다
모놀리식에선 결코 쉬운 작업이 아닙니다
- DB와 Data Interface에 어떻게 추가될 거고
- Business Layer는 어떻게 여러 Data Interface와 연동할 거고
- 여러 DB 중 언제 어느 DB에 접근할 거고
고민해야 할 부분이 많죠
또한, 어느 기능에 문제가 발생하면
소프트웨어 전체에 치명적인 문제로 이어져 서비스가 완전히 정지될 수 있으며(가용성 실패)
어떤 기능을 수정하면 전체를 빌드 & 배포를 다시 해야 하는 등의 어려움도 있습니다(유지보수 어려움)
확장성은 개발자들에게 굉장히 중요한 사항이지만
이는 설계부터 잘 고려하여 잘 짜지 않으면 굉장히 어려운 과제 중 하나였습니다
이러한 문제를 문제를 해결하기 위해 Microservice Architecture라는 개념이 사용됩니다
(드디어)
큰 덩어리였던 소프트웨어의 기능 덩어리들을
마이크로 서비스라고 하는 작은 서비스 단위로 나누는 것이죠
각 마이크로 서비스는 별도의 앱으로 구성됩니다
아래와 같은 그림으로 비교할 수 있겠습니다
왼쪽의 하나의 큰 앱이었던 모놀리식 아키텍쳐가
오른쪽의 작은 단위의 앱들로 나뉘어 마이크로서비스 아키텍쳐로 구성됩니다
별도의 앱들이 협동하여 하나의 큰 서비스를 수행하는 것이죠
각 기능이 확연히 나누어져 있습니다
별거 아닌 거 같아 보이지만 이렇게 함으로써
설계 및 개발 속도가 굉장히 빨라지며
기존과 확연히 다른 개발 특징을 갖게 됩니다
마이크로 서비스의 장점
1. UI 담당, DB 담당, 기능 A 담당, 기능 B 담당, 등등 자신만의 기능을 완전히 분리하여 개발 및 설계 가능
2. 중간에 새로운 개발자가 들어와도 전체를 이해할 필요 없이 담당 부분의 서비스만 이해해도 개발에 빠르게 참여 가능
3. 각 기능별로 소프트웨어를 이해하기 쉬우며 많은 협업자 간의 업무 분할이 쉬움
4. 각 마이크로서비스는 별도의 앱이기 때문에 해당 부분이 변경되면 해당 부분만 빌드 & 배포가 가능하여 속도 향상
5. 서비스의 증설, 새로운 서비스 추가, 하드웨어 추가 등이 쉬움
6. 서비스마다 적합한 별도의 언어나 시스템으로 구성이 가능
7. 특정 서비스에 문제가 생겨도 전체 서비스에 치명적인 영향이 미치지 않음
서비스 간의 의존도가 줄어드니(Loose-coupled) 더 유연하게 확장할 수 있어진 거죠
Tight Coupling VS Loose Coupling
/*
Tight Coupling
- 긴밀한 결합
- 결합된 오브젝트 간에 많은 정보를 공유
- 두 객체의 구현이 서로 연관되어 의존도가 강함
- 즉, 하나의 객체를 변경하면 다른 객체에도 변경할 것이 많음
Loose Coupling
- 느슨한 결합
- 하나의 컴포넌트의 변경이 다른 컴포넌트에 미치는 영향을 최소화하는 게 목표
- 일반적으로 Interface 구조를 사용하므로 구현이 아닌 Interface에 맞춤 -> 연관된 컴포넌트 간에 의존도가 낮음
- 시스템의 안정도와 유연성을 증가
*/
와! 장점이 엄청 많은 것 같죠
그럼 이제 모든 개발은 마이크로서비스의 멋진 개념을 따라 이루어지면 될까요?
(놉. 항상 모든 선택엔 트레이드오프가 있습니다)
마이크로서비스 아키텍쳐가 항상 모놀리식 아키텍쳐보다 좋은 것은 아닙니다
모놀리식 아키텍쳐의 장점도 있죠
1. 설계와 구현이 단순하여 작고 간단한 소프트웨어를 개발하는데 유리
2. 참여한 모든 개발자들이 해당 소프트웨어의 전체 흐름을 이해하고 있음
3. 하나의 앱이기 때문에 디버그하기 쉬움
4. 하나의 앱이기 때문에 테스트하기 쉬움
5. 하나의 앱이기 때문에 빌드 & 배포 과정이 단순함
즉, 확장할 필요가 없고, 간단한 소프트웨어인 경우 더 유리한 것이겠죠
또한, 마이크로서비스 아키텍쳐의 단점도 있습니다
1. 앱 관리 : 각 서비스는 다른 앱이므로 버전 관리 등에서 실수나 문제가 발생할 수 있습니다
2. 디버깅 : 여러 앱을 동시에 연동하며 디버그 해야 하기 때문에 어려울 수 있습니다
3. 연동 : 마이크로서비스는 다른 앱이기 때문에 어떤 식으로든 통신을 해야 합니다
따라서 인증 같은 추가적인 기능이 필요하며, 카프카 같은 소프트웨어를 사용, 추가 구현해야 하는 비용이 듭니다
4. 에러 처리 : 마이크로서비스 A와 B 사이에 발생할 수 있는 에러들이 추가로 생기고 관리해야하는 비용이 듭니다
5. 공유 데이터 : 마이크로서비스 간에 공유하는 데이터가 있으면 싱크를 고려하는 작업이 필요합니다
6. 배포 과정 자동화 : 서비스가 작게 나뉘어 있기 때문에 굉장히 많은 빈도로 빌드 & 배포가 일어납니다
이러한 비용을 최소화하기 위해 자동화를 구현하는 비용이 듭니다
7. 에러 구분 : 마이크로서비스 A에서 발생한 문제인지 B에서 발생한 문제인지 확인이 필요합니다
8. 모니터링 : 로그, 리소스 등의 모니터링 비용이 서비스의 수만큼 발생합니다
결과적으로 마이크로서비스는 아래의 경우에 사용하는 것이 적합합니다
1. 개발할 소프트웨어가 매우 크고 복잡함
2. 비즈니스 적으로 확장되거나 기능이 추가될 가능성이 높음
3. 높은 확장성, 안정성, 가용성이 요구됨
4. 다양한 팀들 간의 협업이 요구됨
물론 현업에서 개발 경험으로는
너무 작지 않은 마이크로 서비스로 적절히 나누어 설계되어
마이크로 서비스와 모놀리식의 중간 정도의 위치에서 개발한다고 느껴집니다
(용도와 크기에 따라서 유연한 선택 필요)
마이크로서비스의 개념에 대해 익혔습니다
이번엔 간단한 예시를 봅시다
예시는 쇼핑 소프트웨어이며
아래의 4가지 앱으로 구성되어 있습니다
- Store Front Web App
- Account Sevice
- Inventory Sevice
- Shipping Service
브라우저를 통해 보여줄 front UI는 하나의 앱으로 처리하며
다른 백엔드 작업은 서비스로 구현되어 있습니다
각 서비스 간의 통신은 REST API를 사용합니다(일반적으로 대부분 그렇습니다)
서로 별도의 앱이기 때문에 합의한 Interface만 맞추면
변경되어도 서로 영향을 미치지 않습니다
서비스가 추가/변경/제거되어도 연동할 REST API의 주소만 변경해주면 되죠
특정 서비스가 중단되어도 치명적인 문제가 발생하진 않습니다
'Cloud > Cloud Native' 카테고리의 다른 글
The Twelve Factors 요약(5분 컷) (0) | 2021.12.22 |
---|---|
The Twelve Factors (0) | 2021.08.12 |
Cloud Native (0) | 2021.07.09 |