데이터베이스와 그 복잡성이 이제 불필요한 이유
(blog.redplanetlabs.com)- 백엔드 복잡성의 원인은 특정 제품의 결함보다, 데이터베이스가 오래 유지해 온 개념적 구조가 애플리케이션 설계를 계속 제약한다는 데 있음
- 데이터베이스는 전역 가변 상태처럼 동작하고, 고정된 데이터 모델·제한적 스키마·정규화와 비정규화의 긴장을 개발자가 떠안게 만듦
- 제안된 대안은 이벤트 소싱과 구체화 뷰를 결합해 원천 데이터와 인덱스 뷰를 분리하고, 인덱스를 데이터 모델이 아닌 내구성 있는 데이터 구조로 다루는 방식임
- Red Planet Labs의 Rama는 depots, ETL, PStates, query topologies로 데이터 수집·처리·인덱싱·질의와 배포·모니터링을 한 플랫폼에 묶음
- Twitter 규모 Mastodon 재구현 사례에서 Rama는 10k 라인과 9인월로 구현됐고, 비교 대상인 Twitter 소비자 제품은 1M 라인과 약 200인년이 들었다고 비교됨
데이터베이스 복잡성의 출발점
- 문제의 초점은 특정 데이터베이스 제품의 API, 운영 난점, 임의 제한이 아니라 오늘날까지 유지된 집합적 개념 구조에 있음
- 더 나은 방식이 등장해야 기존 방식의 문제가 선명해지며, 대안으로 event sourcing과 materialized views의 결합을 제시함
전역 가변 상태로서의 데이터베이스
- 프로그래머는 전역 변수 사용을 최소화하라고 배우지만, 데이터베이스도 본질적으로 전역 가변 상태임
- 데이터베이스는 일반 전역 변수보다 더 다루기 어려운 면이 있음
- 상호작용이 여러 시스템에 퍼져 있어 상태 추론이 어려움
- 상태가 내구성을 가지므로 버그를 고쳐도 손상된 데이터가 자동으로 복구되지 않음
- 손상 범위를 정확히 파악하거나 완벽히 교정하기 어려운 경우가 있음
- 백업으로 되돌리거나 백업 일부를 병합하는 방식은 최적의 해결책이 아님
- 이벤트 소싱과 구체화 뷰를 사용하면 원천 로그에서 뷰를 다시 계산할 수 있어, 손상된 인덱스 상태를 바로잡을 여지가 생김
고정된 데이터 모델의 한계
- 데이터베이스는 key/value, document, relational, column-oriented, graph 같은 데이터 모델 중심으로 설계됨
- 단일 데이터 모델이 모든 사용 사례를 지원하기 어렵기 때문에, 기업은 여러 데이터베이스를 함께 쓰는 경우가 많음
- 더 일반적인 인덱스 추상화는 데이터 모델이 아니라 데이터 구조임
- Key/value: map
- Document: map of maps
- Relational: map of maps, secondary indexes는 추가 map
- Column-oriented: map of sorted maps
- 내구성 있는 데이터 구조는 디스크에 저장돼 매우 커질 수 있고, 중첩 데이터 구조도 표현할 수 있음
- 인덱스를 데이터 구조 조합으로 지정하면 기존 데이터 모델뿐 아니라 더 다양한 인덱스 형태를 만들 수 있음
- 애플리케이션 도메인 모델을 데이터베이스에 맞춰 비트는 대신, 저장소의 형태를 도메인 모델에 맞출 수 있으면 기초 복잡성이 줄어듦
정규화와 비정규화의 긴장
- 관계형 데이터베이스 사용자는 결국 정규화와 비정규화 사이의 선택을 마주함
- 정규화된 저장은 명확한 진실의 원천을 만들고 불일치 가능성을 줄이지만, 조인이 늘어나 질의 비용이 커질 수 있음
- 성능 때문에 같은 정보를 여러 방식으로 저장하면, 버그가 있을 때 데이터 불일치가 생길 수 있음
- RDBMS 아키텍처는 진실의 원천과 빠른 질의를 위한 인덱스 저장소를 같은 데이터스토어에 합쳐 놓음
- 해결책은 두 역할을 분리하는 구조임
- 한 하위 시스템은 진실의 원천을 표현함
- 다른 하위 시스템은 그 원천에서 원하는 수의 인덱스 저장소를 구체화함
- 두 번째 시스템이 원천 데이터에서 인덱스를 다시 계산할 수 있으면 불일치를 교정할 수 있음
제한적인 스키마와 도메인 표현
- 데이터베이스는 저장 가능한 값의 종류가 제품마다 크게 다름
- 어떤 데이터베이스는 byte array 같은 blob만 허용함
- 어떤 데이터베이스는 정수, 부동소수점, 문자열, 날짜 등 여러 타입을 허용함
- 도메인 객체 내부의 중첩 정보를 직접 질의하거나 집계할 수 있도록 일급 표현으로 저장하기는 드묾
- 데이터베이스 구현 언어와 애플리케이션 언어가 달라 상호 운용이 어렵고, Postgres용 protobuf extension 같은 확장도 번거롭고 제한이 있음
- ORM은 도메인 표현과 데이터베이스 표현을 매핑하지만, 추상화가 새어 문제를 일으킬 수 있음
- 이상적인 도메인 표현과 다른 방식으로 데이터를 인덱싱해야 하면 어댑터 코드가 필요하고, 효율적으로 수행할 수 있는 질의도 제한될 수 있음
복잡한 배포와 à la carte 모델
- 완전한 백엔드는 데이터베이스만으로 구성되지 않고, 데이터베이스·처리 시스템·모니터링 도구·스케줄러 등 많은 도구가 함께 필요함
- 대규모 백엔드는 수십 개 도구를 조합해야 할 수 있고, 애플리케이션 업데이트가 마이그레이션·코드 업데이트·인프라 변경의 오케스트레이션으로 커짐
- 프로덕션 준비에는 충분한 텔레메트리가 필요하지만, 도구마다 수집 방식이 달라 하나의 모니터링 대시보드로 모으는 일도 별도 엔지니어링 과제가 됨
- 현재 지배적인 개발 방식은 각 아키텍처 부분에 최적 도구를 골라 붙이는 à la carte 모델에 가까움
- 독립적으로 설계된 도구들을 함께 동작하게 만드는 작업 자체가 크며, 고정 데이터 모델과 제한적 스키마 때문에 도구를 애플리케이션에 맞추기보다 애플리케이션을 도구에 맞추게 됨
- 백엔드 구성을 위한 응집된 모델이 없었기 때문에 à la carte 모델이 자리 잡았고, 응집된 모델에서는 추상화·자동화·재사용 여지가 커짐
백엔드를 보는 단순한 모델
- 백엔드의 주요 기능은 새 데이터를 받는 것과 그 데이터에 대한 질문에 답하는 것임
- 가장 일반적인 질의는 백엔드가 받은 모든 데이터에 함수를 실행하는 형태로 표현할 수 있음
query = function(all data)
- 현실적으로 데이터셋이 10PB이고 질의 응답이 밀리초 단위여야 할 수 있으므로, 실용적 시스템에는 인덱스가 필요함
- 인덱스가 추가된 모델은 다음처럼 표현됨
indexes = function(data)query = function(indexes)
- 기존 백엔드는 이 모델의 구성요소를 여러 좁은 도구로 나눠 구현함
- RDBMS 백엔드는 RDBMS를 데이터와 인덱스에 사용하고, ElasticSearch 같은 별도 데이터베이스를 추가 인덱싱에 사용할 수 있음
- 계산은 API 서버 핸들러나 큐·워커 기반 백그라운드 작업에서 수행되는 경우가 많음
- 대규모 백엔드는 Cassandra, MongoDB, Neo4j, Kafka, Hadoop, Storm, Kafka Streams 같은 도구를 조합할 수 있음
- 모든 구성요소를 통합적이고 범용적으로 구현하는 도구가 있다면 앞선 복잡성을 피할 수 있다는 결론으로 이어짐
Rama의 구성과 Mastodon 사례
- Rama는 이러한 원칙을 기반으로 설계된 백엔드 개발 플랫폼임
- Red Planet Labs는 8월 15일 Rama를 “the 100x development platform”이라는 태그라인으로 발표함
- 비용 절감 사례로 Mastodon을 Twitter 규모로 재구현한 작업을 제시함
- 100M 봇이 초당 3,500회 게시함
- 평균 fanout은 403임
- Twitter의 동등한 소비자 제품은 1M 라인과 약 200인년이 들었다고 비교함
- Rama 구현에는 10k 라인과 9인월이 들었음
- 구현은 open-source이며 complete, high-performance, production-ready라고 제시됨
- Twitter는 규모 달성을 위해 social graph database, in-memory timeline database 같은 특화 데이터베이스를 직접 만들었고, Puppet 설정만 1M 라인 이상인 복잡한 배포를 가졌다고 비교됨
- Rama 기반 구현은 특화 인프라를 하위 문제마다 새로 만드는 대신 Rama의 원시 요소를 조합해 유사한 성능·확장성 문제를 풀었다고 함
- Mastodon 구현의 performance numbers는 Twitter 수치와 같거나 더 좋다고 제시됨
Rama의 프로그래밍 모델
- Rama의 개념은 앞서 제시한 백엔드 모델에 직접 대응함
- Depots: 임의 데이터를 담는 분산 로그이며
data에 해당함 - PStates: partitioned state의 약자이며 인덱스에 해당함
- ETLs:
function(data)에 해당함 - Queries:
function(indexes)에 해당함
- Depots: 임의 데이터를 담는 분산 로그이며
- PStates는 내구성 있는 데이터 구조의 임의 조합으로 필요한 만큼 만들 수 있음
- ETL과 query는 Turing-complete 데이터플로 API로 표현되며, 계산을 분산 실행할 수 있음
- Rama는 Java API 튜토리얼을 문서로 제공하고, Clojure API도 있음
Rama가 데이터베이스 복잡성을 줄이는 방식
- Rama의 PStates는 데이터베이스와 비슷한 역할을 하지만, 해당 PState를 소유한 ETL topology에서만 쓸 수 있음
- 모든 쓰기가 같은 ETL 코드에 있으므로 상태 추론이 쉬워짐
- PStates는 이벤트 소싱 로그 위의 구체화 뷰로 동작함
- depot data가 진실의 원천이므로 PState는 다시 계산될 수 있음
- 데이터 모델 제약은 PStates를 데이터 구조로 지정하는 방식으로 다룸
- Mastodon 구현은 profiles, statuses, timelines만으로도 33개 PStates를 사용함
- 어떤 PState는 10개 사용 사례를 처리하고, 어떤 PState는 하나의 사용 사례만 지원함
- PStates는 durable, partitioned, incrementally replicated 속성을 가짐
- incremental replication은 leader partition 장애 시 takeover할 다른 partition이 준비돼 있음을 뜻함
- 현재 leader에서 보이는 것은 이후 leader에서도 보이도록 보장함
- 정규화와 비정규화 문제는 depots와 PStates를 명시적으로 분리해 다룸
- 제한적 스키마 문제는 도메인 표현을 그대로 사용하는 방식으로 완화함
- hash map, list 같은 일반 데이터 구조
- Protocol Buffers
- 중첩 객체 정의
- Rama가 모르는 타입은 custom serializer 등록으로 처리함
배포, 통합, 모니터링
- Rama 애플리케이션은 modules라고 불리며, module은 여러 depots, ETLs, PStates, query topologies를 포함할 수 있음
- Rama는 module의 배포, 업데이트, 확장을 위한 내장 메커니즘을 제공하며 각각은 터미널의 one-liner로 수행된다고 함
- Rama는 “all or nothing” 도구가 아니라, 다른 시스템과 통합하기 쉽게 설계돼 기존 아키텍처에 점진적으로 도입할 수 있음
- 통합 플랫폼이기 때문에 자체 모니터링도 수행함
- 모니터링 데이터 수집
- 처리
- 인덱싱
- 시각화
- cluster UI telemetry는 module의 성능 이해, 문제 감지와 진단, 확장 시점 판단에 사용됨
학습과 도입 경로
- Rama를 더 배우는 경로로 다음 리소스가 제시됨
- 프로덕션에서 새 기능 구축, 기존 시스템 확장, 인프라 단순화를 위해 Rama를 사용하려는 경우 private beta에 신청할 수 있음
- private beta 사용자에게는 Rama 학습뿐 아니라 코드 작성, 최적화, 테스트를 함께 지원한다고 함
댓글과 토론
Hacker News 의견들
-
“나중에 설명하겠지만 더 나은 접근은 이벤트 소싱과 구체화 뷰”라니, 결국 해법은 복잡도 증가라는 건가. 당연히 그렇겠지
- 제대로 하면 오히려 백엔드 아키텍처가 크게 단순해짐. 낮은 규모의 앱도 보통 Postgres와 ElasticSearch처럼 여러 데이터베이스를 쓰고, 백그라운드 작업용 큐와 워커를 함께 둠
우리가 만든 Twitter 규모 Mastodon 구현이 직접적인 예시임. 같은 기능을 규모 있게 만들기 위해 Twitter가 작성해야 했던 코드보다 말 그대로 100배 적고, Mastodon 공식 구현보다도 40% 이상 적은 코드임. 같은 도구로 두 번째라 더 잘 설계한 게 아니라, 근본적으로 더 나은 추상화로 만들었기 때문임 - 복잡도는 사라지는 게 아니라 다른 곳으로 이동할 뿐임. 많은 작업에서는 이 해법의 절충이 나쁠 수 있음
다만 일정 규모를 넘으면 모든 것이 데이터 엔지니어링 문제가 되고, 전체 시스템 맥락에서는 이 방식이 상대적으로 단순한 해법이 되기도 함. “그냥 mySQL/SQLite/Postgres 쓰라”는 조언은 유효하지 않은 순간이 오기 전까지만 훌륭함 - 복잡도가 더 늘어난다고? 글쓴이는 아주 단순하게 만들었음. 그냥 자기 제품 Rama를 쓰면 됨
- 내가 일했던 모든 회사에서 이벤트 소싱 + 구체화 뷰는 극심한 혼란, 더 많은 버그, 더 긴 장애로 이어졌음. MySQL이나 PostGres, 혹은 Redis/DynamoDB 같은 더 단순한 해법이 전부 더 잘 작동했음
Martin Fowler의 원래 이벤트 소싱 글이 아예 쓰이지 않았더라면 모두에게 더 나았을 거라고 진심으로 믿음. 99%의 경우에는 나쁜 아이디어라고 봄 - 프로그램 도메인에 본질적 복잡도 X가 필요하다면 어쨌든 그 복잡도를 구현해야 함. 이미 작성되고 실전 검증된 다른 사람의 코드에 맡길 수도 있고, 직접 다시 만들 수도 있는데 후자는 시간이 많이 들고 결과도 더 나쁠 수 있음. 공짜 점심은 없음
- 제대로 하면 오히려 백엔드 아키텍처가 크게 단순해짐. 낮은 규모의 앱도 보통 Postgres와 ElasticSearch처럼 여러 데이터베이스를 쓰고, 백그라운드 작업용 큐와 워커를 함께 둠
-
내가 놓친 건지 모르겠지만, 글에서 동시성, 격리, 제약조건 같은 개념을 완전히 빠뜨린 것처럼 보임. 그리고 “쿼리 토폴로지”라는 게 선언적이지도 않고 쿼리 계획/최적화 책임을 작성자에게 떠넘기는 것 같은데, 정말 이걸 더 나은 개발자 환경이라고 보는 건가?
- 이런 내용은 문서에서 충분히 다루고 있음. 이 글은 백엔드 개발의 복잡도와 Rama가 이를 어떻게 다루는지에 관한 글이지, Rama의 모든 측면을 완전히 설명하는 글은 아님. 전부 설명하면 너무 길어짐. Rama를 더 파보면 속성과 보장이 매우 강하다는 걸 볼 수 있음
그리고 맞음, Rama의 쿼리 방식은 훨씬 우월한 접근임. 복잡한 쿼리 계획기가 필요한 건 대개 데이터 색인 방식의 한계, 특히 정규화와 비정규화 사이의 긴장에서 비롯됨. Rama에서는 쿼리에 필요한 형태로 이미 준비된 여러 뷰를 견고하게 구체화하기 쉬움
Rama 개념을 부드럽게 소개하는 튜토리얼은 여기 있음: https://redplanetlabs.com/docs/~/tutorial1.html
- 이런 내용은 문서에서 충분히 다루고 있음. 이 글은 백엔드 개발의 복잡도와 Rama가 이를 어떻게 다루는지에 관한 글이지, Rama의 모든 측면을 완전히 설명하는 글은 아님. 전부 설명하면 너무 길어짐. Rama를 더 파보면 속성과 보장이 매우 강하다는 걸 볼 수 있음
-
“어떤 단일 데이터 모델도 모든 사용 사례를 지원할 수 없다”는 말에 대해, 이론적으로는 사물의 튜플과 관계로 정확히 모델링할 수 없는 도메인이나 유한한 도메인 집합은 없음
실무적으로 특정 데이터베이스/스키마의 범위는 보통 하나의 비즈니스나 문제 영역으로 제한되지만, 타입이 부적절하게 겹치지만 않으면 이것도 별문제가 안 됨. 이름만 조심하면 웹 소매업체와 보험회사를 같은 스키마에 넣어도 충분히 동작함
모든 것을 정확히 하나의 데이터베이스에 넣는 건 초능력임. 내가 이걸 강하게 주장하는 가장 큰 이유는 여러 데이터 저장소에 걸친 분산 트랜잭션을 피하기 위해서임. 모든 비즈니스가 하나의 트랜잭션 시스템 안에서 일어나면 의미론이 극적으로 단순해짐- “모든 것을 하나의 데이터베이스에 넣는 건 초능력”이라는 말에 특히 동의함
사람들이 실제로 데이터를 쓰기 시작하면 100만 달러짜리 대형 DB 서버가 저렴한 데이터베이스들의 중복 배열보다 훨씬 쌈. 개발자든 분석가든 경영진이든 모두 시간이 절약되고, 아마 일부 DBA만 예외일 수 있음 - 큰 데이터베이스는 새롭지 않음. 그게 전부였다면 지난 40년 동안 사람들이 계속 그렇게 했을 것임. 그런데 항상 작동하지는 않았고, 때로는 자주 끔찍했음
이론적으로 그게 전부라고 해도, 또 다른 지속적 문제는 구현임. 요즘 대부분의 개발자는 데이터베이스가 어떻게 동작하고 어떻게 써야 하는지 잘 이해하지 못해 형편없이 사용함. 그래서 이 사실에서 벗어나려고 NoSQL 같은 새 데이터베이스를 만들었고, 머리를 덜 쓰고 접착 코드만 더 쓰려 했음. 그것도 끔찍한 결과로 드러남
머지않아 흐름은 다시 바뀌고 “그냥 큰 데이터베이스 하나”는 다시 유행이 아니게 되며, 또 다른 “단순성” 패러다임이 나올 것임. 마이크로서비스 때처럼 “하나의 큰 데이터베이스” 대신 “많은 작은 데이터베이스”가 단순하다고 여겨질 수 있음. 역사를 이해하지 못하면 반복할 수밖에 없음 - 어떤 사용 사례를 튜플과 관계로 모델링할 수 있다는 말은 데이터베이스가 그 사용 사례의 성능 요구사항을 만족할 수 있다는 뜻이 아님. 성능 요구사항을 못 맞추면 그 사용 사례는 지원되지 않는 것임
일반 프로그래밍에서도 하나의 자료구조나 자료구조 조합이 모든 사용 사례를 지원할 수 없는 것과 같음. 때로는 맵이 필요하고, 때로는 리스트, 집합, 조합, 혹은 완전히 다른 무언가가 필요함 - “모든 것을 하나의 데이터베이스에 넣는 건 초능력”이라는 데 동의함. 이전 회사는 앱마다 별도 DB를 둔 카고컬트식 마이크로서비스 구성이었고, 비즈니스 이점 없이 불필요하게 복잡하고 비싸졌음. 이력서 채우기에는 분명 이점이 있었겠지만. 강제로 필요해질 때까지 복잡하게 만들지 말아야 함
- 꿈같고 정말 아름다운 발상이지만 실제로는 작동하지 않음. 혹시 성공한 사람이 있나? 극단적으로 보면 전 세계에 통합 데이터베이스 하나와 사용자 권한 체계 하나가 필요하다는 얘기가 됨
당연히 데이터 구조는 다양하고, 성능도 필요하며, 너무 중요해서 일반인이 건드릴 수 없는 병목이 되고 모든 변경은 극도로 안전해야 함. 보안도 있음. 누군가 개발 버그 섹션에서 HR이나 임원 전용 재무 섹션으로 넘어가는 방법을 찾으면 어떻게 하나? 범용 ERM 시스템을 구현해 본 사람이라면 통합 시스템이 얼마나 어렵고 고통스러운지 알 것임
다만 이건 극단적인 경우임. 이 이상을 추구하면서 사람들이 어디까지 갔고 어떻게 했는지 궁금함. 하나의 시스템으로 운영되는 비즈니스를 본 적이 없음. 개인 지식 관리 시스템은 어떤가? 모든 것이 들어맞나? 여전히 빠른 작업에는 스프레드시트, 자유 형식에는 텍스트 파일을 쓰지 않나?
- “모든 것을 하나의 데이터베이스에 넣는 건 초능력”이라는 말에 특히 동의함
-
유행어 모음처럼 보임. 세계 최대급 회사 중 하나에서 수년간 데이터베이스를 다뤄왔지만 토폴로지라는 말을 들어본 적이 없음
이걸로 절약할 시간이 있다 해도 Java와 이 프레임워크를 배우는 데 날아갈 것임. 데이터베이스 자체에는 아무 문제가 없음- 동등한 기능을 Twitter 규모로 만들 때 Twitter가 작성한 코드보다 100배 적은 코드로 만든 프로덕션 준비 Mastodon 구현이 있으니, “유행어 모음”이라는 평에는 동의하기 어려움: https://github.com/redplanetlabs/twitter-scale-mastodon
- 나한테는 이런 광고의 한 예처럼 보임
여기에서 텍스트 표를 만들려 했는데 페이지 표시가 완전히 망가져서 스크린샷으로 올림: https://imgur.com/a/XtwSkyx
-
Rama를 다섯 살 아이에게 설명하듯 말하면 뭔가? 문서도 헷갈렸음: https://redplanetlabs.com/docs/~/index.html
“패러다임 전환”이나 “플랫폼” 같은 유행어는 빼줬으면 함. 다이어그램이 필요하다면 더 명확히 설명하는 글을 읽고 싶음- 애플리케이션의 데이터 수집, 처리, 색인, 질의 요구를 어떤 규모에서도 처리할 수 있는 백엔드 개발 플랫폼임. 여러 데이터베이스, 처리 시스템, 큐, 스케줄러를 뒤섞어 백엔드를 구성하는 대신 Rama라는 단일 플랫폼 안에서 전부 할 수 있음
Rama는 클러스터로 실행되고, 여러 애플리케이션은 “모듈”이라는 형태로 그 클러스터에 배포됨. 깊고 상세한 원격 측정도 내장되어 있음
Rama의 프로그래밍 모델은 이벤트 소싱과 구체화 뷰임. Rama 애플리케이션을 만들 때 필요한 만큼 많은 색인을 원하는 형태로, 여러 영속 자료구조 조합으로 구체화함. 색인은 분산 데이터 흐름 API로 구체화됨
Rama는 기존에 있던 것들과 너무 달라서 이 정도가 내가 할 수 있는 고수준 설명임. 기초를 배우기 가장 좋은 자료는 rama-demo-gallery이고, 여러 사용 사례에 Rama를 적용하는 짧고 끝까지 동작하는 상세 주석 예제가 들어 있음. 모두 확장 가능하고 장애 허용적임: https://github.com/redplanetlabs/rama-demo-gallery - 내가 읽기로는 Kappa 아키텍처, 즉 이벤트 소싱의 변형임
“Depot”이라는 추가 전용 이벤트 로그가 있고, 그 위에 임의의 뷰를 만들며 이를 “P-States”라고 부름. Rama 소프트웨어는 이 뷰들의 낮은 지연 업데이트를 약속함. 이 위에 만든 애플리케이션은 뷰를 질의하고 Depot에 새 이벤트/명령을 제출함 - 이벤트 소싱 데이터베이스처럼 보임. 기본적으로 직접 쓰는 대신 메시지를 쓰고, 그 메시지에 따라 갱신되는 읽기 전용 테이블을 만들 수 있음. 특정 도메인에서는 지금도 이렇게 하지만 전통적인 데이터베이스보다 확실히 더 복잡함
- 또 다른 NoSQL 시도처럼 보임. “하지만 이번엔 다르다!”
- 애플리케이션의 데이터 수집, 처리, 색인, 질의 요구를 어떤 규모에서도 처리할 수 있는 백엔드 개발 플랫폼임. 여러 데이터베이스, 처리 시스템, 큐, 스케줄러를 뒤섞어 백엔드를 구성하는 대신 Rama라는 단일 플랫폼 안에서 전부 할 수 있음
-
1~10TB 규모의 라이브 이벤트 데이터셋 위에 유연한 구체화 뷰 엔진을 만드는 1년짜리 프로젝트를 했고, 다른 프로젝트로 옮기기 전 우리 아키텍처도 대략 색인이 있는 곳으로 코드를 보내는 아이디어로 수렴하고 있었음
Rama에는 꽤 끌리지만, 완전히 비합리적인 이유로 JVM 때문에 도입하지 않을 것 같음. 그냥 Java/JVM이 싫음. 이 아키텍처가 다른 환경으로 포팅되면 좋겠음 -
직장에서는 읽기 모델과 쓰기 모델을 분리함. 쓰기 모델, 즉 진실의 원천은 불변조건/제약조건까지 갖춘 전통적인 관계형 도메인 모델이고, ORM에 익숙한 대부분의 개발자에게 추론하기 어렵지 않다고 봄
거의 모든 명령은 이벤트도 만들어 공유 도메인 이벤트 큐에 발행함. 읽기 모델은 이벤트를 소비하는 워커가 각자 필요한 방식으로 뷰를 만들며, 다시 만들 수도 있음. 예를 들어 사용자 관리 서비스는 진실의 원천이고, 다른 서비스는 복잡한 UI를 보여주기 위한 뷰 서비스로서 사용자 서비스와 다른 서비스의 이벤트를 기반으로 자체 읽기 모델/색인을 만듦. 이게 없으면 엄청난 조인이나 느린 서비스 간 API 호출이 필요했을 것임
기술적으로 이벤트 재생은 가능함. 실제로 플랫폼 코드 버그 때문에 지난 3년치 모든 이벤트를 재생한 적도 있음. 하지만 정말 필요했던 적은 거의 없다고 봄. 버그 때문에 뷰를 다시 만들어야 할 때도 있지만 보통 특수 스크립트나 SQL 마이그레이션 같은 임시 프로그램 방식으로 처리함. 우리 아키텍처를 정확히 뭐라고 부르는지는 모르겠고, 아무도 “이벤트 소싱”이라고 부르는 걸 들어본 적은 없음
결국 오래된 MySQL + RabbitMQ와 약간의 접착 코드임. 다만 제대로 하려면 트랜잭션 아웃박스, 최소 1회 전달 보장, 최종 일관성, 올바른 이벤트 처리 순서 유지, 이벤트 데이터 배치, DB 관리, 이벤트 핸들러가 죽었을 때의 처리 등 때문에 아주 사소하진 않음. 이미 실전 검증된, 언어 독립적인 구성이고 PHP와 Go 생산자/소비자가 모두 있는 상황에서 Rama 없이 무엇을 놓치고 있는지, 위 목록의 문제들을 Rama가 어떻게 푸는지 궁금함. Rama는 Java 쪽에 더 맞춰진 것처럼 보임- RDBMS를 쓰면서 복잡도를 관리하는 훌륭한 방식을 엔지니어링한 것 같음. Rama가 그 위에 제공하는 것들이 몇 가지 있음
Rama의 색인은 훨씬 유연함. 예를 들어 1억 개 원소가 있는 중첩 집합이 필요해도 사소함. 사용자 ID → 팔로워 ID 집합 같은 소셜 그래프 색인이 흔한 예임. 입자도별로 쪼갠 시계열 색인, 즉 엔터티 → 입자도 → 시간 버킷 → 통계도 마찬가지로 간단함
Rama에 저장되는 데이터 타입에는 제한이 없음. Rama 쿼리는 매우 강력하며, 일부 또는 전체 색인에 걸친 실시간 온디맨드 분산 질의가 쉽다. 애플리케이션 전반의 깊고 상세한 원격 측정도 내장되어 있어 별도로 만들거나 관리할 필요가 없음
배포도 내장되어 있음. 지금 방식에서는 애플리케이션 업데이트가 워커 코드, 스키마 마이그레이션처럼 여러 시스템에 걸칠 수 있고, 특히 무중단을 원하면 꽤 어려운 엔지니어링 작업이 됨. Rama는 계산과 저장을 끝까지 통합하므로 애플리케이션 출시, 업데이트, 확장이 전부 터미널 한 줄로 가능함
Rama는 훨씬 더 확장 가능함. 이건 기능 관점에서 본 Rama이고, Rama로 코딩할 때 임피던스 불일치가 없다는 게 얼마나 큰 차이를 만드는지는 말로 표현하기 어렵고 써봐야 알 수 있음. Rama는 JVM용이므로 어떤 JVM 언어로도 쓸 수 있고, 현재 Java와 Clojure API를 제공함 - “고객 주소 업데이트” 같은 명령은 SQL을 수행한 뒤 RDBMS 트리거가 RabbitMQ로 이벤트를 보내는 건가, 아니면 ORM이 SQL을 보내고 RabbitMQ에 게시하는 건가?
이벤트는 어디에 어떤 형식으로 저장하나? 더 자세히 듣고 싶음
지금 빠진 건 전체 생태계에 붙일 멋진 이름인 듯함
- RDBMS를 쓰면서 복잡도를 관리하는 훌륭한 방식을 엔지니어링한 것 같음. Rama가 그 위에 제공하는 것들이 몇 가지 있음
-
변경 시점에 데이터를 구체화하면 제품이 한 가지 일을 아주 빠르게 해야 할 때는 이득이 있을 수 있음. 하지만 원자적 쓰기로 함께 갱신해야 하는 복잡한 트랜잭션이 생기거나, 데이터를 다른 방식으로 정리해야 하는 새 기능을 추가하려는 순간 곤란해짐
애플리케이션 구축 부분에서 “그냥 색인 하나 붙이면 된다”는 식으로 가볍게 넘어간 것도 매우 불만족스러움. 색인은 전역 상태이고, 한 계층 아래로 옮겨졌을 뿐임- “한 계층 아래로 옮겨졌을 뿐”이기 때문에, 결정적으로 더는 직접 관리할 필요가 없음. 해야 할 일은 시스템에 무엇을 색인할지만 알려주는 것뿐임. 그것은 상태나 데이터가 아니라 코드임
-
이 문서를 읽어도 대상 독자가 누구이고 무엇을 해결하려는지 명확하지 않음: https://redplanetlabs.com/docs/~/why-use-rama.html#gsc.tab=0
실제 사례를 하나 들고, RAMA로 하면 얼마나 쉽고 효율적인지 변환해서 보여주면 도움이 될 것 같음- 예제는 많이 공개했음
첫 번째는 Twitter 규모 Mastodon 구현으로, 같은 것을 규모 있게 만들기 위해 Twitter가 작성한 코드보다 100배 적은 코드임. 소비자 제품만 기준임. 확장 가능하지 않은 Mastodon 공식 구현보다도 40% 이상 코드가 적음: https://github.com/redplanetlabs/twitter-scale-mastodon
rama-demo-gallery 저장소에도 Rama를 매우 다른 사용 사례에 적용한 짧고 독립적이며 상세히 주석 처리된 예제가 많음. 사용자 프로필 관리, 시계열 분석, 원자적이고 장애 허용적인 은행 송금 등이 포함됨: https://github.com/redplanetlabs/rama-demo-gallery
- 예제는 많이 공개했음
-
실제로 일간 사용자 4천만 명짜리 웹사이트를 운영하는 게 아니라면 “Twitter 규모 Mastodon 클라이언트”로 이게 증명됐다고 주장할 수는 없어 보임. 실제 환경, 그에 따른 코드와 인프라 변경, 실제 사용자, 네트워크 사용량 등을 시뮬레이션하는 건 불가능함
- Twitter 규모 시뮬레이션을 수행했음. 여기 참고: https://blog.redplanetlabs.com/2023/08/15/how-we-reduced-the...