때문에, 물리적 자원을 먼저 고려하여 설계를 시작할 경우 위험하다는 것을 저자는 지적하고 있는데요.물리적 아키텍처만으로는 논리적 설계에서 의도한 복잡한 상호작용과 결합도를 제대로 표현할 수 없기 때문입니다. 이를 무시하고 물리적 설계에 매몰되면 유지보수, 테스트, 배포가 모두 어려워지는 결과를 초래합니다.
저는 블록체인과 연계한 서비스라는 물리적 컴포넌트에 갇혀 설계를 실패한 경험을 스터디원과 공유했는데요. 모두들 경청하며 듣고 피드백주셔서 감사했습니다.
# 컴포넌트 식별 방법과 리팩터링 주기
논리 아키텍처를 견고하게 만들기 위해서는 컴포넌트 식별과 리팩터링의 반복적인 주기가 필요합니다. 그림 8-6 컴포넌트 식별 및 리팩터링 주기 초기에 핵심 컴포넌트를 선별하고 요구사항을 배정한 뒤, 역할과 책임을 분석하고 아키텍처 특성을 검토하여 다시 재구성(리팩터링)하는 과정을 거쳐야 합니다. 이때 처음부터 완벽하게 하려 하기보다는 빈 양동이를 채우듯 기능을 점진적으로 개선해 나가는 것이 핵심입니다.
컴포넌트를 식별하는 세 가지 주요 접근법은 다음과 같습니다:
- 작업 흐름 접근법: 시스템 입장에서 시나리오의 주요 흐름을 보고 선별하는 방식입니다.
- 행위자와 행동 접근법: 누가 어떤 행동을 하는지를 기준으로 추출하며, 시스템 자체도 하나의 행위자로 간주할 수 있습니다.
- 엔티티 함정 주의: 데이터베이스 엔티티로부터 기계적으로 컴포넌트를 도출하는 것을 피해야 합니다. 이는 모든 것을 처리하는 만능 'Manager'나 'Handler', 'Engine', 'Processor' 같은 비대한 컴포넌트를 만들어내는 안티 패턴으로 이어지기 쉽습니다.
이와 관련해 지호님은 교육 과정에서 객체지향을 배울 때 엔티티(주어)부터 시작하는 방식이 각인되어 있어 이러한 함정에 더 쉽게 빠지는 것 같다는 통찰을 나누어 주셨습니다.
그리고 디미터 법칙(Law of Demeter, 최소 지식 원칙)을 통해 컴포넌트가 다른 객체의 내부 구조를 알지 못하게 하여 결합도를 낮추어야 한다는 점에 모두가 공감했습니다. 디미터 법칙에 대해 다른 서적에서는 "묻지 말고 시켜라"(진원님), "메세지를 던져라"(지호님)라고 표현된다고 공유해주셨는데요. 지호님은 설계를 진행할 때 "이 컴포넌트가 이것까지 알아야 할까?"라고 질문을 던지는 것이 중요하다고 덧붙여주셨습니다.
# 분산 컴퓨팅의 8가지 +a 오해와 중요성
분산 컴퓨팅에 관한 오해들 8개 (+저자의 a) 시스템이 커짐에 따라 분산 아키텍처를 고려하게 되는데, 이때 오라클(Sun Microsystems)에서 정의한 분산 컴퓨팅의 8가지 오해를 경계해야 합니다. 네트워크는 항상 신뢰할 수 없고, 지연 시간은 0이 아니며, 대역폭은 결코 무한하지 않습니다. 또한 토폴로지는 변하지 않고 관리자는 한 명뿐이라는 생각 역시 위험한 오해입니다.
특히 분산 시스템에서는 모든 요소가 찢어져 있기 때문에 관측성(Observability)을 확보하는 모니터링은 결코 생략해서는 안 되는 필수 요소입니다.
이에 대해 진원은 면접 과정에서의 경험을 빌려, 많은 개발자가 이력서에 MSA(마이크로서비스 아키텍처)를 언급하지만 막상 이러한 네트워크 실패나 지연 시간 이슈를 어떻게 처리했는지 물으면 제대로 답하지 못하는 경우가 많다고 지적했습니다. 또한 분산 환경에서는 동적 동변성(Dynamic Connascence)이 중요하며, 모니터링이 뒷받침되지 않으면 큰 사고로 이어질 수 있다는 점을 강조하셨습니다.
# 계층형 아키텍처 스타일, 모듈형 모놀리스 아키텍처 스타일
마지막으로 가장 대중적인 두 가지 아키텍처 스타일에 대해 심도 있는 대화를 나누었습니다.
계층형(Layered) 아키텍처: 기술적 역량을 기반으로 컨트롤러, 서비스, 리포지토리 등으로 나누는 전통적인 방식입니다. 진원님은 간단한 조회 기능조차 모든 계층을 억지로 거쳐야 하는 '싱크홀 안티 패턴'에 대해 언급하며 계층의 존재 이유를 고민해봐야 한다고 말씀하셨습니다. 이에 지호님은 조회와 명령을 분리하는 CQRS 패턴을 도입하여 조회 시에는 불필요한 서비스 레이어를 건너뛰는 방식으로 이 문제를 해결하기 시작했다는 경험을 공유해 주셨습니다.
모듈형 모놀리스(Modular Monolith): 도메인 영역별로 컴포넌트를 그룹화하여 모듈성을 높인 스타일입니다. 진원님은 회사가 성장하여 추후 MSA로 전환해야 할 때, 이미 모듈화가 잘 되어 있다면 인스턴스 분리만으로도 우아하게 전환할 수 있다는 점을 들어 가장 현실적이고 우수한 아키텍처라는 의견을 주셨습니다.
모듈 간 통신에 대해서는 예슬님이 위아래 관계가 아닌 동등한 입장에서 호출하는 동급 간(Peer-to-Peer) 방식과, 중앙에서 흐름을 제어하는 중재자(Mediator) 방식의 차이를 짚어주셨습니다. 진원님 역시 리팩터링을 하다 보면 결국 상위 레벨에서 오케스트레이션을 담당하는 중재자 클래스가 만들어지게 된다는 점에 깊이 공감하셨습니다.
특히 혼란스러웠던 점은, 우리가 항상 이것이 계층형인가? 모듈형 모놀리스인가?에 대해 혼란이 오는 경우가 있는데요. 모듈형 모놀리스의 설명 중에서, 모듈 단위 안에서 계층을 가질 수 있다고 설명하는 부분이 있습니다. 이를 통해 우리가 크게 스타일을 구분하는 기준은 최상위 분할(top-level partitioning)이 기준임을 예슬님의 의견을 통해 다시 상기할 수 있었습니다. 예슬님이 구성한 런타임 인터랙션 다이어그램 (예슬님의 피땀눈물이 포함되었기에 모자이크!) 여기서도 발표자 김예슬님이 자신의 도메인의 업무는 어떤 방식인지, 구성에서 어떤 걸 고민했는지 공유해주셨습니다.
# 마치며
스터디에서 서로의 경험을 공유하고, 학습한 내용을 토론하는 과정이 유익했습니다. 특히 다음 3주차에는 3가지의 아키텍처 스타일에 대한 챕터인데요.
- Ch.12 파이프라인 아키텍처 스타일
- Ch.13 마이크로커널 아키텍처 스타일
- Ch.14 서비스 기반 아키텍처 스타일
각각의 스타일마다 어떤 트레이드오프(Trade-off)가 있고, 그에 대한 경험은 어땠는지 토론할 수 있을 것 같아 기대됩니다.