이번 모임에서는 『클린 아키텍처』의 후반부인 30장부터 34장까지를 중심으로 이야기를 나눴습니다. 책의 표현을 빌리면 이번 범위는 "세부 사항"을 다루는 파트였습니다.
개발자는 매일 데이터베이스를 다루고, 웹 화면을 만들고, 프레임워크 위에서 코드를 작성합니다. 그래서 이런 도구들은 너무 익숙하고, 때로는 애플리케이션의 본질처럼 느껴집니다. 하지만 클린 아키텍처는 바로 그 익숙한 것들을 한 걸음 떨어져 보라고 말합니다. 데이터베이스는 중요한 도구이지만 중심 정책은 아니고, 웹은 사용자를 만나는 중요한 창구이지만 유스케이스 자체는 아니며, 프레임워크는 생산성을 높여 주지만 우리 시스템의 핵심 규칙을 대신 책임져 주지는 않는다는 것입니다.
이번 스터디에서는 책의 내용을 요약하는 것에서 그치지 않고, 각자의 업무 경험과 최근 AI 개발 도구의 변화까지 함께 엮어 보았습니다. 특히 "무엇을 중심에 두고, 무엇을 바깥으로 밀어낼 것인가"라는 질문이 여러 사례를 통해 반복해서 등장했습니다.
---
## 이번 스터디에서 다룬 내용
이번 모임에서는 크게 세 흐름으로 발표와 토론이 이어졌습니다.
첫 번째로는 데이터베이스, 웹, 프레임워크가 왜 세부 사항으로 다뤄져야 하는지 정리했습니다. 데이터베이스의 역사와 물리적 디스크 한계, 웹 아키텍처가 중앙 집중과 단말 분산 사이를 오가며 변화해 온 흐름, 프레임워크가 제공하는 편의와 그에 따르는 결합의 위험을 함께 살펴보았습니다.
두 번째로는 코드를 조직하는 네 가지 방식에 대해 이야기했습니다. 계층 기반 패키지, 기능 기반 패키지, 포트와 어댑터 아키텍처, 컴포넌트 기반 아키텍처가 각각 어떤 의도를 갖고 있는지, 그리고 실제 프로젝트에서는 어떤 장단점이 있는지 비교했습니다. 여기서는 단순히 폴더를 어떻게 나눌지가 아니라, 코드 구조가 시스템의 의도를 어떻게 드러내는지가 중요한 주제였습니다.
세 번째로는 실무에서 경계가 흐려지는 사례를 다뤘습니다. 감사 로그, 서비스 로그, 클라우드 네이티브 아키텍처, 프레임워크 의존, AI 코딩 에이전트와 스펙 주도 개발까지 다양한 이야기가 이어졌습니다. 책의 원칙은 선명하지만, 현실의 시스템은 늘 애매한 결정을 요구합니다. 이번 스터디는 그 애매함을 서로의 사례로 풀어 보는 시간이었습니다.
## 데이터베이스는 세부 사항이다
책에서 가장 먼저 다룬 주제는 데이터베이스였습니다. 많은 애플리케이션에서 데이터베이스는 너무 중요한 위치를 차지합니다. 테이블 구조를 먼저 고민하고, 엔티티를 만들고, ORM을 붙이고, 그 위에 서비스 로직을 올리는 방식은 익숙합니다. 그러다 보면 어느 순간 데이터베이스 구조가 애플리케이션의 중심처럼 느껴집니다.
책이 분명히 구분하는 지점은 데이터 모델과 데이터베이스 제품입니다. 저자가 세부 사항이라고 부르는 것은 데이터베이스 제품이지 데이터 모델이 아닙니다. 오히려 데이터 모델은 업무 규칙과 직접 맞닿아 있는 핵심 영역에 가깝습니다. 어떤 정보가 존재하고, 그것들이 어떤 관계를 맺고, 어떤 규칙에 따라 변화하는지는 도메인 그 자체를 구성하는 요소이기 때문입니다. 반면 Oracle을 쓸지 PostgreSQL을 쓸지, Redis를 붙일지, 특정 ORM에 얼마나 기대는지는 그 핵심을 둘러싸는 교체 가능한 결정입니다.
이 구분은 단순하지만 실무에서는 자주 흐려집니다. 예를 들어 특정 데이터베이스가 제공하는 기능을 서비스 로직 안에 깊게 끌어들이면, 도메인 규칙과 저장 기술이 서로 묶이게 됩니다. 처음에는 빠르게 만들 수 있지만, 나중에 저장소를 바꾸거나 확장해야 할 때 비용이 커집니다.
스터디에서는 DBMS가 등장한 배경도 함께 이야기했습니다. 과거 하드디스크는 물리적으로 회전하는 장치였고, 원하는 위치의 데이터를 읽기 위해서는 헤드 이동과 회전 지연을 피할 수 없었습니다. DBMS와 파일 시스템은 이런 물리적 한계를 줄이기 위해 다양한 알고리즘과 캐시 전략을 발전시켜 왔습니다. B-Tree 같은 자료구조도 결국 디스크 I/O를 줄이고 검색 비용을 낮추기 위한 맥락에서 이해할 수 있습니다.
이 관점에서 보면 DBMS는 하드웨어의 제약을 감추기 위한 훌륭한 추상화이기도 합니다. 개발자는 매번 디스크 섹터와 회전 지연을 직접 고민하지 않아도 됩니다. 하지만 그 추상화가 편리하다고 해서, 특정 DBMS 자체가 업무 규칙의 중심이 되어도 된다는 뜻은 아닙니다. 데이터 모델은 중요하지만, 데이터베이스 제품은 경계 바깥에 둘 수 있어야 한다는 점이 이번 논의의 핵심이었습니다.
## 웹은 입출력 장치다
웹에 대한 장도 흥미로운 토론으로 이어졌습니다. 책에서는 웹을 세부 사항이라고 말합니다. 처음 들으면 조금 낯설 수 있습니다. 요즘 대부분의 서비스는 웹 또는 모바일 화면을 통해 사용자와 만나기 때문입니다. 사용자 경험도 중요하고, 화면 흐름도 중요하고, 프론트엔드 구조도 복잡합니다.
그럼에도 웹을 세부 사항으로 본다는 말은 웹을 중요하지 않게 본다는 뜻이 아니었습니다. 핵심은 웹이 유스케이스 자체가 아니라 유스케이스를 호출하는 하나의 입출력 방식이라는 점이었습니다.
사용자가 아무리 화려한 웹 화면 안에서 여러 상호작용을 하더라도, 서버 또는 애플리케이션 코어 입장에서는 마지막에 특정 행위가 남습니다. 주문을 생성한다, 결제를 요청한다, 검색을 실행한다, 파일을 업로드한다, 권한을 검증한다 같은 행위입니다. 화면의 애니메이션, 폼의 배치, 버튼의 스타일은 바뀔 수 있지만, 시스템이 수행해야 하는 유스케이스는 그보다 더 안쪽에 있습니다.
이야기는 컴퓨팅의 무게중심이 어디에 놓이느냐로도 확장되었습니다. 메인프레임과 더미 터미널, PC, 클라이언트-서버, SPA, 클라우드처럼 역사는 중앙 집중과 단말 분산 사이를 계속 오갔습니다. 스터디에서는 이 흐름을 LLM 시대와도 연결했습니다. 지금은 거대한 중앙 서버의 모델을 API로 사용하는 방식이 강하지만, 동시에 로컬 LLM과 온디바이스 AI도 계속 시도되고 있습니다.
결국 웹이든 모바일이든 로컬 LLM이든 클라우드 API든 중요한 질문은 같습니다. "이 바깥쪽 장치가 바뀌어도 내부 유스케이스는 유지될 수 있는가?" UI는 계속 바뀌고, 실행 환경도 바뀌고, 클라이언트와 서버 사이의 책임 분배도 바뀝니다. 그렇기 때문에 애플리케이션의 중심 정책을 특정 웹 구현에 묶어 두지 않는 것이 중요하다는 결론으로 이어졌습니다.
## 프레임워크는 생산성을 주지만 책임져 주지는 않는다
프레임워크는 개발자에게 큰 생산성을 줍니다. 인증, 라우팅, 데이터 접근, 의존성 주입, 테스트, 배포 설정까지 많은 부분을 대신 처리해 줍니다. 하지만 책은 프레임워크도 세부 사항이라고 말합니다. 프레임워크의 저자는 우리의 비즈니스 규칙을 책임져 주지 않습니다. 프레임워크는 자신이 정한 방향과 생태계 안에서 편의를 제공할 뿐입니다.
스터디에서는 Spring Security와 같은 익숙한 사례가 나왔습니다. 인증과 권한을 구현할 때 프레임워크 기능을 쓰는 것은 자연스럽습니다. 하지만 핵심 유스케이스가 특정 보안 프레임워크의 API를 직접 알고 있어야 한다면 결합이 강해집니다. 실제로 중요한 것은 "이 사용자가 이 행위를 할 권한이 있는가"이지, 그 판단이 반드시 특정 프레임워크 타입을 통해 이뤄져야 한다는 뜻은 아닙니다.
LLM 관련 프레임워크 사례도 다뤄졌습니다. 예를 들어 여러 모델 제공자의 API를 쉽게 호출하게 해주는 프레임워크를 쓰면 구현은 빨라집니다. 하지만 서비스 코드 안에 해당 프레임워크가 바로 들어오면, 나중에 직접 API 호출로 바꾸거나 다른 구현으로 교체하기가 어려워집니다. 추상화 지점을 하나 두고, 내부 정책은 그 추상화에만 의존하도록 만들면 프레임워크는 바깥쪽 구현으로 남을 수 있습니다.
여기서 중요한 것은 프레임워크를 피하자는 것이 아닙니다. 오히려 좋은 프레임워크는 써야 합니다. 다만 프레임워크가 애플리케이션의 중심을 차지하도록 방치하지 말자는 이야기입니다. 프레임워크를 사용하는 것과 프레임워크에 종속되는 것은 다릅니다. 이번 스터디에서는 그 차이를 실제 경험을 통해 확인할 수 있었습니다.
## 코드 구조는 시스템의 의도를 드러내야 한다
이번 범위에서는 코드를 조직하는 방식도 중요하게 다뤘습니다. 같은 기능을 구현하더라도 패키지 구조가 무엇을 기준으로 나뉘어 있는지에 따라 시스템을 읽는 방식이 달라집니다.
계층 기반 패키지는 익숙한 방식입니다. controller, service, repository처럼 기술적 역할에 따라 코드를 나눕니다. 단순하고 시작하기 쉽지만, 패키지 이름만 봐서는 이 애플리케이션이 어떤 업무를 다루는지 알기 어렵습니다. 주문, 결제, 회원, 배송 같은 도메인은 여러 계층에 흩어지게 됩니다.
기능 기반 패키지는 도메인이나 유스케이스를 중심으로 코드를 나눕니다. 주문과 관련된 컨트롤러, 서비스, 저장소 코드가 한 영역에 모이면, 패키지 구조 자체가 업무 도메인을 설명합니다. 특정 기능을 수정해야 할 때 둘러봐야 하는 범위도 더 명확해질 수 있습니다.
포트와 어댑터 아키텍처는 내부와 외부의 경계를 더 선명하게 세웁니다. 도메인과 유스케이스는 내부에 두고, 웹 컨트롤러나 데이터베이스 접근 코드는 외부 어댑터로 둡니다. 의존성은 외부에서 내부로 향해야 하며, 내부 정책이 외부 도구를 직접 알지 않도록 만드는 것이 핵심입니다.
컴포넌트 기반 아키텍처는 주요 비즈니스 능력을 하나의 컴포넌트로 응집시키는 방식으로 논의되었습니다. 예를 들어 주문과 관련된 업무 로직이 하나의 컴포넌트 안에 모이면, 외부는 그 내부 구현을 몰라도 주문 기능을 사용할 수 있습니다. 다만 현실에서는 도메인 간 의존이 완전히 사라지기 어렵고, 지나치게 분리하면 오히려 오버 엔지니어링이 될 수 있다는 의견도 있었습니다.
이 논의에서 중요한 점은 "정답인 폴더 구조"를 찾는 것이 아니었습니다. 코드 구조는 시스템이 어떤 일을 하는지, 무엇을 보호하려고 하는지, 어떤 방향으로 의존성이 흘러야 하는지를 드러내야 합니다. 구조는 단순한 정리가 아니라 설계 의도 그 자체가 될 수 있습니다.
## 접근 제어자도 아키텍처의 일부다
접근 제어자에 대한 이야기도 인상적이었습니다. 패키지를 잘 나누고 아키텍처를 그럴듯하게 설계해도, 모든 클래스와 생성자와 메서드를 public으로 열어 두면 외부 코드가 내부 구현에 직접 접근할 수 있습니다. 그러면 계층 기반, 기능 기반, 포트와 어댑터, 컴포넌트 기반이라는 구분이 실제 코드에서는 흐려집니다.
접근 제어자는 단순히 문법적인 장치가 아닙니다. 잘 사용하면 컴파일러 수준에서 아키텍처를 어느 정도 강제할 수 있습니다. 외부에는 인터페이스만 열고, 구현체와 내부 세부 로직은 패키지 내부에 숨길 수 있습니다. 그렇게 하면 의도하지 않은 의존이 생기는 것을 줄일 수 있습니다.
스터디에서는 테스트 코드와 접근 제어자의 긴장도 함께 이야기했습니다. 내부 메서드를 테스트하려면 접근 범위를 넓히고 싶어지는 순간이 있습니다. 하지만 테스트 편의를 위해 내부 구현을 public으로 열어 두면 캡슐화가 깨질 수 있습니다. 반대로 행위 중심으로 테스트하면 내부 구현을 숨길 수 있지만, 테스트 작성 방식이 달라져야 합니다.
결국 이 문제 역시 절대적인 답보다는 팀의 기준이 중요해 보였습니다. 어떤 것은 행위 중심으로 테스트하고, 어떤 것은 테스트 전용 접근 방식을 둘 수도 있습니다. 중요한 것은 "테스트 때문에 구조가 무너지고 있는가", 또는 "캡슐화라는 이름으로 테스트 가능성을 지나치게 낮추고 있는가"를 계속 점검하는 일입니다.
## 실무에서는 경계가 늘 깔끔하지 않다
책의 원칙은 명확하지만, 실무에서는 경계가 늘 깔끔하게 나뉘지 않습니다. 이번 스터디에서 가장 현실적인 토론은 로그와 감사 이력에 대한 이야기였습니다.
예를 들어 운영자가 장애 원인을 추적할 때 보는 로그와, 사용자가 자기 데이터에 가해진 변경 이력을 확인할 때 보는 로그를 나란히 놓고 보면 차이가 분명해집니다.
전자는 trace id, 응답 시간, 에러 스택 같은 기술 정보가 중심이고, 중앙 로그 저장소에 던져 두고 필요할 때 검색하면 되는 성격입니다. 누가 읽는지가 정해져 있고, 그 사람들은 시스템 내부의 언어에 익숙합니다.
후자는 다릅니다. "누가, 어떤 자원에, 어떤 변경을 가했는가"를 도메인 언어로 기록해야 하고, 시스템 내부에 익숙하지 않은 사람도 읽을 수 있어야 합니다. 책임 소재를 확인하는 근거가 되기도 합니다. 같은 "로그"라는 단어를 쓰지만, 이건 사실상 도메인 행위를 기록하는 일에 가깝습니다.
이렇게 보면 "로그는 무조건 바깥이다" 또는 "감사 이력은 무조건 도메인이다"처럼 단정하기 어렵습니다. 시스템 로그, 감사 로그, 비즈니스 이벤트는 표면적으로 비슷해 보여도 경계의 안과 밖이 다릅니다. 어떤 것은 외부 인프라에 던져도 충분하고, 어떤 것은 도메인 이벤트로 모델링해야 합니다.
클라우드 네이티브 아키텍처도 비슷한 질문을 던졌습니다. S3, Lambda, managed database, ETL, 분석 도구 등을 처음부터 전제로 설계하는 시스템은 특정 클라우드에 강하게 묶입니다. 이때 클라우드는 단순한 세부 사항일까요, 아니면 제품 전략의 일부일까요? 스터디에서는 현실적으로 특정 클라우드에 종속되는 선택을 할 수는 있지만, 그 선택이 핵심 정책을 어디까지 잠그는지 의식해야 한다는 쪽으로 이야기가 이어졌습니다.
## AI 개발 도구와 클린 아키텍처
후반부에는 AI 개발 도구에 대한 이야기도 자연스럽게 이어졌습니다. 흥미로웠던 점은 이 논의 역시 클린 아키텍처의 주제와 연결되었다는 것입니다.
AI에게 "이런 스타일로 작성해 줘", "이런 컨벤션을 지켜 줘", "너는 이런 역할이야"라고 알려주는 방식은 유용합니다. 이런 지침은 일종의 소프트 하네스라고 볼 수 있습니다. 하지만 코딩 에이전트에게는 더 단단한 피드백 장치도 필요합니다. 테스트 커버리지가 떨어지면 실패하게 만들고, 린트가 깨지면 통과하지 못하게 하고, 빌드가 실패하면 바로 수정하게 하는 식입니다. 이런 하드 하네스는 AI가 빠르게 잘못을 확인하고 방향을 고치게 만듭니다.
이 관점은 아키텍처에도 그대로 적용됩니다. "의존성을 잘 지켜 줘"라고 말하는 것만으로는 부족할 수 있습니다. 정적 분석, 테스트, 모듈 경계, 접근 제어자, CI 검증 같은 장치가 함께 있어야 합니다. 사람에게도 AI에게도 좋은 의도만으로는 부족하고, 빠르게 실패하고 고칠 수 있는 피드백 루프가 필요합니다.
디자인 도구와 MCP를 활용한 실습 경험도 공유되었습니다. 디자인 토큰과 인터페이스를 두고, 실제 UI 구현이나 디자인 도구 연동은 바깥쪽 세부 사항으로 다루려는 시도였습니다. 웹 UI를 언제든 교체할 수 있게 만들고, 디자인 시스템을 코드와 연결하려는 접근은 "웹은 세부 사항이다"라는 책의 메시지와도 맞닿아 있었습니다.
다만 핸즈온을 진행할 때는 현실적인 어려움도 컸다고 합니다. 참여자마다 개발 환경이 다르고, Node 설치 여부도 다르고, MCP 권한 설정도 필요하고, 행사장에서는 화면이 잘 보이지 않거나 네트워크가 불안정할 수 있습니다. 그래서 핸즈온은 생각보다 훨씬 더 작게 가져가야 한다는 회고도 있었습니다. 이 역시 좋은 설계와 좋은 실행 사이의 간극을 보여 주는 사례였습니다.
## 결국 중요한 것은 바뀌는 것과 지켜야 할 것을 나누는 일
이번 스터디를 관통한 질문은 하나였습니다.
무엇이 자주 바뀌는가?
무엇을 쉽게 교체할 수 있어야 하는가?
무엇은 시스템의 중심에 남아야 하는가?
데이터베이스 제품은 바뀔 수 있습니다. 웹 프레임워크도 바뀔 수 있습니다. 인증 라이브러리도 바뀔 수 있고, LLM 호출 프레임워크도 바뀔 수 있습니다. 디자인 도구도, 클라우드 서비스도, AI 코딩 도구도 바뀔 수 있습니다.
하지만 업무 규칙과 유스케이스는 그보다 더 안쪽에서 보호되어야 합니다. 물론 도메인도 바뀝니다. 오히려 비즈니스는 빠르게 바뀌기 때문에, 외부 기술의 제약에 덜 묶여 있어야 합니다. 도메인이 변할 때 데이터베이스, 프레임워크, UI 때문에 발목 잡히지 않도록 만드는 것이 경계를 세우는 이유입니다.
클린 아키텍처가 말하는 독립성은 특정 기술을 싫어하자는 태도가 아닙니다. 좋은 도구를 적극적으로 쓰되, 그 도구가 중심 정책을 침범하지 않게 하자는 태도에 가깝습니다. 도구는 바뀌고, 환경은 바뀌고, 유행은 바뀝니다. 그래서 더더욱 중심을 어디에 둘지 정해야 합니다.
## 마무리
이번 클린 아키텍처 스터디는 책의 후반부를 읽으며, 우리가 매일 쓰는 도구들을 다시 바라보는 시간이었습니다. 데이터베이스, 웹, 프레임워크, 클라우드, AI 도구는 모두 중요합니다. 하지만 중요하다고 해서 모두 중심이 되어야 하는 것은 아닙니다.
오히려 자주 쓰고 강력한 도구일수록 더 조심해야 합니다. 편리함은 결합을 만들기 쉽고, 결합은 변화의 속도를 늦춥니다. 좋은 아키텍처는 도구를 배척하는 구조가 아니라, 도구를 잘 쓰면서도 바꿀 수 있는 여지를 남기는 구조입니다.
이번 스터디를 통해 책의 원칙이 과거의 객체지향 설계 이야기로만 머무르지 않는다는 점도 확인할 수 있었습니다. AI 코딩 에이전트, MCP, 디자인 시스템, 클라우드 네이티브 환경에서도 결국 같은 질문이 반복됩니다. 어디까지가 핵심이고, 어디부터가 세부 사항인가. 무엇을 보호하고, 무엇을 교체 가능하게 만들 것인가.
클린 아키텍처 스터디는 이번 범위를 끝으로 한 사이클을 마무리했습니다. 다음 스터디에서는 새로운 주제로 다시 모여, 책과 실무 사이의 거리를 함께 좁혀 보려고 합니다.