본문 바로가기
카테고리 없음

마이크로서비스(microservice) 아키텍처 12가지 원칙

by techdebt 2025. 1. 27.
반응형

MSA 12factors

 

MSA 12 FACTORS

마이크로서비스 아키텍처의 12-Factor App은 소프트웨어 개발에서 클라우드 기반의 애플리케이션을 구축할 때 따라야 하는 12가지 원칙의 집합입니다. 이 원칙들은 애플리케이션을 더욱 확장 가능하고, 유지보수가 쉽고, 클라우드 환경에서 안정적으로 배포할 수 있도록 설계되었습니다.

모든 건축물이 튼튼한 기초를 필요로 하듯, 마이크로서비스도 견고한 기반이 필요합니다.

첫 번째로 중요한 것은 단일 코드베이스입니다. 이는 마치 한 회사가 하나의 본사 건물을 가지고 여러 지점을 운영하는 것과 같습니다. 코드는 Git과 같은 버전 관리 시스템에서 중앙 집중적으로 관리되며, 각 환경(개발, 테스트, 운영)에 배포됩니다.

의존성 관리는 더욱 흥미로운 주제입니다. 최근 한 프로젝트에서 겪은 일을 예로 들어보겠습니다.

팀원 중 한 명이 로컬 환경에 설치된 라이브러리에 의존하는 코드를 작성했고,

이는 다른 환경에서 예상치 못한 오류를 발생시켰습니다.

모든 의존성을 명시적으로 선언하고 애플리케이션과 함께 패키징하는 것은 시스템의 유지보수 관점에서 굉장히 중요한 이슈입니다.

I. Codebase

원칙: 애플리케이션은 단일 코드베이스를 가져야 하며, 다수의 배포가 가능해야 합니다.
설명: 모든 환경(개발, 테스트, 프로덕션)에서 동일한 코드가 사용되며, 버전 관리 시스템에 저장됩니다.

II. Dependencies

원칙: 명시적으로 선언되고 분리된 의존성을 사용해야 합니다.
설명: 애플리케이션은 시스템에 사전 설치된 패키지에 의존해서는 안 됩니다. 모든 필요한 라이브러리는 애플리케이션과 함께 패키징되어야 합니다.

III. Configuration

원칙: 설정 정보는 코드에서 분리되어야 합니다.
설명: 환경변수를 통해 설정을 관리하여, 코드 변경 없이 다양한 환경에서 애플리케이션을 실행할 수 있게 합니다.

쿠버네티스 패러다임에서는 코드에서 구성을 분리하기 위한 다양한 옵션이 있습니다. 키-값 쌍을 일반 텍스트 형식으로 보관하는 configMap을 사용할 수 있습니다. configMap 샘플은 아래와 같습니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: game-config
data:
  app_mode: demo
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30    
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice

IV. Backing Services

원칙: 백엔드 서비스를 연결된 리소스로 취급해야 합니다.
설명: 데이터베이스, 메시징 시스템 등 외부 서비스에 대한 접근은 URL 등의 설정을 통해 이루어져야 하며, 애플리케이션과 느슨하게 결합되어야 합니다.

V. Build, release, run

원칙: 엄격하게 분리된 빌드와 실행 단계를 가져야 합니다.
설명: 코드 빌드 단계에서 생성된 릴리즈는 실행 환경에서 변경되지 않고 그대로 배포되어야 합니다.

VI. Processes

원칙: 애플리케이션은 하나 이상의 무상태 프로세스로 실행되어야 합니다.
설명: 세션 상태 정보는 서버가 아닌 데이터베이스, 캐시와 같은 백엔드 저장소에 저장되어야 합니다.
컨테이너의 경우, 컨테이너 자체가 임시적이기 때문에 이는 매우 중요합니다. 컨테이너는 자주 재시작되는 경향이 있으므로 컨테이너에 저장된 데이터가 사라지게 됩니다. 12-Factor 앱은 프로세스를 상태 비저장 상태로 취급하며 아무것도 공유하지 않습니다.

