요약
포스트호그가 웨어하우스 제품을 DuckDB에서 자체 Trino와 새 테이블 형식 HogLake로 옮겼습니다.
제품 분석 회사 포스트호그의 엔지니어 벤저민 크노페비더가 쓴 글입니다. 다섯 달 전 ClickHouse 대신 DuckDB로 웨어하우스를 다시 만들었습니다. 그런데 고객 작업이 예상보다 크고 복잡해 석 달 동안 구조를 다시 짰다고 밝혔습니다.
왜 중요한가
- 한 대에서 도는 단일 노드 엔진은 로컬에서 뛰어나도, 클라우드에서는 자원을 미리 정하기 어렵다는 사례입니다.
- 여러 DB에서 두루 쓰게 설계한 형식은 규모가 커지면 오히려 최적화를 가로막을 수 있다고 봤습니다.
- Postgres 호환 접속을 대규모로 제공하는 일에도 운영 비용이 크게 든다는 점을 보여 줍니다.
핵심 내용
- DuckDB는 쿼리가 오기 전에 서버 크기를 정해야 하는데, 쿼리마다 필요한 CPU와 메모리를 예측하기 어려웠습니다.
- DuckLake(DuckDB용 레이크하우스 확장)는 커밋마다 카탈로그 전체 통계를 다시 읽어 쓰기 한 번에 3분 넘게 걸리기도 했습니다.
- 통계 행의 99% 이상이 이미 없는 테이블의 것이었고, 지우면 쓰기가 30~50배 빨라졌지만 다시 쌓였습니다.
- 자사 데이터 약 2PB, 1조 행을 직접 올려 써 봤지만 원본 프로젝트 반영이 늦어 별도 포크로 패치를 유지했습니다.
- Postgres 접속 방식은 HTTP보다 부하 분산 도구가 적고, 클라이언트마다 다른 동작을 맞추기 힘들었습니다.
HN 반응
- 다섯 달 만에 엔진을 또 바꾸면서 측정 결과도 없다는 비판이 많았고, 창업자는 소수 시범 고객용 제품이라고 해명했습니다.
- 처음부터 Iceberg와 Trino를 쓰지 않은 이유를 묻자, 작성자는 Iceberg의 쓰기 속도가 너무 느렸다고 답했습니다.
다섯 달 전에 ClickHouse에서 DuckDB로 갈아탔는데, 이번에는 DuckDB에서 자기들이 만든 Trino 파생품으로 갈아탄다는 건가요?
게다가 글은 새 구성이 문제를 해결했는지도 말해 주지 않은 채 끝납니다.
요즘은 다운타임을 거의 없이(그럴 것이라고 생각합니다만) 이런 마이그레이션을 할 수 있고 이것저것 시도해 볼 수 있다는 건 좋은 일입니다. 다만 갈아타기 전에 어떤 테스트를 했는지를 더 읽고 싶었습니다. DuckDB가 자기들 규모에서는 통하지 않을 거라는 걸 모르고 넘어갔고, 몇 달 쓰다가 또 갈아탔다는 사실은 설득력이 없습니다.
블로그 글에 담기지 않았을 뒷이야기가 더 있기를 바랍니다. 지금 쓰인 대로라면, 튜닝하고 유지보수하는 것보다 마이그레이션하는 걸 더 좋아해서 여섯 달마다 기술 스택을 바꾸던 팀들과 일했던 기억이 떠오릅니다.
그래도 ClickHouse, DuckDB, Trino를 이력서랑 링크드인에 올릴 수 있게 됐잖아요. 문제 해결이죠!
예전에 한 고객사가 저를 불러서 시스템을 봐 달라고 했습니다. 만든 사람이 몇 년 전에 떠난 시스템이었는데, 엉망이었어요. 게다가 아무 이유도 없이 Docker를 잔뜩 쓰고 있었고, 특정 프리릴리스 버전에서만 돌아갔습니다. 찾아보니 그 사람은 당시 막 뜨던 이 신기술로 발표 한 번 할 만큼만 머물다가 더 좋은 직장으로 옮겨 갔더군요.
제가 본 이력서 주도 개발(Resume Driven Development) 중에 가장 확실한 사례였습니다. 물론 그게 유일한 사례는 아니지만요.
예전에 다닌 스타트업에서는 아키텍트가 자기 측근들을 몇 달 동안 방에 가둬 놓고, 자기가 관심 있던 백서(white paper)를 하나도 빠짐없이 구현하게 했습니다. 나머지 회사에는 이 새로운 질서를 받아들이라고 했고요. 재작성을 하고 1년도 안 돼서 엔지니어링 인력의 3분의 2를 해고했고, 얼마 안 가 회사는 팔렸습니다. 그 아키텍트는 그렇게 쌓은 경험을 인정받아 FAANG에 들어갔죠. 그 사람과 점심을 먹을 때 "나는 보통 내가 떠난 회사를 처음보다 더 나쁜 상태로 만들어 놓고 나오지"라고 농담하던 게 기억납니다. 제멋대로인 사이코패스입니다.
그딴 회사는 잊으세요, 친구. 저도 스타트업 마인드셋인 회사에 있었는데 똑같았어요. 사흘 만에 한 푼도 안 받고 그만뒀습니다.
솔직히 이제는 그런 건 중요하지도 않아요.
원 댓글 작성자가 알고 싶어 하는 것들이야말로 면접에서 정말 따지는 것들이에요. 결정의 이유 말이죠. 실제 구현이 아니라요.
요즘은 프런티어 에이전트가 있어서 뭘 구현하든, 아무리 복잡한 것이라도 별일이 아니에요. 그러니 경험과 지식은 특정 기술에 얽매이지 않는 방식으로 쌓으세요. 언어, 앱, 스택은 겉껍데기일 뿐이에요.
추가: 어디까지나 제 경험담이에요. 지금 제가 사람을 뽑는다면 지원자에게서 이런 걸 볼 거라는 얘기고요.
이런 일 때문에라도 저는 "중요한 건 나중에 하면 된다"는 사람들에게 반대합니다. 저는 그렇게 빠르게 달리는 기계의 엔진을 갈아 끼우고 싶지 않습니다. 실제 트래픽과 합성 트래픽에서 어떻게 동작하는지, 초당 수천 건의 트랜잭션을 처리할 때 어떤 방식으로 실패하는지를 익힐 시간이 없습니다.
문제가 아직 비교적 작을 때 그런 걸 정리해 두고 싶지 않을 이유가 있습니까?
그 밖에 합리적인 선택지는 문제가 너무 커져서 여러 도메인으로 갈라질 때까지 기다리는 것뿐입니다. 그러면 도메인 하나를 먼저 옮겨 보고, 잘 되면 더 옮길 수 있습니다.
실제 부하에서 시스템이 어떻게 동작할지 확실히 알 수 없다면, 트래픽을 새 시스템으로 옮겼다가 다시 옛 시스템으로 되돌리는 일을 여러 번 해야 할 수도 있습니다. 그러려면 양방향 마이그레이션이 모두 필요하고, 전환할 때마다 사람의 실수로 데이터가 날아가거나 서비스가 내려갈 위험이 생깁니다.
반론을 하나 들자면, 중요한 결정을 미룰수록 올바른 결정을 내릴 정보가 더 많이 쌓입니다. 그러면 DB 엔진을 1년에 두 번씩 갈아타는 일은 피할 수도 있겠죠.
제 생각에 당신과 답글 대상인 분은 사실 같은 얘기를 하고 있어요. "반론"이 아니라 "추가 논점"이죠.
정말 중요한 선택은 (단지) 방향을 틀 때 내리는 선택이 아니에요. 어떤 DB든(또는 시스템의 기반이 되는 비슷한 계층이든) 고르는 일은 언제나 중요한 결정이에요. 결국 선택지는 둘이에요. 충분히 따져 본 최선의 선택을 미루거나, 지금 내리거나. 지금이 아니라면 적어도 내게 맞는 최선의 선택을 할 만큼 데이터와 경험이 쌓이는 즉시 내려야 하고요.
제 생각에 당신은 잠재 비용의 대부분이 처음 선택에서 갈아타는 행위 자체에서 나온다고 보는 것 같아요. 하지만 갈아타는 비용은 그것이 시스템과 얼마나 얽혀 있느냐에 비례하고, 그건 대체로 운영 규모에 달려 있어요. 제가 본 문제는, 조직이 처음 선택에 별 고민 없이(고민이 있었다 해도 최소한만) 뭔가를 골라 놓고, 규모가 커져서 갈아타는 게 생사가 걸린 문제가 될 때까지 기다렸다가, 그제야 관성과 필사적으로 싸워야 한다는 거였어요. 당신이 답글을 단 분이 말하려는 것도 그게 아닐까 싶어요.
눈사태가 시작되면 조약돌이 표를 던지기엔 이미 늦습니다.
맞아요, 결정을 미룰 수 있다면 그건 강력합니다. 하지만 지금 얘기하는 건 이미 내려진 결정을 되돌리거나 다시 내려야 하는 경우입니다. 이런 경우에는 기술 부채가 우리 전문성보다 빨리 늘어날 때 무너집니다. 보통 일이 지체되는 이유는 문제에 자원을 투입할 시간이 없어서가 아니라 계속 자원을 투입하지 않아서입니다. 그러니 우리의 지식 기반은 거의 늘지 않죠. 특히 선두 주자라면 더 그렇습니다. 옮겨 가기엔 너무 늦어질 때까지는, 당신이 해 온 것보다 당신의 문제를 더 잘 풀어 줄 사람은 없습니다.
창업자입니다. 이 글은 저희 웨어하우스 제품에 관한 것이고, 메인 분석 DB와는 별개입니다. DuckDB 웨어하우스는 소수의 파일럿 고객이 썼고요. 분석 쿼리는 전부 ClickHouse 데이터베이스가 처리하고 있습니다.
다음에는 웨어하우스 제품에 VictoriaLogs를 써 보세요. 필드가 수백 개인 와이드 이벤트를 페타바이트 단위로 효율적으로 저장하고 쿼리할 수 있습니다. 자세한 내용은 https://docs.victoriametrics.com/victorialogs/keyconcepts/ 를 보세요. 단일 노드 구성에서 클러스터 구성으로 아주 쉽게 확장할 수 있어서, 고객당 인스턴스 하나로 시작해 워크로드가 늘어나면 스토리지 노드를 여러 대로 차츰 늘려 갈 수 있습니다. https://docs.victoriametrics.com/victorialogs/cluster/#single-node-and-cluster-mode-duality
소수 사용자를 대상으로 한 파일럿 프로그램이라고 쓰셨다면 블로그 글이 훨씬 더 말이 됐을 겁니다.
지금 쓰인 대로라면 엔지니어링 팀이 회사의 핵심 인프라를 통째로 옮기는 것처럼 보입니다.
제가 뭘 놓친 건가요, 아니면 이 글의 기술적인 내용이라곤 "행이 1조 개면 데이터가 많다, 이번엔 trinio가 통할지도 모른다"가 전부인가요?
측정이나 엔지니어링은 별로 없고 갈아엎기만 잔뜩 한 것 같은 느낌이에요.
제가 이 제품 사용자라면 "5개월 전에 소프트웨어를 다시 만들었는데 풀고 싶던 문제가 안 풀려서 또 하는 중이고, 이번엔 해결될지도 모른다"는 이 글의 메시지가 정말 걱정스러울 거예요.
[저자] 실제로는 이랬습니다. 저희가 고객이 돌리고 싶어 하는 워크로드의 문제와 복잡도를 과소평가했어요. 뭔가를 다시 만든 게 아니라, 웨어하우징을 하는 고객에게 제공할 수 있는 새 스택을 개발하고 있는 겁니다. 이런 맥락이 블로그 글에 제대로 드러나 있지 않다는 데는 동의합니다.
농담이 아니라, 지금 엔지니어링이 이뤄지는 방식을 보면 이런 일이 훨씬 더 많아질 거라고 생각해요. 저는 지난 2년간 그린필드 프로젝트 두 개에 참여했는데, 둘 다 그 기간에 여러 번 다시 쓰거나 "테세우스의 배" 같은 대규모 변경을 겪었어요.
새 제품을 만드는 엔지니어들은 LLM 덕분에 제품의 기술적 세부 사항을 거의 이해하지 못해요. 전통적인 고위 관리자가 자기 담당 제품에 대해 갖던 이해 수준과 같아요. 장애 리뷰에 꼬박꼬박 들어오는 M2나 M3가 있는 엔지니어링 조직에서 일해 본 적 있으면 아실 거예요. 장애 리뷰마다 Postgres나 Kafka 큐에 문제가 있는 건이 꼭 하나씩 나오고, 현장과 동떨어진 그 M3는 이렇게 결론을 내리죠.
제가 일이 어떻게 돌아가는지도 모르는 M2나 M3한테서 그런 한심한 소리를 들은 게 한두 번이 아니에요. 그들은 모든 문제의 교집합에 있는 듯한 키워드에 매달려요. 그러고는 그걸 없애 보고 어떻게 되는지 보자는 게 논리적인 해법이 되죠. 예전에는 이게 아주 비싼 일이었지만, 이제는 코드베이스에 LLM을 붙여서 "Postgres를 FancyDB로 교체해. 논리적인 체크포인트 목록으로 나누고, 각 체크포인트에 회귀 테스트가 없으면 추가하고, 모든 체크포인트를 스택형 PR로 열어"라고 시키면 되잖아요. 오후 내내 돌려 놓으면 46k줄짜리 PR과 (토큰 비용 800달러 청구서) 뒤에 FancyDB를 써 볼 준비가 끝나요. 안 해 볼 이유가 있을까요? 그러다 FancyDB에 문제가 생기면, 시간을 들여서 무슨 일인지 이해하려 할까요, 아니면 그냥 "다음엔 DynamoDB를 써 보자"고 할까요?
저는 이렇게 일하는 회사를 정말 많이 다녀 봤습니다. 도구가 새로울 뿐 방식은 새롭지 않아요. 망했다는 스타트업들 얘기를 들어 보면, 보통 바닥을 치기 전에 이런 걸 몇 번씩 했습니다.
솔직히 저한텐 전혀 새롭지 않은 얘기로 읽혀요. Claude Code가 누구 눈에도 반짝이기 전인 10년 전에 저도 비슷한 일을 겪었거든요(그리고 제가 바로 그 문제였고요).
그래서 "루프"라는 새 기능이 있는 거죠. 에이전트한테 데이터베이스 목록을 뽑아서 전부 프로덕션에서 돌려 보다가 괜찮은 걸 찾으라고 시키세요. "장애는 없어야 해"라고 꼭 덧붙이고요.
제가 보기에 핵심 "통찰"은 고객마다 VM을 하나씩(혹은 여러 대씩) 띄우고 쿼리를 라우팅하려면, 먼저 쿼리 비용을 추정할 수 있어야 한다는 겁니다.
Snowflake가 그렇게 하는 걸로 알고 있어요. 실행하러 보내기 전에 쿼리 최적화를 해서, 필요한 리소스가 대략 얼마인지 미리 알아요(물론 틀릴 수도 있지만요).
[저자] 기본적으로는 맞습니다. 다만 저희는 EKS에서 파드를 띄웠어요. 고객이 얼마나 필요할지 추정하기도 어려웠고, 저희가 용량을 얼마나 제공해야 할지 알기도 어려웠습니다. 가격을 CPU 시간(이나 비슷한 단위)으로 매길 계획이었기 때문에 그 로직이 사실상 맞지 않았어요.
Snowflake가 그 정보를 어떻게 쓰나요? 어차피 웨어하우스는 직접 골라야 하잖아요. 무거운 쿼리는 더 큰 웨어하우스로 라우팅되는 "탄력적 웨어하우스"가 있으면 좋겠지만, 그런 건 없어요.
[저자] 저희가 Trino의 도움으로 하고 있는 게 기본적으로 그겁니다. Trino는 쿼리가 필요로 하는 만큼 리소스를 동적으로 쓸 수 있는 분산 쿼리 엔진이에요.
탄력적 옵션이 있을 걸요. 그리고 웨어하우스를 정해 놓더라도 모든 쿼리가 웨어하우스의 모든 노드를 쓰는 건 아니에요.
맞아요, 수평 확장 옵션은 있어요. 쿼리가 많이 대기하면 Snowflake가 노드를 하나 더 띄울 수 있죠. 하지만 쿼리가 원격 스토리지로 스필되고 있다면 그건 도움이 안 돼요. 그런 쿼리를 빠르게 하려면 더 큰 노드가 필요하거든요.
Snowflake에는 리소스를 더 추가하는 옵션이 있고 수직 확장을 하라는 뜻이겠지만, 웨어하우스 크기를 키우는 것만큼 잘 되지는 않아요.
쿼리 플래너/옵티마이저는 웨어하우스 안에서 돌아가지 않아요. 이런 걸 예측하는 게 옵티마이저의 주된 기능 중 하나고요.
안녕하세요! 저자입니다.
저희는 설계를 했고, 측정을 했고, 그런 다음 어떻게든 동작하게 만들려고 했습니다. 현재 아키텍처를 완전히 버리고 처음부터 다시 시작하기로 결정하기 전까지 아마 너무 오래 매달렸을 겁니다. 질문이 더 있으면 기꺼이 답하겠습니다.
왜 처음부터 그냥 Iceberg와 Trino(멋을 부리려면 Paimon)를 쓰지 않으셨어요? 이건 꽤 오래전부터 정답으로 받아들여진 방식인데요. 빠른 OLAP 저장소는 오브젝트 스토리지에서 Trino 같은 제대로 된 쿼리 엔진으로 가는 방식만큼 확장되지 않아요.
Iceberg도 써 봤는데 데이터를 쓰는 속도가 너무 느렸다는 게 짧은 답입니다.
저희가 이 프로젝트를 시작한 이유가 바로 그겁니다.