알림
한빛미디어 서평단 <나는리뷰어다> 활동을 위해 도서를 협찬받아 작성된 서평입니다.
음.. 이번에는 꽤 난이도 있는 책을 선택하게 됐습니다.
요즘은 LLM이 코드도 잘 짜주고 개발 생산성도 많이 올라갔지만, 아직까지는 아키텍처나 설계 패턴을 처음부터 체계적으로 잡아주는 영역은 부족하다고 느껴졌습니다. (물론 이 부분도 점점 좋아지고 있는 것 같긴 합니다.)
그래서 이번에는 “클라우드 애플리케이션 아키텍처 패턴”을 읽고 나름대로 정리해보려고 합니다.
O’Reilly에서 나오는 동물책들은 내용은 탄탄하지만, 개인적으로는 난이도가 꽤 높게 느껴졌습니다. 한 번에 이해하기보다는 실무 경험과 연결해서 천천히 곱씹어야 하는 책이라는 느낌이었습니다.
보통 웹 아키텍처를 이야기할 때 모놀리식과 MSA를 많이 비교합니다.
하지만 이 선택은 단순히 트렌드를 따르기보다는, 프로젝트의 성격이나 트래픽 규모 등을 충분히 고민한 뒤 결정하는 것이 맞다고 생각합니다.
이전 프로젝트에서 MSA를 적용해본 경험이 있습니다. Backend 8개, Frontend 6개를 운영했는데, 팀원은 3명이었습니다.
돌이켜보면 점점 감당이 어려워졌고, 중복 코드도 많이 생겼습니다. 당시에는 나름대로 최선의 선택이라고 생각했지만, 지금 기준에서는 아쉬운 부분이 많습니다.
결과적으로 유지보수 난이도는 상당히 높았습니다. 한 사람이 3~4개의 서비스를 동시에 관리해야 했고, 배포, 장애 대응, API 연동 등 관리 포인트가 크게 늘어났습니다.
프로젝트를 진행하면서 스프링 마이크로서비스 코딩 공작소 도서 스터디를 병행했고, 넷플릭스 OSS 기반의 Spring Cloud 구조도 접해볼 수 있었습니다.
Eureka(Service Discovery), API Gateway, Config Server, 분산 추적과 같은 구성 요소들을 그때 함께 적용했더라면 운영 부담을 조금은 줄일 수 있지 않았을까 하는 아쉬움도 있습니다.
다만, 당시 인력과 상황을 고려하면 이러한 구조를 실제로 도입하고 안정적으로 운영하는 것 역시 쉽지 않았을 것 같습니다.
특히 서비스가 여러 개로 나뉘다 보니, 각 서비스의 위치(API 호출 주소)를 관리하는 문제, 공통 설정을 일관되게 유지하는 부분, 그리고 인증/인가 처리 등에서 반복적인 작업이 계속 발생했습니다.
이런 부분에서 Spring Cloud 기반의 서비스 디스커버리, 중앙 설정 관리, API Gateway를 활용했다면 어느 정도 복잡도를 줄일 수 있었을 것 같습니다.
또한 Vault와 같은 비밀정보 관리 도구를 함께 사용했다면, 환경별 설정이나 보안 정보 관리도 더 안정적으로 운영할 수 있었을 것이라는 생각이 들었습니다.
물론 이러한 구성 요소들을 도입한다고 해서 모든 문제가 해결되는 것은 아니며, 오히려 또 다른 복잡도를 가져올 수도 있습니다. 결국 선택의 문제라고 생각합니다.
그럼에도 불구하고, 마이크로서비스를 제대로 운영하려면 단순히 서비스를 나누는 것에서 끝나는 것이 아니라 이를 뒷받침하는 인프라와 도구까지 함께 고려해야 한다는 점을 느꼈습니다.
이러한 경험을 바탕으로 보면.. 규모가 작은 프로젝트나 개인 프로젝트의 경우 초기 서비스는 모놀리식으로 시작하는 것이 더 합리적이라고 생각합니다.
개발 속도가 빠르고 관리 포인트가 적으며 변경 대응도 쉽기 때문입니다. 서비스가 성장하면 그때 점진적으로 분리하는 것이 현실적인 접근이라고 생각합니다.
요즘은 특히 빠르게 서비스를 만들고 시장 반응을 확인하는 것이 더 중요하다고 느껴집니다. 이후 필요에 따라 아키텍처를 점진적으로 개선해 나가는 것이 더 효율적인 전략이 아닐까 생각합니다.
이제 각 장에서 인상 깊었던 내용을 간단히 정리해보겠습니다.
추가적으로 내용이 방대하다 보니 일부 장은 가볍게 넘어간 부분도 있습니다. 관심있는 장은 조금 더 자세히 정리했습니다.
1장 클라우드 애플리케이션
클라우드 환경이 기본이 된 요즘, 애플리케이션 아키텍처도 그에 맞춰 달라져야 한다는 걸 짚고 넘어가는 장이었습니다.
과거처럼 서버 한 대 사서 띄워놓고 끝나는 게 아니라, 갑작스러운 트래픽 변화에 유연하게 대응(탄력성)하고, 장애가 발생해도 서비스가 멈추지 않도록 복원력을 갖추는 게 핵심이더라고요.
특히 인프라를 코드로 관리(IaC)하면서 수동 개입을 최소화하고, 시스템 스스로 확장과 복구를 수행하는 구조를 짜야 한다는 점이 기억에 남습니다.
2장 애플리케이션 아키텍처
2.1 애플리케이션 아키텍처란
이 장에서는 소프트웨어 아키텍처의 개념과 함께 아키텍처에서 발생하는 다양한 트레이드오프, 컴포넌트 관련 용어, 그리고 대표적인 아키텍처 패턴들에 대해 설명합니다.
특히 아키텍처 패턴을 설명하면서 저자가 자주 사용하는 표현이 있는데, 바로 커다란 진흙 덩어리(Big Ball of Mud)입니다. 쉽게 말해 구조 없이 뒤섞인 코드, 흔히 말하는 잡탕 코드를 의미합니다.
이 부분을 읽으면서 개인적으로 많이 공감됐습니다.
예전에 레거시 프로젝트를 진행하면서 하나의 .jsp 파일에 수천 줄, 많게는 만 줄이 넘는 코드가 들어가 있는 경우를 본 적이 있는데, 그런 코드는 구조를 파악하는 것 자체가 부담스럽고, 수정하는 것도 상당히 어렵습니다.
이런 경험이 있다 보니 왜 이런 표현을 사용하는지 바로 이해가 됐습니다.
2.2 커다란 진흙 덩어리
애자일 개발은 새로운 프로젝트를 시작할 때 완벽한 구조를 먼저 만드는 것이 아니라, 최소한의 기능을 빠르게 구현한 뒤 사용자 피드백을 기반으로 점진적으로 개선해 나가는 방식을 권장합니다.
이론적으로는 매우 이상적인 방식이지만 실제 프로젝트에서는 요구사항이나 기능, 디자인은 계속 바뀌는 반면 일정은 거의 변하지 않는 경우가 많아 현실적으로 적용하기 쉽지 않다는 생각도 들었습니다.