VII. Port binding

원칙: 서비스는 포트 바인딩을 통해 외부에 노출되어야 합니다.
설명: 애플리케이션은 웹 서버를 내장하여 독립적으로 실행될 수 있어야 하며, 외부 요청을 직접 받을 수 있어야 합니다.

VIII. Concurrency

원칙: 프로세스 모델을 통해 애플리케이션을 확장해야 합니다.
설명: 다양한 작업(웹 요청 처리, 배경 작업 처리 등)을 위해 여러 프로세스를 동시에 실행함으로써 애플리케이션을 확장합니다.
마이크로서비스와 컨테이너의 가장 큰 장점은 필요에 따라 개별 서비스를 확장할 수 있다는 점입니다. 이러한 개별 서비스는 다른 서비스를 방해하지 않고 확장할 수 있습니다.
동일한 서비스 또는 애플리케이션의 인스턴스가 여러 개 있는 경우 이러한 유형의 확장을 수평적 확장이라고 합니다. 애플리케이션의 사용량에 따라 동일한 컴퓨터에서 메모리와 CPU를 늘리는 것을 수직적 확장이라고 합니다. 

IX. Disposability

원칙: 빠른 시작과 우아한 종료를 지원하는 폐기 가능한 애플리케이션을 만들어야 합니다.
설명: 애플리케이션은 빠르게 시작할 수 있어야 하며, 종료 신호를 받았을 때 데이터 손실 없이 안전하게 종료되어야 합니다.

X. Dev/prod parity

원칙: 개발, 스테이징, 프로덕션 환경을 최대한 비슷하게 유지해야 합니다.
설명: 환경 간 차이를 최소화함으로써, 소프트웨어 배포 시 발생할 수 있는 문제를 줄일 수 있습니다.

XI. Logs

원칙: 로그를 이벤트 스트림으로 취급해야 합니다.
설명: 애플리케이션은 로그를 파일이나 데이터베이스로 직접 쓰지 않고, 표준 출력을 통해 로그를 스트리밍해야 합니다.
로그는 실행 중인 애플리케이션의 동작에 대한 가장 중요한 정보를 제공합니다. 특히 애플리케이션이나 서비스를 실행하는 동안 발생할 수 있는 문제를 해결하는 데 도움이 됩니다. 로그는 이벤트가 발생할 때 트리거되는 중요한 데이터 스트림으로 취급됩니다. 애플리케이션은 스탯아웃에 정보를 기록하도록 설계되어야 하며, 로그 파일에 쓰거나 관리하려고 시도해서는 안 됩니다. 

XII. Admin processes

원칙: 관리/유지보수 작업을 일회성 프로세스로 실행해야 합니다.
설명: 데이터베이스 마이그레이션, 관리 스크립트 실행 등의 작업은 애플리케이션과 동일한 환경에서 일회성 프로세스로 실행되어야 합니다.

 

모니터링과 운영: 안정적인 서비스 유지하기

로깅은 마이크로서비스 운영에서 특히 중요합니다.

최근 한 장애 상황에서 경험한 것처럼, 잘 설계된 로깅 시스템은 문제 해결의 핵심이 됩니다.

로그를 이벤트 스트림으로 처리함으로써, 실시간으로 시스템의 상태를 모니터링하고 문제에 신속하게 대응할 수 있습니다.

관련해서 다음 포스팅을 한다면 현재 실무에서 모든 데이터를 이벤트 스트림형태로 변환해서 일괄 저장 및 분석하는 아키텍처를 설계 과정에 대한 내용을 써보면 어떨까 싶습니다.

결론

12 Factors는 단순한 가이드라인이 아닌, 실전에서 검증된 베스트 프랙티스입니다.

이러한 원칙들을 따르면서도, 각 조직의 특성과 요구사항에 맞게 유연하게 적용하는 것이 중요합니다. 결국 가장 좋은 아키텍처는 실제 문제를 효과적으로 해결하는 아키텍처입니다.