마이크로서비스란?
: 개별적으로 배포 일정을 갖고 업데이트 운영이 가능한 작고 독립적인 소프트웨어 프로세스
- 다른 마이크로서비스와 별개로 업데이트 가능
- 필요에 따라 외부에 노출하거나 외부 접근 불허
- 하나의 마이크로서비스가 많은 기능을 갖지 않는다.
마이크로서비스 앱이란?
: 프로젝트의 주요 기능들을 수행하기 위해 서로 협업하는 작은 서비스들로 구성된 분산 프로그램
- 클러스터 안에서 동작하는 여러 개의 작고 독립적인 서비스로 구성 (각각의 서비스나 구성 요소는 논리적 또는 가상으로 구분된 컴퓨터에 위치)
모놀리스와 마이크로서비스
1. 모놀리스
: 전체적인 앱이 단일 프로세스로 동작
- 앱 개발 난이도가 낮다.
- 작은 규모(= 낮은 복잡도)의 실험적 모델 개발에 적합 (작은 규모의 개발엔 microservice architecture을 적용할 필요가 없다.)
- 시간이 지남에 따라 관리가 어려워진다.
- 코드 변경이 어렵다.
- 실험적 기능 추가가 어렵다.
- 스파게티 코드가 될 수 있다.
2. 마이크로서비스
(1) 마이크로서비스가 대세가 된 이유
: 분산 애플리케이션에 대한 접근성 변화
- 분산 애플리케이션은 매우 복잡하고 구현에 많은 비용 발생
- 클라우드와 가상화, 가상 인프라 관리 자동화 도구(.ex. 쿠버네티스)의 등장에 따른 분산 시스템의 구축 비용 감소
- `분산 애플리케이션 기반의 모놀리스 앱을 대체하기 위한 비용이 줄어들었다.
- 분산 시스템의 구성 요소들을 가능한 작게 만든 것이 마이크로서비스이다.
(2) 마이크로서비스의 장점
1) 세밀한 확장성
- 애플리케이션의 확장성을 세밀하게 조절 가능
- 각 서비스가 필요에 따라 독립적으로 확장 가능
2) 배포 위험 감소
- 새로운 코드를 배포할 때의 위험을 최소화
- 하나의 업데이트가 전체 시스템에 영향을 미치지 않음
3) 기술적 유연성
- 개발자들이 하나의 기술 스택에 구속되지 않고, 각 서비스에 가장 적합한 기술 스택을 선택할 수 있다.
(2) 마이크로서비스의 단점
- 어렵고 복잡하다.
(3) 마이크로서비스 최신 도구
1) 도커
- 패키지를 만들거나 서비스 배포
2) 도커 컴포즈
- 개발 환경에서 마이크로서비스 앱 테스트
3) 쿠버네티스
- 클라우드에 앱을 호스트 (클라우드에 앱을 돌리고 싶을 때)
마이크로서비스 앱의 설계
1. 마이크로서비스 앱의 설계 규칙
- 미래에 필요한 검증을 위해 지나치게 미리 설계하지 말자. (단순한 설계부터 시작)
- 최대한 단순하게 유지하기 위해 개발 과정에 지속적인 리팩토링을 적용하자.
- 좋은 설계가 자연스럽게 완성되도록 하자.
- 마이크로서비스들로 구성된 커다란 앱을 미리 단정적으로 설계할 수 없다.
2. 마이크로서비스의 원칙
(1) 단일 책임 원칙
- 하나의 (마이크로)서비스는 개념적으로 하나의 업무를 책임져야 한다.
(2) 느슨한 연결
- 서비스 간 연결을 최소화하고, 반드시 필요한 정보가 아니면 공유하지 않는다.
- 서비스들 간의 연결과 종속성을 최소화하면 앱에서 어떤 문제가 확산되는 일 없이 개별 서비스를 업그레이드하기 쉬워진다. -> 변화하는 업무 요구에 맞춰 유연하게 대응 가능
(3) 강한 응집력
- 하나의 마이크로서비스 안에서는 코드가 서로 기능적으로 연계돼 있고, 맡은 서비스 영역에 대한 문제를 풀 수 있도록 동작해야 한다.
- 하나의 마이크로서비스가 2개 이상의 문제를 해결하거나, 책임지는 범위가 위의 경우보다 크다면 강한 응집력을 갖지 못한 것이다.
3. 도메인 기반 설계 (Domain Driven Design)
: 비즈니스 도메인을 중심으로 설계해나가는 방법
- DDD에서 의미적 구분의 개념은 마이크로서비스의 경계를 정하는데 적합하다.
- 마이크로서비스 분야에서는 반복되는 코드에 대해 관대하다.
개발 프로세스 확장
1. 작은 규모의 마이크로서비스 앱을 소규모로 개발하는 경우
- 개발자들은 개발 워크스테이션에서 하나의 코드 베이스로 코드 작성과 테스트를 한다.
- 개발자들은 호스팅된 코드 레포지토리에 코드 변경사항을 푸시해서 앱을 운영 환경에 배포하기 위한 CD 파이프라인을 트리거한다.
- 새로운 앱을 개발할 때 빠르게 시작하는데 적합하다.
- 하지만 규모가 커질수록 문제가 발생한다.
- 운영 환경과 비슷한 테스트 환경 필요 (완벽하지 않은 변경 사항이 고객에게 영향을 주지 않도록)
- 개발자 간의 간섭
- 하나의 코드 베이스로 작업하므로 merge conflict 및 빌드 관리 실패 발생
- 확장성 부족
- 하나의 코드 레포지토리와 CD 파이프라인은 확장성이 없다.
- 따라서 아래와 같이 여러 팀으로 쪼개는 방법을 생각할 수 있다.
2. 여러 팀으로 개발하는 경우
- 각각의 팀이 다른 마이크로서비스 집합을 서로 겹치지 않게 책임을 지도록 앱을 분할한다.
- 각 팀은 하나 이상의 마이크로서비스를 소유한다.
- 코딩부터 테스트를 거쳐 운영 환경까지 모두 책임(가용성, 성능 유지까지)
- 아래와 같이 마이크로서비스를 독립적으로 동작하도록 분리할 수 있다.
3. 독립적인 마이크로서비스
(1) 단일 레포지토리와 CD 파이프라인
- 쉽게 시작할 수 있고, 인프라를 만들고 운영하는데 시간이 훨씬 적게 소비된다.
- 단일 CD 파이프라인은 모든 마이크로서비스를 같은 속도로 출시해야 하는 문제가 있다.
- 배포할 때마다 전체 앱이 망가질 수 있다.
- 따라서 아래와 같이 레포지토리와 CD 파이프라인을 나눌 수 있다.
(2) 분리된 코드 레포지토리와 여러 CD 파이프라인
- 세밀하게 배포 제어가 가능하다.
- 전체 앱의 관리는 더 복잡해진다.
4. 코드 레포지토리의 분리
- 마이크로서비스마다 구분되도록 레포지토리 구성
- 새로운 레포지토리는 하나의 마이크로서비스 코드와 그 코드를 운영 환경에 배포하는 코드를 포함한다.
5. CD 파이프라인 분리
- 마이크로서비스마다 구분된 배포 파이프라인이 필요하다.
- 하나의 마이크로서비스 배포 파이프라인을 만든 후 재사용 가능
6. 메타리포
: 분리된 레포지토리들을 하나의 코드 레포지토리로 묶어주는 가상 코드 레포지토리
- 단일 코드 레포지토리의 단순함과 편리함
- 분리된 레포지토리의 독립성 유지
- ".meta" 설정 파일을 만들어 구성
- infrastructure는 어떤 레포지토리랑 연결돼 있고, azure-storage는 어떤 레포지토리랑 연결돼 있고....
7. 다중 환경 만들기
- 개발자가 각자 개발 워크스테이션에서 하는 테스트로는 한계가 있다.
- 고객이 사용 중인 운영 환경은 아니지만, 운영에 가까운 환경에서 테스트 필요
8. 운영 워크플로
- 코드 레포지토리 안에서 배포 환경에 맞게 브랜치로 구분해서 사용
- development branch
- test branch
- production branch
성능 확장성
1. 더 많은 부하를 처리하기 위한 성능 확장
- 마이크로서비스는 성능에 대한 섬세한 제어가 가능하다.
- 성능이 떨어지는 부분, 사용량이 최대일 때 과부하가 걸린 위치 등을 모니터링하기 쉽다.
- 수직 확장(scale-up)만 가능한 모놀리스와는 다르게, 마이크로서비스에선 다양한 방식으로 성능 조정이 가능하다.
- 전체 클러스터의 수직 확장
- 전체 클러스터의 수평 확장
- 개별 마이크로서비스의 수평 확장
- 전체 클러스터의 탄력적인 확장
- 개별 마이크로서비스의 탄력적인 확장
- 데이터베이스 확장
(1) 전체 클러스터의 수직 확장 (scale-up)
- 앱이 커지면서 클러스터가 앱을 실행하는 데 충분한 연산 능력(CPU), 메모리, 저장소 등을 보유하지 못할 수 있음 -> 클러스터에 가용한 자원을 증가시켜야 한다. (virtual machine의 core, 메모리, 저장소 성능 높여야 한다.)
(2) 전체 클러스터의 수평 확장 (scale-out)
: 같은 크기로 개수를 늘리는 방식
- 일반적으로 수직 확장보다 비용이 덜 소요된다.
- 적은 수의 크고 비싼 VM > 많은 수의 작고 싼 VM
(3) 개별 마이크로서비스의 수평 확장
- 클러스터의 규모는 충분하지만 개별 마이크로서비스에 부하가 걸리는 경우, 부하를 여러 인스턴스로 분해할 수 있도록 수평 확장
(4) 전체 클러스터의 탄력적인 확장
- 요청 수준에 맞게 자동으로, 그리고 동적으로 클러스터를 확장
- 요청이 적을 때는 자동으로 필요없는 자워 해제
- 요청 많을 때는 새로운 자원을 증가한 부하에 맞게 할당
(5) 개별 마이크로서비스의 탄력적인 확장
- 마이크로서비스의 복제 수를 마이크로서비스 부하에 맞게 동적으로 확장하거나 줄인다.
(6) 데이터베이스 확장
- 하나의 마이크로서비스는 자신만의 데이터베이스 하나를 가져야 한다.
- 여기서 데이터베이스 != 데이터베이스서버
- 그렇지 않을 경우, 공유 데이터베이스로 인해 마이크로서비스가 더 이상 독립적이지 않게 되고, 심각한 병목이 발생할 수 있다.
- 앱이 커지면 규모가 큰 데이터베이스는 여러 독립적인 데이터베이스 서버로 분리해서 확장할 수 있다.
- 하나의 데이터베이스를 하나의 데이터베이스 서버로 감당하기 어려워지면 샤딩(sharding, DB에 데이터를 나눠서 저장하는 것)을 이용할 수 있다.
(7) 인프라 변경 관리
- 블루-그린 배포
- 두 개의 운영환경을 통해 잠재적인 위험을 가진 인프라 변경으로부터 고객을 보호
모놀리스를 마이크로서비스로 전환하기
1. 마이크로서비스 플랫폼 구성
- 쿠버네티스 클러스터 생성
2. 자연스러운 경계(DDD)로 분할하기
- 모놀리스가 거대하고 복잡하다면 리팩토링이 필요하다.
3. 가장 자주 변경하는 부분을 추출
- 마이크로서비스가 주는 장점을 바로 누릴 수 있다.
4. 과정 반복
* 본 게시물은 성신여자대학교 박지웅 교수님의 '클라우드컴퓨팅' 강의 내용을 토대로 작성했습니다.
'Cloud' 카테고리의 다른 글
[클라우드 컴퓨팅] 1. 클라우드 컴퓨팅 개요 (0) | 2025.03.10 |
---|