모놀리틱 아키텍처 (크리스 리차드슨)
This a translation of an article Monolithic Architecture originally written and copyrighted by Chris Richardson.
이글은 Chris Richardson가 작성하였으며, 저작권을 가지고 있는 Monolithic Architecture 글의 번역본입니다.
정보
- 패턴: 모놀리틱 아키텍처 (Monolithic Architecture)
맥락 (Context)
서버 사이드 기업용 애플리케이션 개발을 하고 있다고 해보자. 데스크탑 브라우저와 모바일 브라우저, 그리고 네이티브 모바일 애플리케이션을 포함해 여러 가지 다양한 클라이언트 지원해야만 한다. 또한, 애플리케이션은 3rd 파티가 사용할 수 있도록 API를 노출해야 할 수도 있다. 또한 웹서비스나 메시지 브로커를 통해서 다른 애플리케이션 서비스와 통합해야 할 수도 있다. 애플리케이션은 비즈니스 로직을 실행하고, 데이터베이스에 접근하며, 다른 시스템들과 메시지를 주고받아 HTML/JSON/XML 응답을 돌려주는 것으로 요청(HTTP 요청과 메시지)을 처리한다
애플리케이션은 계층형 아키텍처나 6방형(hexagonal) 아키텍처를 갖거나 다양한 유형의 컴포넌트로 구성되어 있다.
- 프리젠테이션 컴포넌트- HTTP 요청을 제어해서 HTML이나 JSON/XML(웹서비스 API들로써)로 응답을 보내는 책임
- 비즈니스 로직- 애플리케이션의 비즈니스 로직
- 데이터베이스 접근 로직 - 데이터베이스에 접근해서 데이터 접근 객체 만드는 책임
- 애플리케이션 통합 로직 - 메시지 처리 레이어를 말하며, Spring Integration을 기반으로 하는 걸 예로 들 수 있음
이들은 애플리케이션의 다양한 기능적인 측면에 상응하는 논리적인 컴포넌트이다.
문제 (Problem)
애플리케이션의 배포 아키텍처는 어떤 것인가?
영향도 (Forces)
- 애플리케이션을 개발하는 개발자들의 팀
- 새로운 팀원은 빠르게 생산성을 보여줘야 함
- 애플리케이션은 쉽게 이해하고, 수정할 수 있어야 함
- 애플리케이션의 지속적인 배포가 관례화 되기를 기대함
- 규모가변성(Scalability) 와 가용성(Availability) 요구사항을 만족하기 위해서 다수의 장비에서 애플리케이션의 다수의 복사본이 실행되야 함
- 최근 부각된 기술(프레임워크, 프로그래밍 언어 등)을 기회로 활용되기를 원한다.
해결방법 (Solution)
모놀리틱 아키텍처를 사용해서 애플리케이션을 구축한다. 예를 들면,
- 단일 자바 WAR 파일
- Rails 또는 NodeJS 코드의 단일 디렉토리 구조
예시
고객에서 주문까지, 재고(inventory)를 확인하고, 신용결재(credit)가 가능하며, 이를 출하(ships)할 수 있는 전자 상거래 애플리케이션을 구축한다고 상상해보자. 애플리케이션은 신용거래를 확인하고, 재고를 관리하고, 주문을 출하하는 백 엔드 서비스와 함께 사용자 인터페이스를 구현하는 StoreFrontUI를 포함하는 각각 컴포넌트로 구성한다.
애플리케이션은 단일 모놀리틱 애플리케이션으로 배포된다. 예를 들어, 톰캣과 같은 웹 컨테이너에서 실행되는 하나의 WAR 파일로 구성 된 자바 웹 애플리케이션이거나 Apache/Nginx나 톰캣의 JRuby에서 돌아가는 Phusion Passenger를 사용한 단일 디렉토리 구조로 구성된 Rails 애플리케이션일 수 있다. 스케일 확보와 가용성 증대를 위해 로드 발란서(load balancer) 뒤에서 다수의 인스턴스를 실행할 수 있다.
상황 해결하기
이 해결책은 여러 장점을 가지고 있다.
- 개발의 단순함: 현재의 개발 툴과 IDE의 목표는 모놀리틱 애플리케이션의 배포를 지원이다.
- 배포의 단순함: 적절한 런탐임 환경에 WAR 파일을 간단하게 배포해야 한다.
- 확장의 단순함: 로드 발란서 뒤에 애플리케이션의 다수의 복사본을 실행해서 애플리케이션 스케일 확보해야 한다.
그렇지만 일단 애플리케이션이 커지고 팀의 규모가 성장하면 이 접근방법은 가면 갈수록 심각해지는 여러 단점이 발생한다.
- 큰 모놀리틱 코드 기반은 개발자들을 위축시키며, 특히, 팀에 새로운 개발자에게는 더 그렇다. 애플리케이션은 이해하기 어렵고, 수정하기 어려워질 수 있다. 결과적으로 보통 개발은 점점 더 느려지며, 물리적인 모듈 경계가 없기 때문에 모듈화는 시간이 지나면 지날수록 깨진다. 게다가 변경을 정확하게 구현하려면 어떻게 해야 하는지 이해하기 어렵기 때문에 시간이 지날수록 코드의 품질은 나선형으로 떨어진다.
- IDE 과부하 - 코드 기반이 더 커지면 IDE 속도를 더 느리게 만들고어서 개발자 생산성은 떨어진다.
- 웹 컨테이너 과부하 – 애플리케이션이 더 커지면서 애플리케이션을 시작하기가 점점 더 오래 걸린다. 이 문제는 컨테이너가 시작되기를 기다리는 시간을 허비해 개발자 생산성에 큰 영향을 준다.
- 지속적인 배포 어려움 – 또한 모놀리틱 아키텍처가 커질수록 빈번한 배포에 장애물이 된다. 하나의 컴포넌트를 갱신하고 싶을 때 전체 시스템을 재 배포 해야 한다. 이는 변경 영향도가 있든 없든 혹시나 문제의 원인이 될까 봐 백그라운드 작업(일례로 자바 애플리케이션에서 Quartz 잡)을 중단하게 한다. 또한 컴포넌트가 갱신되지 못하면 정확한 기동이 실패할 수 있다. 결과적으로 재 배포에 관련된 위험은 증가하며, 빈번한 갱신을 막게 된다. 이 점은 특히 보통 빠르게 반복하면서 자주 재 배포를 필요로 하는 사용자 인터페이스 개발자에게 특히 문제이다.
- 애플리케이션 스케일 확보의 어려움 – 모놀리틱 아키텍처는 한 가지 관점으로만 스케일 확보를 할 수 있다. 반면에 애플리케이션의 복사본을 더 만들어 실행함으로써 트랜잭션 용량을 증가시켜 스케일 확보를 할 수 있다. 일부 클라우드는 부하량에 따라 동적으로 인수턴스의 수까지 조정 할 수 있다. 하지만 한편으로 이 아키텍처는 데이터 용량을 증가시켜 스케일 확보는 불가능하다. 애플리케이션 인스턴스의 각 복사본은 모든 데이터에 접근할 수 있으며, 이는 캐시 효율성을 떨어트리고, 메모리 소비와 I/O 트랙픽을 증가시킨다. 또한 다른 애플리케이션 컴포넌트는 다른 리소스 요구사항을 갖는다. 하나의 컴포넌트는 CPU가 집중적으로 필요할 수도 있는 반면에 또 다른 컴포넌트는 메모리가 집중적으로 필요할 수 있다. 모놀리틱 아키텍처는 각 컴포넌트 별로 독립적인 스케일 확보가 불가능하다.
- 개발 스케일 확보의 장애물 – 또한 모놀리틱 애플리케이션은 개발 스케일 확보에 장애물이다. 일단 애플리케이션이 특정 크기가 되면 엔지니어링 조직을 특정 기능 영역에 집중하는 팀으로 분배하는 것이 유익하다. 예를 들어, UI 팀, 회계 팀, 재고 팀 등으로 구분하기를 원할 수 있다. 팀들이 독립적으로 일하는 것을 막는다는 것이 모놀리틱 아키텍처를 사용할 때의 문제점이다. 팀 간에 반드시 개발 노력과 재 배포를 조정해야만 한다. 이건 한 팀이 제품을 변경하고, 갱신하는 것보다 훨씬 더 어렵다.
- 오랫동안 인정받은 기술 스택을 요구함 – 모놀리틱 아키텍처는 개발을 시작했을 때 선택한 기술 스택(그리고 일부 경우에는 특정 기술의 정해진 버전으로)으로 강력히 강제한다. 모놀리틱 애플리케이션에서는 새로운 기술을 적용하기 어려울 수 있다. 예를 들어, JVM을 선택해야 한다고 생각해보자. 지금까지 자바뿐만 아니라 몇 개의 언어를 사용하고 있고 그루비와 스칼라처럼 자바와 훌륭하게 상호 호환성(inter-operate)을 제공하는 다른 JVM 언어를 사용할 수 있다. 그러나 JVM 언어가 아닌 언어로 작성된 컴포넌트는 모놀리틱 아키텍처에서는 존재할 수가 없다. 또한, 애플리케이션이 시간이 지나서 구식이 된 플랫폼 프레임워크를 사용한다면 새롭고 더 나은 프레임워크를 위해 애플리케이션을 점진적으로 마이그레이션 해야 하는 도전에 직면할 수 있다. 새로운 플랫폼 프레임워크를 적용하기 위해서는 전체 애플리케이션을 재작성 해야 하는 큰 위험을 책임져야만 가능하게 된다.
관련 패턴
마이크로서비스 아키텍처는 모놀리틱 아키텍처의 제약을 다루는 대안 패턴이다.
쓰임새
Neflix, Amazon.com과 eBay처럼 잘 알려진 인터넷 서비스가 모두 최초에는 모놀리틱 아키텍처였다. 대부분 웹 애플리케이션은 모놀리틱 아키텍처를 바탕으로 개발되었다.