아키텍쳐의 중요성
소프트웨어 개발에서 아키텍처란 서비스의 구성과 동작에 대한 구성 방식을 구조적으로 표현하고 결정한 것을 말한다. 시스템의 규모가 커지고 트래픽이 증가할수록, 단순한 기능 구현을 넘어 시스템의 구조(아키텍처)가 서비스의 효율과 성패를 결정하는 핵심 요소가 될 수 있다.
모놀리식 아키텍처(Monolithic Architecture) 특징
모놀리식 아키텍처(MA)는 모든 기능(사용자, 주문, 결제 등)이 하나의 코드베이스에 통합되어 하나의 애플리케이션으로 동작하는 전통적인 구조이다. 다음과 같은 특징과 장점을 가진다.
- 특징: 모든 모듈이 단일 데이터베이스를 공유하고, 모듈 간 통신은 메모리 내 함수 호출로 이루어진다.
- 장점: 초기에 개발이 쉽고, 배포가 단순하며, 단일 DB를 사용하므로 트랜잭션 관리가 용이하다. 간편한 개발, 빠르고 편한 End to End 테스트, 손쉬운 모니터링 및 디버깅의 장점을 가진다.
모놀리식(MA) 아키텍처의 한계
규모가 커질수록 모놀리식의 장점은 사라지고, 다음과 같은 문제들이 나타난다.
- 느리고 위험한 배포: 작은 기능 수정에도 전체를 빌드/재배포해야 하므로 배포 시간이 길고 배포 과정 자체가 위험하다.
- 장애 전파 위험: 하나의 모듈(예: 재고 관리)의 버그나 부하가 전체 애플리케이션을 다운시킬 수 있어 장애 격리가 불가능하다.
- 비효율적인 확장 (Scale-Out): 트래픽이 몰리는 특정 기능만 확장하고 싶어도, 전체 시스템을 확장해야 하는 자원 비효율이 발생한다.
마이크로서비스 아키텍처 (MSA)의 등장
MSA는 '리팩터링'의 저자인 마틴 파울러에 의해 널리 퍼진 개념이다.
- 정의: MSA는 애플리케이션을 명확하게 구분된 비즈니스 경계(Bounded Context)를 기준으로 나누어, 독립적으로 개발, 배포, 운영이 가능한 작은 서비스들의 집합으로 구성하는 구조이다. 즉, 서비스는 단순한 기술적 모듈이 아니라, 하나의 일관된 비즈니스 도메인(예: 주문, 결제, 재고)에 대한 책임을 완벽하게 가져야 한다.
- 핵심 장점:
- 독립적 배포: 서비스별 개별 배포가 가능해 민첩성을 확보한다.
- 장애 격리: 서비스 간 영향이 최소화되어 안정성이 높아진다.
- 유연한 확장: 필요한 서비스만 선택적으로 확장하여 효율성을 극대화한다.
Bounded Context의 중요성
비즈니스 경계(Bounded Context)는 MSA 설계의 핵심 철학이다.
"여기까지는 '상품(Product)'이라는 단어가 A라는 의미로 사용되고, 저기부터는 '상품'이 B라는 다른 의미(예: 배송 가능 상품)로 사용된다"는 것을 명확히 구분하는 경계이다. 각 서비스가 이 경계 안에서만 동작하고 자신의 데이터베이스를 소유하게 함으로써, 서비스 간의 강한 결합을 막고 독립적인 개발이 가능해진다. 이 경계 설정이 잘못되면 MSA는 오히려 유지보수가 더 어려운 분산된 모놀리식(Distributed Monolith)이 될 위험이 있다.
MSA 구현 시 당면할 필수 과제1: 분산 환경에서의 인증/공유 상태 관리
MSA로 전환 시 가장 먼저 직면하는 실질적인 문제는 사용자 인증 및 상태(State) 관리다. MSA 환경은 로드 밸런싱을 위해 서버 인스턴스를 여러 대 운영하는데, 이로 인해 전통적인 세션 방식은 사용할 수 없게 된다.
1. 문제 인식: 세션 불일치와 무상태 아키텍처의 필요성
모놀리식에서는 사용자 세션을 단일 서버의 인메모리(In-Memory)에 저장했지만, MSA에서는 로드 밸런서가 요청을 서로 다른 서버로 분산시켜 로그인 상태가 유지되지 않는 문제가 발생한다. 따라서 MSA를 성공적으로 운영하려면 모든 서버가 공유하는 중앙 집중식 상태 관리가 필요하거나, 아예 상태를 가지지 않는 무상태(Stateless) 아키텍처로 전환해야 한다.
단일 서버(Monolithic) 환경에서는 내부 메모리 캐시가 가장 효율적이며, 별도의 Redis 서버 구축은 네트워크 오버헤드와 운영 비용을 발생시키는 오버 엔지니어링일 수 있다. Redis는 MSA처럼 다중화된 서버들 간의 상태 공유라는 분산 시스템의 필수적인 수단으로서 존재 가치를 가진다.
2. 해결책 1: 중앙 집중식 세션 저장소
기존 세션 방식을 유지할 경우, 모든 서비스 인스턴스들이 공유할 수 있도록 외부 저장소를 사용한다.
- Redis의 적합성: Redis는 디스크 기반 RDB와 달리 인메모리(In-Memory) 기반이므로 세션 조회 속도가 압도적으로 빠르며, 세션에 필수적인 만료 정책(TTL)을 쉽게 설정할 수 있어 MSA 환경의 분산 상태 관리에 적합하다.
3. 해결책 2: 무상태(Stateless) 토큰 기반 인증
MSA의 철학에 가장 부합하며, 현대 분산 시스템에서 가장 권장되는 방식이다.
- 원리: 서버는 로그인 성공 시 사용자 정보와 만료 시간을 담은 토큰(예: JWT, JSON Web Token)을 발행하고 클라이언트에게 전달한다. 서버는 전달받은 토큰의 유효성만 검증하므로, 자체적으로 상태를 저장할 필요가 없어 무상태(Stateless)가 실현되며 확장이 매우 용이해진다.
MSA 구현 시 당면할 필수 과제2: 분산 시스템 관련 문제들
MSA는 여러 독립적인 서비스가 네트워크를 통해 협력하는 분산 시스템을 구축하는 것이므로, 모놀리식에서는 겪지 않았던 근본적인 복잡성에 직면하게 된다.
1. 동적 서비스 위치 파악 문제 (Service Discovery)
수많은 서비스 인스턴스가 동적으로 생성/삭제되는 환경에서 통신하려는 서비스의 네트워크 위치를 어떻게 안정적으로 알 수 있을까? 이 문제를 해결하기 위해 서비스 디스커버리(Service Discovery) 메커니즘을 도입해야 한다. 또한, 모든 외부 요청을 하나의 진입점으로 통합하여 내부 서비스로 라우팅하는 API 게이트웨이(API Gateway)를 구축해야 한다.
2. 네트워크 실패와 장애 복원력 문제 (Resilience)
서비스 간 통신이 네트워크 의존성을 갖게 되므로, 네트워크 지연이나 대상 서비스의 실패가 시스템 전체로 전파되는 것을 막는 것이 필수적이다.
- 서킷 브레이커(Circuit Breaker): 특정 서비스 호출이 실패할 경우 일시적으로 호출 자체를 차단하여 장애 전파를 막고 복구 시간을 벌어준다.
- 벌크헤드(Bulkhead): 자원(스레드 풀 등)을 격리하여, 한 서비스의 과부하가 전체 시스템의 자원을 고갈시키지 않도록 보호한다.
3. 데이터 일관성 및 분산 트랜잭션 문제 (Data Consistency)
각 서비스가 독립적인 DB를 가지므로, 여러 서비스에 걸친 비즈니스 로직에서 데이터의 원자성(Atomicity)을 즉각적으로 보장하기 어렵다. 다음 방법은 즉각적인 원자성을 포기하고 최종적 일관성을 추구하는 접근 방식이다.
- 분산 트랜잭션 처리: 여러 DB에 걸친 데이터가 최종적으로 일관되도록 처리하기 위해 SAGA 패턴을 활용하거나, 이벤트 드리븐 아키텍처를 구축하고 메시지 브로커(Kafka 등)를 통해 비동기적으로 데이터 변경 사항을 전파한다.
- 데이터 동시성 제어: 여러 서비스나 요청이 동일한 데이터를 동시에 수정할 때 충돌이 발생하는 것을 방지하기 위해 낙관적 락(Optimistic Lock)과 같은 동시성 제어 기법을 주로 사용한다. 낙관적 락은 MSA의 유연성을 해치지 않으면서 데이터 일관성을 지킬 수 있는 방법이다.
MSA 구현 시 당면할 필수 과제3: 운영 및 개발 환경 관리 (DevOps)
MSA는 서비스의 개수가 기하급수적으로 늘어나기 때문에, 운영 방식 자체를 근본적으로 바꿔야 하며, 데브옵스(DevOps) 문화와 자동화된 툴링이 필수적이다.
1. 강력한 CI/CD (Continuous Integration / Continuous Delivery) 파이프라인 구축
수많은 서비스를 수동으로 빌드하고 배포하는 것은 불가능하다. 따라서 개발부터 배포까지의 모든 과정을 완전히 자동화하는 CI/CD 파이프라인 구축이 필수적이고, 이를 위해 컨테이너 기술(Docker)과 오케스트레이션 도구(Kubernetes)를 기반으로 빠르고 안정적인 배포 환경을 확보해야 한다.
2. 통합 로깅, 모니터링 및 트레이싱
서비스가 분산되면서, 문제 발생 시 원인 추적이 매우 복잡해진다.
- 통합 로깅: 모든 서비스 로그를 중앙 집중식으로 수집하고 관리(예: ELK Stack)해야 한다.
- 분산 트레이싱(Distributed Tracing): 하나의 사용자 요청이 여러 서비스를 거치는 과정을 시각적으로 추적(예: Jaeger)하여 병목 지점이나 실패 지점을 정확히 파악하는 시스템이 필요하다.
3. 팀 구성 및 문화 변화 (Conway의 법칙)
MSA를 도입하려면 조직 문화의 변화도 필요하다.
- Conway의 법칙: 시스템 디자인은 조직의 커뮤니케이션 구조와 유사한 형태의 시스템을 만들게 된다. MSA의 성공을 위해서는 기능 단위가 아닌 비즈니스 도메인별로 팀을 독립적으로 구성해야 한다.
- End-to-End 오너십: 각 팀이 자신이 담당하는 서비스의 개발부터 운영(배포, 모니터링, 장애 대응)까지 전 과정을 책임지는 문화를 확립해야 진정한 MSA의 효과를 볼 수 있다.
MSA는 분명 높은 복잡성을 요구하지만, 대규모 시스템의 민첩성, 안정성, 유연한 확장성을 확보하기 위한 현시점의 가장 강력한 아키텍처 솔루션이다. 시스템이 성장하고 모놀리식의 한계에 봉착했을 때, MSA로의 전환이 필요하다.
그렇다고 무조건 MSA가 정답은 아님을 명심해야 한다. MSA로 전환하는 순간, Redis, Kafka, Kubernetes 등 복잡한 분산 시스템용 인프라에 대한 추가적인 구축 비용, 운영 책임, 장애 관리 책임이 발생한다.
단일 서버로도 충분한 규모의 서비스라면, 이러한 인프라 도입은 프로젝트에 비해 불필요한 오버 엔지니어링이 될 수 있다. 따라서 서비스의 규모, 팀의 역량, 성장 속도를 종합적으로 고려하여 아키텍처를 신중하게 선택하는 지혜가 필요하다.
이번 아티클에서는 MSA 구현을 위해 필요한 과제들에 대해서 소개했다. 소개한 기법들을 활용해 시스템 안정성을 확보하는 구체적인 방법을 다루는 아티클도 나중에 작성해보도록 하겠다.
'Newly I Learned' 카테고리의 다른 글
| 분산 컴퓨팅, RAID의 한계를 넘어 분산 플랫폼의 시대로(대본) (0) | 2025.11.05 |
|---|---|
| NoSQL, Cassandra (0) | 2025.11.05 |
| 왜 Entity를 그대로 반환하면 안 될까? – 백엔드 계층 분리의 이유 (3) | 2025.05.22 |
| WebRTC와 디스코드 스트림 세션 (2) | 2025.05.18 |
| Newly Learned Keyword : OSSCA 체험형 프로젝트 멘티형 1차 지원 中 (0) | 2025.04.10 |