클린 아키텍처 스터디 4주차 후기: 아키텍처의 본질, 경계, 그리고 실무적 딜레마 (15장~19장)
안녕하세요. 이번 4주차 세션에서는 로버트 C. 마틴의 『클린 아키텍처』 15장부터 19장까지의 내용을 다루었습니다.
단순히 책의 이론을 읊는 것을 넘어, 실무에서 겪은 생생한 시행착오와 현대 소프트웨어 엔지니어링 관점(예: 『데이터 중심 애플리케이션 설계』와의 시각 차이)에서 클린 아키텍처를 어떻게 바라봐야 할지 깊이 있는 논의가 진행되었습니다.
1. 아키텍처란 무엇인가?
15장부터 19장까지는 시스템의 형태를 규정하고, 컴포넌트 간의 경계를 나누는 '아키텍처의 본질'에 대해 설명합니다.
- 선택지를 가능한 한 오래 열어두기: 좋은 아키텍처는 시스템이 잘 동작하는 것을 넘어, 생명주기 전체(개발, 배포, 운영, 유지보수)를 지원해야 합니다. 핵심 전략은 '세부 사항(디테일)'에 대한 결정을 지연시키고, '정책(비즈니스 룰)'에 집중하여 가능한 한 많은 선택지를 열어두는 것입니다. 이를 통해 책임이 따르는 마지막 순간(Last Responsible Moment)에 최적의 결정을 내릴 수 있습니다.
- 독립성과 결합 분리: 시스템은 UI, 비즈니스 룰, 데이터베이스 등으로 수평적(계층) 분리가 이루어져야 하며, 동시에 유스케이스 단위로 수직적 분리가 가능해야 합니다. 여기서 주의할 점은 우연한 중복(가짜 중복)과 진짜 중복을 구별하는 것입니다. 형태가 비슷해 보인다고 섣불리 통합하면 코드가 강하게 결합되어 훗날 변경의 발목을 잡게 됩니다.
- 경계와 수준(Level): 경계를 넘는다는 것은 결국 함수 호출과 데이터 전달을 의미합니다. 아키텍처의 올바른 의존성 방향은 항상 저수준(I/O, DB, UI 등 상세 구현)에서 고수준(핵심 비즈니스 정책)을 향해야 합니다.
2. 실무에서 마주하는 아키텍처: 경험과 적용
이론을 실제 프로젝트에 적용하면서 겪은 시행착오와 해결책에 대한 발제는 많은 참석자의 공감을 이끌어냈습니다.
ERD 우선 설계의 함정
보통 새로운 프로젝트를 시작할 때 기능 정의 후 가장 먼저 하는 일은 DB 스키마(ERD)를 그리는 것입니다. 하지만 이는 비즈니스 로직이 데이터베이스 구조에 종속되게 만듭니다. 데이터베이스 결정을 지연시키는 방식을 실제 코드에 적용해 보면 다음과 같은 장점이 있습니다.
- 인터페이스 기반 설계: 저장소 인터페이스(OrderRepository)만 정의하고 핵심 도메인 로직을 먼저 구현합니다.
- In-Memory 저장소 활용: MVP 단계나 테스트 시에는 DB 없이 HashMap 등을 활용한 인메모리 구현체를 주입하여 비즈니스 로직을 검증합니다.
- 플러그인 교체: 훗날 요구사항이 명확해졌을 때 MongoDB나 MySQL 구현체를 만들어 주입(DI)만 변경하면, 도메인 코드는 단 한 줄도 수정할 필요가 없습니다.
무분별한 MSA 도입의 대가
마이크로서비스 아키텍처(MSA)의 트렌드에 따라 도메인별로 DB 인스턴스를 완벽히 분리했던 경험도 공유되었습니다.
- 문제 발생: 시스템을 분리하자 스프링의 @Transactional이 제대로 동작하지 않아 분산 트랜잭션 문제(일부 데이터만 커밋되는 현상)가 발생했습니다.
- 해결 및 교훈: Saga 패턴, 2PC 등을 도입하려다 배보다 배꼽이 커지는 상황을 맞이했고, 결국 DB를 하나로 합치되 컬렉션/테이블 수준에서만 분리하는 구조로 롤백했습니다. 아키텍처의 경계(소스 수준 -> 배포 수준 -> 서비스 수준)는 시스템의 규모와 필요에 따라 점진적으로 승급시켜야 하며, 처음부터 무리하게 서비스 수준의 격리를 시도하는 것은 오버엔지니어링임을 깨닫는 사례였습니다.
배포 수준에서의 의존성 통제
실무에서는 바쁘다는 핑계로, 혹은 주니어 개발자의 실수로 도메인 계층이 인프라 계층을 참조하는 '깨진 유리창' 현상이 쉽게 발생합니다. 이를 원천 차단하기 위해 Gradle 멀티 모듈이나 모노레포의 package.json 의존성 설정을 활용하여, 아예 컴파일 레벨에서 하위 계층 참조를 막아버리는 방법이 효과적이라는 팁이 공유되었습니다.
3. 심층 토론: 데이터베이스는 정말 단순한 플러그인일까?
이날 스터디의 가장 뜨거운 화두는 "DB를 단순히 갈아 끼울 수 있는 플러그인으로 취급하는 것이 현대 소프트웨어 개발에서 현실적인가?"였습니다.
- 클린 아키텍처의 관점: DB는 세부 사항이며 비즈니스 로직은 DB의 존재를 몰라야 한다.
- 현실의 딜레마 (데이터 중심 애플리케이션 관점): 현대 서비스에서는 데이터 자체와 데이터의 모델링(Access Pattern)이 비즈니스의 핵심이 되는 경우가 많습니다. DynamoDB와 같은 NoSQL을 사용할 때는 파티션 키 설계 등 데이터 접근 패턴을 처음부터 고려하지 않으면 개발 자체가 불가능합니다. 또한, 대용량 트래픽 처리나 복잡한 조인 최적화를 위해서는 비즈니스 로직이 DB의 특성을 어느 정도 '인지'하고 있어야만 성능을 달성할 수 있습니다.
- 결론 도출: 마틴 파울러나 로버트 C. 마틴이 주장한 유연성과 추상화는 '테스트 용이성'과 '변경에 대한 민첩성'을 극대화하지만, 그 대가로 잃게 되는 품질 속성(성능, 고도화된 벤더사 기능 활용 등)이 분명 존재합니다. 따라서 상황(글로벌 스케일의 트래픽인지, 빠른 가설 검증이 필요한 MVP인지)에 따라 추상화의 수준과 트레이드오프를 결정하는 것이 엔지니어의 진짜 역량이라는 데 의견을 모았습니다.
4. 마무리
이번 스터디는 『클린 아키텍처』가 제시하는 이상적인 설계 원칙을 배우는 동시에, 그것을 맹목적으로 따르기보다 우리의 실무 환경과 데이터의 특성에 맞게 어떻게 조율할 것인가를 치열하게 고민해 보는 시간이었습니다.
(여담으로, LLM(Claude, Gemini 등)과 Obsidian을 연동하여 자신만의 지식 베이스 아키텍처를 구축하고 활용하는 트렌디한 생산성 향상 방법도 공유되며 즐겁게 마무리되었습니다.)