커다란 진흙 덩어리 아키텍처는 말 그대로 구조화된 설계를 최소화하고, 빠르게 동작하는 코드를 만드는 데 집중하는 방식입니다.
때로는 기존 코드를 복사해서 기능을 추가하는 방식도 포함됩니다.
처음에는 다소 무질서하게 보일 수 있지만, 빠르게 결과물을 만들어야 하는 상황에서는 오히려 가장 현실적인 선택이 될 수도 있습니다.
저자 역시 이 아키텍처를 무조건 나쁜 것으로 보지 않습니다.
오히려 가장 단순한 아키텍처는 아키텍처가 없는 것이라는 관점에서, 초기 단계에서는 이런 접근이 효과적일 수 있다고 설명합니다.
빠르게 동작하는 최소 기능을 만들고, 이후 필요에 따라 점진적으로 구조를 개선해 나가는 방식입니다.
다만 단점도 분명합니다.
시간이 지날수록 코드 간 의존성이 복잡하게 얽히게 되고, 유지보수가 매우 어려워집니다.
결국 어느 시점이 되면 구조를 정리하거나 재설계해야 하는 상황이 발생하게 됩니다.
흥미로운 점은 PayPal과 같은 대형 서비스도 처음에는 이러한 모놀리식 구조, 즉 일종의 “진흙 덩어리” 형태에서 시작했다는 것입니다.
이후 서비스 규모가 커지면서 점진적으로 모듈화, 분산 시스템, 그리고 마이크로서비스 아키텍처로 발전해 나갔습니다.
그래도 페이팔(paypal) 같은 업체에서도 처음에는 진흙 덩어리 아키텍처에서 시작해 모듈화되고 분산 시스템을 거쳐 마이크로서비스로 변모했는지 과정을 소개(https://www.youtube.com/watch?v=KwTxhG4OMlI - postman에서 발표한 영상인 것 같네요)하기도 합니다.
아래는 AI가 해당 유튜브 내용을 요약한 내용이에요.
정보
PayPal은 초기에는 하나의 큰 모놀리식 구조로 서비스를 운영했습니다. 이 방식은 구조가 단순하고 개발과 배포가 쉬운 장점이 있었지만, 서비스가 성장하면서 트래픽이 증가하고 시스템이 복잡해지면서 확장성과 유지보수 측면에서 한계를 겪게 됩니다.
이러한 문제를 해결하기 위해 PayPal은 마이크로서비스 아키텍처로 전환했습니다. 기능을 여러 개의 작은 서비스로 나누어 각각 독립적으로 개발하고 배포할 수 있게 되면서, 확장성과 개발 속도는 크게 개선되었습니다.
하지만 동시에 서비스 간 통신, 데이터 일관성, 장애 대응 등 분산 시스템에서 발생하는 복잡도가 크게 증가했습니다. 단순히 서비스를 나누는 것만으로는 문제가 해결되지 않았고, 이를 관리하기 위한 공통 플랫폼과 운영 체계가 함께 필요하게 되었습니다.
결국 이 사례를 통해 느낄 수 있는 점은, 마이크로서비스는 무조건 좋은 선택이 아니라 상황에 따라 신중하게 결정해야 한다는 것입니다. 서비스 규모와 팀의 역량, 운영 환경을 고려하지 않으면 오히려 복잡도만 증가할 수 있습니다.
3장 클라우드 네이티브 애플리케이션
컨테이너(Docker/Kubernetes), CI/CD 파이프라인, 그리고 데브옵스(DevOps) 문화까지, 클라우드 생태계에서 서비스가 어떻게 살아숨쉬는지 보여주는 장입니다.
흥미로웠던 건 “장애는 반드시 발생한다"는 전제(Design for Failure)를 깔고 간다는 점이었어요.
장애를 막으려고 끙끙대기보다, 장애가 났을 때 얼마나 빨리 복구하고 롤백할 수 있느냐에 초점을 맞추는 거죠.
결국 수동으로 한 땀 한 땀 관리하는 시대는 지났고 파이프라인을 통한 자동화가 살 길이라는 걸 다시 한 번 실감했습니다.
4장 마이크로서비스 아키텍처
모놀리식에 비해 확장이 편하고 팀별로 독립적인 배포가 가능하다는 달콤한 장점 뒤에는, 네트워크 지연, 서비스 간 복잡한 트랜잭션 처리, 분산 모니터링이라는 어마어마한 운영 비용이 숨어 있다는 걸 책에서도 날카롭게 지적하고 있습니다.
단순히 “크기가 커서 쪼갠다"가 아니라, 통신 방식이나 데이터 정합성을 어떻게 보장할지부터 철저히 설계되지 않으면 오히려 팀의 발목을 잡을 수 있는 양날의 검이라는 생각이 들었습니다.
5장 마이크로서비스 설계
“어떻게 잘 쪼갤 것인가?“에 대한 해답을 어느 정도 제시해주는 곳이 바로 이 장입니다.
도메인 주도 설계(DDD)의 바운디드 컨텍스트(Bounded Context) 개념을 가져와서 비즈니스 경계에 맞춰 서비스를 나누는 구체적인 방법론을 설명합니다.
데이터베이스도 서비스별로 완전히 분리해야 느슨한 결합이 완성된다는 점을 여러 번 강조하는데, 이게 막상 실무에서 적용하려면 조인(Join)을 못 해서 상당히 골치가 아프거든요.
책에서는 이런 데이터를 어떻게 동기화하고 API로 잘 묶어낼 지 설계적 관점에서 다뤄주어서 꽤나 흥미롭게 읽은 파트입니다.
6장 이벤트 주도 아키텍처
MSA 환경에서 각 서비스들이 API로 쫀쫀하게 묶여 있으면 결국 하나가 죽을 때 다 같이 죽는 대참사가 일어날 수 있습니다.
이 장에서는 Kafka 같은 메시지 브로커를 중간에 두고 이벤트를 발행/구독(Pub/Sub)하는 비동기 방식을 대안으로 제시합니다.
이렇게 하면 서비스 간 결합도는 확 낮추면서 확장성은 끌어올릴 수 있죠.
하지만 이벤트가 꼬이거나 유실될 때, 디버깅을 위해 로직 점프를 따라가다 보면 머리가 아파옵니다.
눈에 즉각적으로 보이지 않는 흐름을 어떻게 추적할지가 EDA(Event-Driven Architecture, 이벤트 기반 아키텍처) 패턴을 도입할 때의 가장 큰 숙제가 아닐까 싶습니다.
7장 클라우드 네이티브 스토리지
데이터베이스 엔지니어가 아니더라도 반드시 알아야 할 CAP 이론과 최종 일관성(Eventual Consistency) 모델에 대해 다룹니다.
클라우드에선 보통 여러 스토리지나 분산 DB를 엮어 쓰기 마련인데 이때 “데이터가 항상 일치해야 하는가?” vs “데이터가 일시적으로 안 맞더라도 서비스가 죽지 않고 가용한가?“의 딜레마에 부딪히게 됩니다.
이제는 하나의 거대한 RDBMS로 모든 데이터를 커버하려 하기보다는 도메인 특성에 맞춰 NoSQL과 RDBMS를 섞어 쓰는(Polyglot Persistence) 전략이 필수가 되어가고 있다는 걸 체감할 수 있었습니다.
8장 클라우드 애플리케이션 클라이언트
8.1 육각형 아키텍처란
설계 원칙 중 UI와 도메인 분리를 예로 들며, 육각형 아키텍처라고 불리는 포트와 어댑터 아키텍처를 강조했습니다.

육각형 아키텍처(Hexagonal Architecture)는 일반적인 스프링 MVC 구조와 비교했을 때 다음과 같이 이해할 수 있습니다.
| |
이 구조에서는 Service가 Repository에 직접 의존하기 때문에 DB나 외부 기술에 대한 의존성이 강해지는 안타까운 특징이 있습니다.
반면, 육각형 아키텍처는 다음과 같은 구조를 가집니다.
| |
와 같이 Port(인터페이스)를 중심으로 도메인과 외부를 분리하게 되죠.
이 구조에서는 Controller는 Inbound Adapter, Repository 구현체는 Outbound Adapter, Domain은 핵심 비즈니스 로직, Port는 도메인이 외부에 요구하는 인터페이스 역할을 가지게 됩니다.
이러한 구조 덕분에 도메인 로직이 외부 기술(DB, API 등)에 의존하지 않게 되고, 테스트 시에도 Port를 Mock으로 대체할 수 있어 테스트가 정말 편해집니다.
당연히 DB나 외부 시스템이 통째로 변경되더라도 Domain은 전혀 영향을 받지 않습니다.
결과적으로 도메인만 안정적으로 유지된다면, 프론트엔드나 저장소 구현은 요리조리 자유롭게 변경할 수 있는 매력적인 구조라는 점이 특징입니다.
8.2 싱글 페이지 애플리케이션
주로 백엔드만 다루다 보니 프론트쪽 SPA에 대한 깊이가 살짝 부족했는데, 이번 기회에 꽤 명확하게 정리할 수 있었습니다.
싱글 페이지 애플리케이션을 웹 폼 애플리케이션과 구분 짓는 가장 핵심적인 요소는, 브라우저가 단일 페이지로 불러오는 콘텐츠에 웹 브라우저 내에서 실행되는 자바스크립트 프로그램이 포함되어 있다는 점입니다.

위와 같이 SPA 방식은 뷰가 완전한 웹 페이지가 아니라는 점에서 모든 브라우저 애플리케이션에서 사용하는 모델-뷰-컨트롤러(MVC) 같은 패턴의 기출 변형이라고도 볼 수 있습니다.
SPA 방식은 클라이언트 내에 페이지 상태를 저장하고 REST API 방식으로 백엔드 서비스와 데이터를 주고받습니다.
여러 화면이나 페이지를 나타낼 수 있는 복잡한 비즈니스 기능에 필요한 모든 HTML과 CSS, 자바스크립트 코드를 단일 페이지로 싹 밀어 넣어서 제공해주기 때문에 이 방식을 싱글 페이지라고 부릅니다.
덕분에 렌더링 속도가 매우 빠르고 사용자 입장에서도 화면 전환이 매끄러워서 반응성이 훨씬 뛰어나게 느껴집니다.
물론 장단점이 극명합니다.
속도, 개선된 사용자 경험, 백엔드와의 느슨한 결합, 상태 로컬 저장이라는 막강한 장점이 있는 반면 자바스크립트 번들을 다 받아야 해서 겪는 초기 로드 속도 저하, SEO(검색 엔진 최적화) 대응의 까다로움, 브라우저 내역 관리 문제 같은 단점들도 같이 떠안아야 합니다.
더 나아가서 이 책은 마이크로 프론트엔드 개념까지 확장해서 설명해줍니다.
백엔드를 거대한 덩어리에서 마이크로 서비스로 잘라낸 것처럼 프론트도 여러 컴포넌트나 모듈 단위로 쪼개어 개발하고 합치는 개념이죠.
참조할 만한 사이트로 책에서는 single-spa를 언급하고 있는데, 관심 있으신 분들은 한 번 둘러보셔도 좋을 듯합니다.

결국 마이크로 서비스나 마이크로 프론트엔드나 핵심은 하나 같습니다. 대규모 애플리케이션을 더 작고, 각각 테스트 가능하며, 관리하기 쉬운 독립된 단위로 쪼개어 시스템의 복잡도를 낮추는 것이죠.
반대로 말하면, 소규모 인원으로 빠르게 돌려야 하는 스타트업이나 개인 프로젝트 상황이라면 괜히 쪼개서 고생하지 말고 모놀리식이 훨씬 나은 선택지일 수 있다는 생각이 확고해졌습니다.
9장 애플리케이션 이전과 현대화
이 장에서는 기존 온프레미스 기반의 레거시 시스템을 클라우드 환경으로 이전하는 다양한 전략을 설명합니다.
단순히 인프라만 클라우드로 옮기는 Lift & Shift 방식부터 애플리케이션 구조를 클라우드 네이티브에 맞게 재설계하는 방식까지 여러 접근 방법이 제시됩니다.

핵심은 한 번에 모든 것을 변경하기보다는 단계적으로 이전을 진행하는 것입니다.
무리한 빅뱅 방식의 전환은 리스크가 크기 때문에, 점진적으로 시스템을 개선하고 클라우드 환경에 적응해 나가는 접근이 중요하다는 점을 강조합니다.
10장 모놀리식 점진적 대체
기존의 모놀리식 시스템을 마이크로서비스 구조로 전환하는 방법을 설명하며, 특히 스트랭글러 패턴(Strangler Pattern)을 중심으로 다룹니다.
스트랭글러 패턴은 기존 시스템을 한 번에 교체하는 것이 아니라, 일부 기능부터 새로운 서비스로 분리하고 점진적으로 대체해 나가는 방식입니다.
기존 시스템 앞단에 라우팅 계층을 두고, 새로운 기능은 신규 서비스로 처리하도록 점진적으로 전환하는 구조입니다.
이 방식은 시스템 안정성을 유지하면서 구조를 개선할 수 있다는 점에서 현실적인 접근 방법으로 제시되며, 점진적인 전환 전략의 중요성을 잘 보여주는 사례로 볼 수 있습니다.
느낀점
이 책을 읽으면서 가장 크게 느낀 점은 은총알은 없다(No Silver Bullet) 는 것이었습니다. 결국 모든 선택에는 트레이드오프가 존재하며, 절대적인 정답은 없다는 점을 다시 한번 생각하게 되었습니다. 아키텍처 또한 프로젝트의 규모와 복잡성에 따라 달라지며, 이를 이해하고 상황에 맞는 구조를 선택하는 것이 중요합니다.
우리가 선택하는 다양한 아키텍처 패턴과 기술에는 항상 그에 따른 비용과 제약이 따릅니다.
프로젝트의 규모, 팀의 역량, 기술 스택, 일정 등 여러 요소를 종합적으로 고려하여 가장 합리적인 선택을 하는 것이 중요하다는 점을 다시 느끼게 되었습니다.
최근에는 클라우드나 마이크로서비스와 같은 기술이 많이 주목받고 있지만, 단순히 트렌드를 따르기보다는 현재 서비스가 직면한 문제를 먼저 이해하고, 그에 맞는 구조를 고민하는 것이 더 중요하다고 생각합니다.
아키텍처를 고민하고 있는 개발자라면 한 번쯤 읽어볼 만한 책이라고 생각합니다.