-
Notifications
You must be signed in to change notification settings - Fork 0
Description
CHAPTER 3 아키텍처 모듈성
그림 3-1은 물이 담긴 유리컵입니다.
컵은 서버, 물은 애플리케이션입니다.
모놀리식 애플리케이션이 점점 커지고 고객 수요가 늘어나면 처리해야 할 유저 부하가 급증하고 리소스를 더 많이 차지하기 시작합니다.
Figure 3-1. A full glass representing a large monolithic application close to capacity
그림 3-2와 같이 빈 유리컵을 하나 더 가져와 물을 두 컵으로 나눠 담습니다.
절반의 물을 더 부을 수 있으니 50%의 용량을 추가 확보한 셈입니다.
이 유리컵 비유는 비즈니스 이해관계자, C-레벨 임원들에게 아키텍처 모듈화를 효과적으로 설명하는 데 아주 요긴했습니다.
그리고 아키텍처 리팩터링에 아낌없이 비용을 투자했습니다.
Figure 3-2. Two half-full glasses representing an application broken apart with plenty of capacity for growth
변화에 능동적으로 대처하는 능력, 민첩성은 아키텍처 모듈화의 중요한 강점입니다.
아래 문구는 2020년 1월, David Benjamin과 David Komlos가 포브스에 기고한 글에서 발췌했습니다.
- 진로 수정이 필요할 때마다 과감하고 신속하게 결단을 내려 효과적으로 밀어붙이는 능력이야말로 승자와 패자를 가르는 요인 중 하나입니다.
기술이 비즈니스만큼 빠르고 능동적으로 움직이게 하려면 어느 정도 이상의 아키텍처 민첩성이 꼭 필요합니다.
3.1 모듈화 동인(Modularity Drivers)
아키텍트는 뚜렷한 비즈니스 동인 없이 시스템을 더 잘게 나누면 안 됩니다.
애플리케이션을 더 작은 부분으로 나누는 주요 비즈니스 동인은 시장 출시 속도와 시장에서의 경쟁 우위 확보입니다.
출시 속도는 변화에 신속하게 대응하는 능력인 아키텍처 민첩성이 필요합니다.
민첩성은 유지 보수성, 시험성, 배포성 등 많은 아키텍처 특성으로 이뤄진 복합적인 아키텍처 특성입니다.
경쟁 우위는 확장성, 애플리케이션 가용성, 내고장성을 높이면 출시 시기를 앞당겨 달성할 수 있습니다.
그림 3-3은 모듈화와 연관된 기술 동인technical driver과 비즈니스 동인의 관계를 나타낸 것입니다.
Figure 3-3. The drivers for modularity and the relationships among them
유지 보수성, 시험성, 배포성은 모듈러 모놀리스나 마이크로커널 아키텍처 같은 모놀리식 아키텍처에서도 충분히 달성할 수 있습니다.
3.1.1 유지 보수성Maintainability
유지 보수성은 각종 패치, 프레임워크 업그레이드, 서드파티 업데이트 등의 내부적 변경은 물론이고 기능을 얼마나 쉽게 추가, 변경, 삭제할 수 있는지를 나타내는 특성입니다.
소프트웨어 아키텍트이자 hello2morrow의 창시자인 알렉산더 폰 지트제비츠는 애플리케이션의 유지 보수성을 객관적으로 측정할 수 있는 새로운 기준을 마련했습니다.
- ML: 시스템 전체의 유지 보수성 수준(%)
- k: 시스템에 있는 논리적 컴포넌트의 총 개수
- Ci: 주어진 컴포넌트의 결합도
수식에 따르면 컴포넌트 간 결합도가 높을수록 코드베이스의 유지 보수성은 전반적으로 낮아집니다.
수식 외에 컴포넌트에 따른 애플리케이션의 유지 보수성을 측정하는 메트릭 몇 가지가 있습니다.
Component coupling
- 컴포넌트가 서로 알고 있는 정도와 형태
Component cohesion
- 컴포넌트의 동작이 서로 연관돼 있는 정도와 형태
Cyclomatic complexity
- 컴포넌트 내부의 전체적인 간접 참조 및 중첩 정도
Component size
- 컴포넌트 내부에 구현된 코드의 전체 문장 수
Technical versus domain partitioning
- 컴포넌트를 기술적 용도로 나누는지, 도메인 목적에 맞게 나누는지
대규모 모놀리식 아키텍처는 일반적으로 다수의 레이어에 걸쳐 기능이 분할돼 있습니다.
도메인 관점에서도 컴포넌트 간 결합도가 높고 응집도는 약하기 때문에 유지 보수성이 떨어집니다.
그림 3-4와 같이 새로운 요구사항이 생겨 시스템에 반영하려면 모든 레이어의 코드를 추가해야 하므로 애플리케이션 전체를 고쳐야 합니다.
Figure 3-4. With monolithic layered architectures, change is at an application level
모듈러 아키텍처는 도메인을 더 잘게 개별 배포가 가능한 소프트웨어 단위로 분리해서 구현하므로 변경 작업이 한결 수월합니다.
그림 3-5 처럼 새로운 요구사항의 변경 범위가 특정 도메인 서비스 수준에 국한되므로 변경이 필요한 특정 배포 단위만 손쉽게 격리시킬 수 있습니다.
Figure 3-5. With service-based architectures, change is at a domain level
그림 3-6은 마이크로서비스 아키텍처이므로 새 요구 사항을 기능 수준의 변경 범위로 배포 가능하게 됩니다.
Figure 3-6. With microservices architectures, change is at a function level
3.1.2 시험성Testability
시험성은 아키텍처 민첩성을 위한 필수 성분으로, 테스트의 완전성과 용이함을 의미합니다.
애플리케이션을 더 작은 배포 단위로 나눠 아키텍처를 모듈화하면 서비스를 변경하더라도 전체 테스트 범위가 줄어들고 테스트를 좀 더 완전하고 수월하게 진행할 수 있습니다.
시험성이 개선이 되어도 모놀리식 배포 애플리케이션과 동일한 문제가 재발할 가능성이 있습니다.
그림 3-7처럼 모놀리식 애플리케이션을 3개의 자기 완비형self-contained 배포 단위로 분리했다고 가정했습니다.
서비스A는 B, C와 상관없으므로 테스트 범위는 A로만 한정됩니다.
하지만 A, B, C 서비스가 서로 통신을 하고 있으면 A만 변경한다고 해도 B, C를 테스트해야 하므로 시험성이 급격히 떨어지며, 테스트 용이성 및 완전성 모두 부정적인 영향을 받습니다.
Figure 3-7. Testing scope is increased as services communicate with one another
3.1.3 배포성Deployability
배포성은 배포의 용이함과 배포 빈도, 전체 리스크까지 포괄한 개념입니다.
소프트웨어를 격주 혹은 더 자주 배포하면 배포 리스크가 전반적으로 커지고 새로운 기능이나 버그 픽스가 지연될 가능성이 높아집니다.
배포 빈도는 이 변화를 얼마나 재빠르게 흡수할 수 있는지에 따라서도 적절히 조정해야 합니다.
모놀리식은 배포에 코드 프리징이나 목 배포 등 잡다한 작업들이 있고, 새로운 기능 및 버그 수정판을 배포하면 다른 파트가 말썽을 일으킬 위험이 있습니다.
배포 주기도 길어서 배포성이 현저히 낮습니다.
이때 개별 배포 단위를 늘려 어느 정도 모듈화하면 배포하는데 필요한 작업과 리스크가 줄어들게 됩니다.
더 잘게 분해된 서비스들이 비즈니스 트랜잭션을 완료하기 위해서는 더 많은 통신을 해야 하는 단점이 있습니다.
배포 시점에 다른 서비스에 문제가 생길까봐 단순 변경도 배포하기 어려울 만큼 리스크가 커질 수도 있습니다.
소프트웨어 아키텍트인 매트 스틴은 마이크로서비스 오케스트레이션에 대한 자신의 블로그 게시글에서 이런 말을 했습니다.
- If your microservices must be deployed as a complete set in a specific order, please put them back in a monolith and save yourself some pain.
분산 진흙잡탕이 된 상황에서는 아키텍처 모듈화의 장점을 얻기는 거의 불가능합니다.
3.1.4 확장성Scalability
확장성은 유저 부하가 증가해도 시스템이 응답성을 유지하는 능력입니다.
시스템이 응답성을 유지하는 능력인 탄력성과도 연관이 있습니다.
그림 3-8은 확장성과 탄력성의 차이점을 보여줍니다.
Figure 3-8. Scalability is different from elasticity
두 아키텍처 특성 모두 응답성을동시 요청 수의 함수로 나타내지만, 아키텍처와 구현 관점에서는 전혀 다른 방식으로 취급됩니다.
확장성은 일반적으로 회사가 정상 궤도를 따라 꾸준히 성장하는 긴 시간에 걸쳐 영향을 미치지만,
탄력성은 유저 부하가 갑자기 치솟는 경우 즉각적인 대응을 할 수 있는 능력을 말합니다.
짧은 시간에 폭증하는 유저 부하를 감당하려면 서비스의 MTTS(Mean-Time-To-Startup)가 아주 짧아야 합니다.
아키텍처 관점에서 이 정도의 탄력성을 달성하려면 서비스를 아주 세분화하는 것이 좋습니다.
MTTS는 적절한 아키텍처 솔루션을 갖춰 놓고 소규모 경량 플랫폼과 런타임 환경 등의 설계 시점 기법을 적용함으로써 관리할 수 있습니다.
서비스를 잘게 나누면 확장성, 탄력성 모두 좋아지지만,
탄력성은 세분도(배포 단위 사이즈), 확장성은 모듈성(개별 배포 단위로 분리)과 직접적인 관계가 있습니다.
그림 3-9는 세 가지 아키텍처 스타일에 대해 확장성과 탄력성을 평가해서 별점을 매긴 것입니다.
Figure 3-9. Scalability and elasticity improve with modularity
단일 비즈니스 트랜잭션에 많은 서비스가 참여해 서로 통신할수록 확장성과 탄력성이 떨어집니다.
따라서 높은 확장성과 탄력성이 필요한 경우, 서비스간 동기 통신을 가능한 한적게 유지하는 것이 중요합니다.
3.1.5 가용성/내고장성
내고장성fault tolerance을 아키텍처 모듈화 관점에서 시스템의 어떤 파트가 고장 나도 나머지 파트는 응답성과 가용성을 유지하는 능력으로 정의합니다.
도메인 및 기능 수준에서 내고장성을 확보하려면 아키텍처 모듈화가 필수입니다.
조심해야 할 부분은 장애가 발생한 서비스에 동기적으로 의존하는 다른 서비스가 있는 경우, 내고장성을 달성하기는 어렵습니다.
분산 시스템에서는 내고장성을 유지하기 위해 서비스간 비동기 통신이 꼭 필요한 이유입니다.
3.2 한빛가이버 사가: 비즈니스 케이스 만들기
시스템을 분해하기로 한 결정을 기록하고 경영진에게 제출할비즈니스케이스 프레젠테이션 자료를 만들기 위해 ADR을 정리했습니다.
ADR: 한빛가이버 애플리케이션을 분산 아키텍처로 마이그레이션
Context
- 한빛가이버 애플리케이션은 신규 고객 및 고장 티켓 접수/처리, 운영 및 분석 리포팅, 과금/결제 처리, 기타 제반 관리 기능 등 수많은 비즈니스 기능이 구현된 모놀리식 시스템이다.
- 그러나 이 시스템은 현재 확장성, 가용성, 유지 보수성 등 여러 측면에서 문제가 많은 상황이다.
Decision
현재 운영 중인 모놀리식 한빛가이버 애플리케이션을 분산 아키텍처로 마이그레이션 한다. 이 과정에서 잘 마무리 되면 다음과 같은 성과를 기대할 수 있다.
- 내고장성을 높여 코어 티케팅기능을 외부 고객에게 매끄럽게 제공한다.
- 신규 고객 및 티켓 접수가 늘어나도 유연한 확장이 가능해서 그동안 빈번했던 애플리케이션 프리징 현상이 해결된다.
- 리포팅 기능 자체와 데이터베이스에 대한 리포팅 부하를 분리함으로써 애플리케이션의 잦은 프리징 현상이 해결된다.
- 팀이 현재의 모놀리식 애플리케이션보다 훨씬 더 신속하게 새로운 기능을 구현하고 버그 픽스를 할 수 있게 돼서 전반적으로 민첩성이 향상된다.
- 시스템에서 발생하는 버그가 줄어 테스트가 더 용이해진다.
- 새 기능을 더 빠르게(매주 또는 매일) 서버에 배포하고 버그를 조치함으로써 배포성이 개선된다.
Consequences
- 개발 인력 대부분이 아키텍처 마이그레이션 작업에 참여할 예정이므로 이 기간 중에는 새로운 기능 구현이 다소 미뤄질 것이다.
- 마이그레이션 작업으로 추가 비용이 든다.
- 릴리스 담당 엔지니어는 기존 배포 파이프라인이 수정될 때까지 다수의 배포 유닛을 릴리스하면서 상태를 모니터링해야 한다.
- 마이그레이션을 하려면 모놀리식데이터베이스를 분리해야 한다.
Metadata
Metadata
Assignees
Labels
Projects
Status