클린 아키텍처 6주차 스터디 후기: 선 긋기의 미학, 그리고 로보틱스 실무 적용 (25장~29장)
안녕하세요. 이번 세션에서는 로버트 C. 마틴의 『클린 아키텍처』 25장부터 29장까지의 내용을 다루며, 아키텍처의 '계층과 경계'를 더욱 미시적인 관점에서 파고들었습니다.
이번 주차 스터디가 특별했던 이유는 이론적인 논의를 넘어, 일반적인 웹 백엔드를 벗어난 '로보틱스(Robotics)' 도메인에서의 아키텍처 경계 나누기와 마이크로서비스(MSA) 및 테스트 코드가 실무에서 낳는 딜레마 에 관한 케이스 스터디가 진행되었기 때문입니다. 스터디원들의 고민이 담긴 발제와 토론 내용을 정리하여 공유드립니다.
1. 미시적 관점에서의 선 긋기와 메인(Main) 컴포넌트 (25장~26장)
아키텍처에서 '선을 긋는다(Boundary)'는 것은 시스템의 핵심 규칙이 세부 구현 사항에 오염되지 않도록 의존성의 방향을 통제하고, 언제든 쉽게 교체할 수 있는 플러그인(Plugin) 구조를 만든다는 것을 의미합니다.
동심원의 미시적 분리 (Hunt the Wumpus 사례) 스터디에서는 저자인 엉클 밥(Uncle Bob)이 1972년 텍스트 기반 게임 'Hunt the Wumpus'를 구현해 둔 11년 전 깃허브 레포지토리를 직접 살펴보았습니다. 해당 코드에서는 게임의 '핵심 규칙(도메인)'과 '메시지 출력 방식(UI)'이 철저히 인터페이스로 분리되어 있었습니다. 이를 통해 내부 로직은 단 한 줄도 건드리지 않고, 영문 콘솔 출력 구현체를 '한국어판 출력 구현체'로 손쉽게 갈아끼우는 데모를 확인하며 추상화의 강력함을 체감했습니다.
궁극의 플러그인, 메인(Main) 컴포넌트 아키텍처의 가장 바깥쪽 원에 위치하는 메인 컴포넌트는 시스템의 모든 세부 사항을 알고 의존성을 조립하는 역할을 합니다. 본질적으로 가장 '더러운' 코드들이 모이는 곳이지만, 이 계층이 존재해야만 도메인이 순수성을 유지할 수 있습니다. 현대 웹 개발에서는 스프링(Spring)과 같은 프레임워크의 IoC 컨테이너가 이 조립 역할을 대신 수행하여 개발자의 눈에서 멀어졌을 뿐, 아키텍처적 관점에서 메인 컴포넌트의 역할과 중요성은 여전히 유효하다는 점을 짚어보았습니다.
2. MSA의 환상과 '진짜 결합도'의 비밀 (27장)
많은 조직이 마이크로서비스 아키텍처(MSA)를 도입하면 시스템의 결합도가 낮아지고 유지보수가 유연해질 것이라 기대합니다. 하지만 이번 스터디에서는 이러한 맹신을 경계해야 한다는 깊은 공감대가 형성되었습니다.
MSA는 배포 단위일 뿐, 아키텍처가 아니다 : MSA는 프로세스를 물리적으로 분리하여 배포와 확장의 독립성을 제공할 뿐, 시스템의 본질적인 결합도를 낮추는 마법의 은탄환이 아닙니다.
진짜 결합은 '데이터와 행위'에 있다 : 이커머스 시스템을 예로 들어보겠습니다. 만약 '고객 등급(VIP, 일반 등)'이라는 필드가 하나 추가되었을 때, 주문 서비스, 결제 서비스, 알림 서비스 등 분리된 여러 MSA 팀이 일제히 코드를 수정하고 배포 순서를 맞추기 위해 슬랙에서 전쟁을 치러야 한다면 어떨까요? 이는 물리적으로만 떨어져 있을 뿐, 논리적으로는 강하게 결합된 모놀리식 시스템과 다를 바 없습니다. 결국 서비스의 쪼개짐보다 내부 데이터 구조와 도메인 이벤트의 흐름을 어떻게 설계하느냐가 아키텍처 결합도를 좌우합니다.
3. 깨지기 쉬운 테스트와 테스팅 API (28장)
내부 자료구조를 Set에서 Map으로 변경하는 등 사소한 리팩토링을 진행했을 뿐인데, 수십 개의 단위 테스트가 일제히 깨져버려 난감했던 경험은 개발자라면 누구나 공감할 것입니다.
테스트 주객전도의 위험성 테스트 코드는 시스템의 변경을 돕고 안정성을 보장하기 위해 존재합니다. 하지만 테스트가 시스템의 내부 세부 구조(Private 메서드나 구체적인 자료구조 등)와 너무 강하게 결합되어 있으면, 오히려 아키텍처의 구조적 변경을 가로막는 장애물이 되어버립니다.
테스팅 API (Testing API) 도입 테스트 코드는 의존성 방향의 가장 끝단에 위치하며, 항상 시스템을 향해 의존해야 합니다. 테스트의 독립성을 확보하기 위해서는 시스템 내부 구조의 결합을 우회하여 핵심 '행위(비즈니스 로직)'만을 검증할 수 있도록 돕는 테스트 전용 API 계층을 두는 것이 좋습니다. 이를 통해 구조적 리팩토링이 행위 검증 테스트를 파괴하는 현상을 방지할 수 있습니다.
4. 클린 임베디드 아키텍처와 생생한 케이스 스터디 (29장)
29장은 하드웨어와 펌웨어, 소프트웨어의 경계를 다룹니다. 시간이 지날수록 하드웨어는 낡아가고 펌웨어는 그 하드웨어에 종속되지만, 소프트웨어는 유연하게 변화해야 합니다. 이를 위해 하드웨어 추상화 계층(HAL)을 두게 되는데, 이 개념은 웹 개발과 특수 도메인에서도 훌륭한 인사이트를 제공합니다.
케이스 스터디 1: 웹 백엔드에서의 펌웨어 오염 (MongoDB 트랜잭션)
한 스터디원은 과거 MongoDB의 트랜잭션 락 문제(단일 인스턴스에서만 롤백이 지원되는 한계)를 해결하기 위해, 핵심 도메인 로직을 통째로 뜯어고쳐야 했던 뼈아픈 경험을 공유했습니다. 아키텍처 관점에서 이는 DB라는 '펌웨어(세부 사항)'의 한계가 순수해야 할 '소프트웨어(도메인)'를 오염시킨 전형적인 안티 패턴입니다. 올바른 추상화와 계층 분리가 왜 필수적인지 뼈저리게 느낄 수 있는 사례였습니다.
케이스 스터디 2: 로보틱스 도메인의 시뮬레이션 경계 분리
이번 스터디의 하이라이트였던 로봇 소프트웨어 제어 도메인 사례입니다. 일반적인 웹 개발에서 사이드 이펙트가 'DB 업데이트'라면, 로보틱스에서의 사이드 이펙트는 '실제 물리적인 로봇 팔이 움직이는 것'입니다. 만약 코드를 잘못 실행하여 무거운 로봇이 오작동하면 물리적 충돌이나 막대한 비용 손실이 발생합니다.
따라서 로보틱스 개발에서는 '실제 로봇을 동작시키는 환경'과 '가상의 시뮬레이션 환경'을 아키텍처 수준에서 완벽하게 분리해야 합니다.
해결 방안: 로보틱스 애플리케이션 계층, 로보틱스 도메인 계층, 그리고 유저 도메인 계층을 엄격히 나눕니다. 그리고 하위 인프라 계층을 '물리적 DB/로봇 컨트롤러'와 '인메모리 시뮬레이터'로 구현하여 플러그인처럼 교체할 수 있게 만듭니다.
경계 강제하기: 인간의 실수를 방지하기 위해 소스 코드 작성 단계에서 패키지 간의 가시성을 물리적으로 차단합니다. 이를 통해 시뮬레이션 모드일 때 개발자의 부주의로 실제 하드웨어 제어 로직이 호출되는 치명적인 결함을 컴파일 단계에서 차단하는 견고한 아키텍처를 설계할 수 있습니다.
5. 실무 적용의 딜레마와 자유 토론
발제 이후 이어진 자유 토론에서는 아키텍처 이론을 실무 현장에 적용할 때 부딪히는 현실적인 벽과, AI 시대 개발자의 진화에 대한 이야기꽃이 피었습니다.
리팩토링의 두려움과 휴먼 엔지니어링 "아키텍처를 개선해야 하는 건 아는데, 잘 돌아가는 레거시를 건드렸다가 알 수 없는 곳에서 장애가 터지면 감당할 수 있을까?" 하이 리스크 로우 리턴인 구조 개선 작업 앞에서 개발자들은 망설일 수밖에 없습니다. 시스템을 변화시키기 위해서는 기술적인 완벽함도 중요하지만, 변경의 필요성을 설득하고 조직의 공감대를 이끌어내는 소통과 신뢰(휴먼 엔지니어링)에 대해 이야기나누었습니다.
AI 시대, 코더(Coder)에서 설계자로의 진화 최근 Claude 4.7 Opus와 같은 압도적인 성능의 LLM 도구들이 긴 컨텍스트를 완벽히 이해하고 코드를 생성해 내면서, 개발의 패러다임이 급변하고 있습니다. 이제 개발자는 직접 타이핑에 매몰되는 것이 아니라, 전체 시스템의 아키텍처와 경계를 어떻게 나눌지 치열하게 기획하고, AI를 검토자이자 페어 프로그래머로 활용하는 '리서처(Researcher)'이자 '아키텍트(Architect)'로 진화하고 있다는 의견들이 오갔습니다.
마무리
클린 아키텍처 스터디의 공식적인 챕터 리뷰가 막바지를 향해 달려가고 있습니다. 웹 백엔드, 로보틱스 등 각자가 몸담은 도메인은 달라도, 잦은 변경의 폭풍 속에서 비즈니스의 핵심 가치를 안전하게 보호하려는 소프트웨어 엔지니어링의 본질은 완벽히 동일하다는 것을 깊이 깨달을 수 있는 소중한 시간이었습니다.
다음 세션에서는 책의 남은 챕터를 마무리하고, 앞으로 어떤 주제(데이터 지향 프로그래밍, 인프라스트럭처, DDD 등)로 함께 성장을 이어나갈지 논의할 예정입니다. 감사합니다!