[메인터뷰] 는 메인테이너가 메인이 되는 인터뷰로, 클라우드브로 커뮤니티가 오픈소스 빌더들의 이야기를 기록하는 시리즈의 여섯 번째 편입니다.
고종현 님은 TanStack Query의 메인테이너입니다. 전 세계 프론트엔드 엔지니어가 매일 쓰는 라이브러리를 유지 관리하는 사람인데, 오픈소스를 어떻게 시작했느냐는 물음에는 이렇게 답했습니다.
“오픈소스를 하고 싶어서 한 게 아니에요. 그냥 제가 쓰는 툴이 오픈소스였던 거죠.”
거창한 사명이 아니라 자기가 쓰는 도구를 제대로 알고 싶었던 마음에서 출발했다는 이야기입니다. 인터뷰를 마치고 그의 답들을 다시 늘어놓아 보니, 서로 다른 주제 같던 이야기들이 하나로 꿰였습니다. 어떻게 신뢰를 쌓고, 어떻게 그 신뢰를 지키는가. 기여의 시작도, 메인테이너가 된 계기도, 상업화를 보는 시선도 전부 그 축 위에 있었습니다.
디자인에서 엔지니어로
고종현 님은 원래 디자인을 전공했습니다. 입시 미술만 4년을 했고, 색감과 자간, 행간, 마진이 왜 그렇게 놓여야 하는지를 오래 들여다본 사람입니다. 2019년에는 졸업작품으로 TouchFlow라는 앱을 만들어 창업까지 했습니다. 맥북의 터치바에서 영상편집 단축키를 시각화해 눌러 쓸 수 있게 한 유틸리티였습니다.
창업은 오래가지 않았습니다. 외부 플랫폼에 대한 의존이 컸고, 그 플랫폼이 워낙 거대해 언제든 흔들릴 수 있는 리스크였습니다. 시장 자체도 크지 않았습니다. 그런데 그 경험이 그를 다른 곳으로 데려갔습니다.
“창업을 하다 보니 느낀 게, 엔지니어로 일을 해도 괜찮겠다는 거였어요. 더 다양한 문제 해결에 참여할 수 있으면 그것도 행복한 삶일 것 같아서요.”
창업이 목표가 되어서는 안 된다고 그는 분명히 했습니다. 목표는 문제 해결이고, 창업이든 직함이든 그건 수단이라는 것입니다. 그렇다고 디자인을 버린 것도 아니었습니다. 그는 디자인과 엔지니어링을 나뉜 것으로 보지 않습니다.
“디자이너는 좀 더 큼직한 엔지니어링을 하는 거고, 엔지니어는 디자이너가 못 보는 디테일을 하나씩 잡아주는 사람이라고 생각해요.”
만들고 싶은 게 있어서 디자인을 배웠고, 디자인만으로는 구현이 안 되니 엔지니어가 됐다는 설명이었습니다. 그 배경은 지금도 쓸모가 있습니다. 리소스가 부족해 엔지니어 혼자 화면을 만들어야 하는 어드민 작업에서, 논리적으로 디자인할 수 있는 감각이 다른 엔지니어에게는 없는 강점이 됩니다.
내가 쓰는 툴을 이해하려고
TanStack에 발을 들인 계기도 같은 자리에서 시작됩니다. 프론트엔드가 늘 하는 일은 서버의 상태를 받아와 화면에 보여주는 것입니다. 그가 개발을 시작하던 무렵, 이 서버 상태를 다루는 방식은 춘추전국시대에 가까웠습니다. Redux가 있었고, 그 위에서 비동기를 다루려고 Redux Thunk나 Saga가 쓰였습니다.
문제는 이 도구들의 출발점이었습니다.
“이 라이브러리들이 처음부터 서버 상태를 제어하려고 만들어진 게 아니라 비동기 자체에 맞춰져 있다 보니, 인터페이스를 이해하는 것 자체가 난이도가 높았어요.”
Redux 계열은 클라이언트의 상태를 한곳에 모아 흐름을 통제하려는 도구였고, 비동기는 그 위에 얹은 확장이었습니다. 그런데 프론트엔드가 실제로 가장 자주 하는 일은 서버의 상태를 가져와 캐시하고, 언제 다시 불러올지를 정하는 것입니다. TanStack Query는 이 문제를 정면으로 잡아 서버 상태라는 개념을 일급으로 끌어올렸고, 캐싱과 재요청 정책을 높게 추상화해 두었습니다. 그래서 이해하기가 쉬웠습니다.
고종현 님은 이 라이브러리를 팀에 도입하고 싶었는데, 당시 다니던 회사에서는 쓰지 않는 곳이 있었습니다. 근거 없이 도입을 주장하는 건 위험한 일이라, 먼저 제대로 알아야겠다고 생각했습니다. 그래서 테스트 코드의 스펙부터 들여다봤습니다. 커버가 덜 된 부분을 채우고, 타입이 아쉬운 곳을 손보는 식으로요.
“저 혼자만 쓰면 라이브러리가 인터페이스로서 가치가 없잖아요. 다른 사람도 쓰게 하고 싶었어요. 그러려면 제가 먼저 제대로 이해해야 했고요.”
인터페이스는 여러 사람이 같은 약속을 공유할 때 비로소 가치를 갖습니다. 그가 기여에 들어간 동기가 바로 그 지점이었습니다. 자기가 이해한 도구를 남도 믿고 쓸 수 있게 만드는 일. 신뢰라는 축이 여기서 처음 드러납니다.
매번 터지던 테스트
메인테이너로 인정받은 전환점은 화려한 신기능이 아니었습니다. 오히려 가장 지루한 축에 드는 작업이었습니다.
TanStack Query의 CI 테스트가 이상하게 불안정했습니다. 그가 PR을 올릴 때마다 GitHub Actions의 테스트가 간헐적으로 실패했습니다. 글로벌 라이브러리의 테스트가 이렇게 들쭉날쭉 터진다는 건 큰 문제였습니다. 그가 짚은 지점이 정확했습니다.
“테스트가 터지는 건 괜찮아요. 오히려 항상 터져야 하는데, 간헐적으로 터지는 건 이게 더 큰일이거든요.”
이 말에는 테스트에 대한 정확한 감각이 담겨 있습니다. 테스트는 참이든 거짓이든 결정적이어야 합니다. 조건이 같으면 항상 통과하거나 항상 실패해야 하고, 그래야 결과를 신호로 믿을 수 있습니다. 같은 코드가 어떤 날은 통과하고 어떤 날은 실패하는 flaky한 상태는, 실패보다 나쁩니다. 무엇을 믿어야 할지 알 수 없게 만들기 때문입니다.
원인은 테스트가 Real Timer을 쓰는 데 있었습니다. 타이머가 도는 동안 CI를 돌리는 기기의 성능과 부하에 따라 미세한 시간 차가 생겼고, 그 차이가 결과를 갈랐습니다. 해법은 Fake Timer로 바꾸는 것이었습니다. 실제 시계 대신 테스트가 시간을 직접 제어해, 타이머를 원하는 만큼 인위적으로 흘려보내는 방식입니다. 이렇게 하면 기기 성능과 무관하게 언제나 같은 순서로 같은 결과가 나옵니다.
문제는 규모였습니다. TanStack Query는 데이터를 언제 다시 불러올지, 캐시를 언제 만료시킬지처럼 시간과 얽힌 로직이 코드 전반에 퍼져 있는 라이브러리입니다. 시간 처리를 손대려면 전부를 손대야 했습니다.
“제가 기여를 하려면 CI가 100퍼센트 믿을 수 있어야 하는데, 그게 고장 나 있으니까 이것부터 고치지 않으면 안 되겠다 싶었어요.”
그는 코드베이스를 라인 단위로 전부 갈아엎었습니다. 이 노가다가 TanStack 팀의 눈에 들었습니다. TanStack Query 메인테이너 TkDodo가 디스코드로 같이 해보자고 제안하면서 그는 메인테이너로 합류하게 됐습니다.
여기에 곱씹을 지점이 있습니다. 그를 메인테이너로 만든 건 새 기능이 아니라, 모두가 딛고 서는 바닥을 다시 믿을 수 있게 만든 일이었습니다. 오픈소스에서 신뢰는 화려한 기여가 아니라 이런 기반 작업에서 쌓입니다. 눈에 잘 안 띄고, 생색도 안 나고, 그래서 아무도 선뜻 떠맡지 않는 일. 그걸 끝까지 해낸 사람에게 TanStack 팀이 문을 열었습니다. 막상 안에서 본 메인테이너의 일은 생각과 달랐습니다.
“메인테이너는 유지 관리자잖아요. 사실 더럽고 지루한 작업이 훨씬 많아요. 테스트 코드, 문서화, CI 같은 것들이요.”
거절이 아니라 보완
큰 라이브러리에는 기능 요청이 끊임없이 들어옵니다. TanStack Query처럼 규모가 큰 프로젝트라면 인기 있는 요청을 거절하다 반발을 사는 일도 있을 법합니다. 그런데 그는 거절한 기억이 별로 없다고 했습니다.
“좋은 기능이니까 항상 제안을 해주시는 거라서, 거절이라기보다는 보완하는 쪽인 것 같아요.”
mutationOptions라는 인터페이스가 그런 경우였습니다. TanStack Query에는 데이터를 읽어오는 Query와 데이터를 바꾸는 Mutation이 있습니다. 이미 잘 쓰이던 QueryOptions에는 queryKey라는 필수값이 있어서, 그 키를 기준으로 타입을 안전하게 보장할 수 있었습니다. 그런데 MutationOptions에는 mutationKey가 필수값이 아닙니다. 기준이 될 타입이 없으니 사용처에서 타입을 어떻게 보장할지가 까다로운 문제였습니다. 그는 거절하는 대신, 이런 경우 저런 경우를 하나씩 짚어가며 각 케이스에서 타입이 무너지지 않게 보완하는 지난한 과정을 거쳤습니다.
버전을 관리하는 방식에도 그의 시선이 담겨 있었습니다. 메이저 버전을 올릴 때 사용자와 메인테이너의 기대가 어긋난다는 것입니다.
“메이저 버전을 올릴 때는 새 기능을 넣으면서 브레이킹 체인지를 내야 사람들이 다음 버전으로 넘어와요. 그렇게 넘어온 분들이 많아지면 그때 백포팅을 해서 변경 사항을 줄여주는 거죠.”
이 타이밍 감각이 흥미롭습니다. 사용자는 메이저 버전에서 더 나은 개발 경험을 기대하지만, 메인테이너에게 메이저 버전은 하위 호환을 깨는 부담스러운 결정입니다. 그래서 그는 먼저 신기능과 함께 브레이킹 체인지를 내보내 사람들이 넘어올 동기를 만들고, 충분히 넘어온 뒤에 이전 버전으로 필요한 기능을 백포팅해 변경 폭을 줄입니다. 억 단위 사용자를 한 번에 절벽에서 밀지 않고 완만한 경사로 옮겨 태우는 일입니다. 라이브러리가 살아남으려면 안 할 수 없는 작업이라고 그는 말했습니다. 그리고 한마디를 덧붙였습니다. 결국 자기가 필요해서 한 일이라고요.
기술은 도구다
인터뷰 내내 그의 답변에는 하나의 축이 있었습니다. 기술 자체가 목표가 아니라는 것입니다.
“기술은 어떤 메시지를 전달하기 위한 도구지, 기술 자체가 목표가 돼서는 안 된다고 생각해요.”
라이브러리를 깊이 파고들다 보면 기술에만 몰두하는 사람으로 비치기 쉬운데, 그는 그렇게 읽히는 걸 경계했습니다. 도구를 잘 알고 싶은 이유는 전하려는 것을 잘 전하기 위해서지, 도구를 다루는 일 자체가 목적은 아니라는 것입니다.
디자인을 했던 것도 같은 맥락이었습니다. 무언가 만들고 싶은 게 있었고, 그걸 만들려니 디자인이 필요했고, 디자인만으로 안 되니 엔지니어링으로 넘어왔습니다. 그에게 두 일은 늘 무언가 만들고 있는 한 사람의 상태였습니다. 앞의 기술 이야기들이 왜 하나같이 신뢰로 수렴했는지도 여기서 풀립니다. 도구가 목적이면 화려한 기능을 좇게 되지만, 전달이 목적이면 사람들이 그 도구를 믿고 쓸 수 있는지가 먼저입니다. 그가 flaky한 테스트를 갈아엎고, 기능 요청을 보완으로 받고, 백포팅으로 완만한 이전을 설계한 건 전부 그 우선순위에서 나온 선택이었습니다.
돈을 받지 않는다는 것
오픈소스를 지속하는 문제에 이르자 그의 답은 한층 신중해졌습니다. 풀타임으로 오픈소스만 하는 것에는 현실적인 한계가 있다고 봤습니다.
“서비스 개발자가 써야 할 라이브러리를 만드는 입장인데, 제가 서비스 개발자가 아니면 현실적이지 못한 기능이 나올 수 있거든요.”
사용자로 남아 있어야 라이브러리를 제대로 유지할 수 있다는 이야기입니다. 만드는 사람과 쓰는 사람이 분리되는 순간 감이 떨어진다는 것인데, 이건 라이브러리처럼 남이 쓸 것을 만드는 일에서 특히 날카로운 통찰입니다. TanStack은 이름 자체가 Tanner의 Stack에서 왔습니다. 이윤을 좇기보다 최고의 웹을 만들자는 미션으로 굴러가고, Cloudflare와 CodeRabbit 같은 후원 파트너가 붙어 있습니다.
상업화 이야기에서 그는 자기 자리부터 분명히 했습니다. 기여하는 입장이라 자금을 논할 위치가 아니라는 전제를 먼저 달았고, 그 위에서 자기 생각을 꺼냈습니다.
“기술을 파는 사람이 그 기술을 충분히 이해하고 있어야 할 텐데, 다양한 기술을 다 그렇게 이해하는 게 정말 어려울 거라서요.”
MIT 라이선스 이야기도 나왔습니다. 그는 돈을 받지 않는다는 사실이 오히려 메인테이너를 보호하는 면이 있다고 봤습니다. MIT 라이선스는 소프트웨어를 있는 그대로 제공하고, 그로 인해 생기는 문제의 책임을 제작자에게 묻지 않는 구조입니다. 무상으로 내놓았기에 책임에서 자유로운 것인데, 돈을 받고 파는 순간 그 무상성이 흔들리고 책임의 경계가 모호해집니다. 그가 조심스러워한 지점이 바로 여기였습니다. 답을 내리기보다, 판단할 근거가 아직 부족하다고 그는 말했습니다.
그리고 커뮤니티
앞의 질문들은 그냥 흘려보낼 물음이 아닙니다. 판매하는 쪽이 그 다양한 기술을 다 이해할 수 있는가, MIT 라이선스 아래에서 제값을 받는 근거는 무엇인가. 클라우드브로가 답을 하나씩 쌓아가야 하는 질문이 바로 이런 것들입니다. 메인테이너가 코드의 소유권을 그대로 쥐고, 상업 실행권만 파트너가 맡아 기업에 맞는 형태로 다듬고 제값을 받게 하는 구조. 그 구조가 정말 메인테이너를 지키는지 아닌지는 말이 아니라 레퍼런스로 증명해야 하는 문제라고 봅니다.
고종현 님의 이야기를 관통한 신뢰라는 축은, 클라우드브로가 풀려는 문제와도 맞닿아 있습니다. 그가 flaky한 테스트를 고쳐 코드에 대한 신뢰를 세웠다면, 오픈소스를 상업화하는 일에는 다른 종류의 신뢰가 필요합니다. 이 프로젝트가 기업 환경에서 정말 돌아가는가, 값을 매길 만한가에 대한 신뢰입니다. 그가 지적했듯 파는 쪽이 기술을 충분히 이해하지 못하면 그 신뢰는 서지 않습니다. 그래서 우리는 프로젝트를 그대로 파는 대신, 기업에 맞는 형태로 다듬고 검증한 레퍼런스로 그 신뢰를 하나씩 세우려 합니다.
지속 가능성의 딜레마도 그가 정확히 짚었습니다. 후원에만 기대서는 프로젝트를 오래 끌고 가기 어렵고, 그렇다고 풀타임으로 뛰어들자니 사용자로 남아야 한다는 현업의 자리를 놓칠 수 없습니다. 코드로 직접 기여할 수 없는 우리가 이 생태계에 보탤 몫이 있다면, 메인테이너가 후원과 기부에만 매달리지 않고 자기 프로젝트로 자생할 길을 함께 찾는 일이라고 생각합니다.
메인테이너가 메인이 되는 [메인터뷰] 의 여섯 번째 이야기는, 기술을 도구로 두고 문제 해결에 집중하려는 한 프론트엔드 개발자의 이야기로 채웠습니다.
[메인터뷰] 는 클라우드브로 커뮤니티가 오픈소스 빌더들의 이야기를 기록하는 시리즈입니다. 다음 편에서 또 다른 빌더를 소개할게요!
