Val Town이 Supabase와 Clerk를 지나 Better Auth로 인증 시스템을 옮기며 겪은 문제, 교훈, 그리고 전환 과정을 돌아봅니다.
Elsewhere Elsewhere
Tom MacWright2026년 5월 6일
2023년에 저는 Val Town이 어떻게 Supabase를 떠났는지, 그리고 더 전통적인 데이터베이스 구성으로 이동했는지에 대해 쓴 적이 있습니다. 당시 우리는 Supabase의 기능을 많이 사용하고 있었고, 그중에는 인증도 포함되어 있었습니다. 그래서 옮길 때는 대응되는 서비스를 찾았습니다. 데이터베이스는 Render, 인증은 Clerk를 사용했습니다. 하지만 상황은 빠르게 바뀌었고, 2023년 말에는 Clerk를 벗어나자는 이슈가 등록되었습니다. 그 이슈는 마침내 한 달 전에 닫혔고, 우리가 Better Auth로 전환하면서 마무리되었습니다.
중요한 맥락 하나는 Clerk가 큰 성공을 거둔 서비스라는 점입니다. 최근 5천만 달러를 유치했고, 만족하는 사용자도 많습니다. 비슷한 소식으로 Supabase도 기업가치 50억 달러에 1억 달러를 유치했습니다. 두 회사 모두 축하합니다. 저는 아마 형편없는 벤처 투자자가 될 것입니다. 인증과 row level security에 대해 제가 가진 의견과 경험은 이런 숫자와 성과 앞에서는 부차적입니다. 성공에는 반박하기 어렵습니다.
그럼에도 불구하고, 그 이슈를 닫고 Better Auth로 전환하게 되어 저는 기쁩니다. 그 과정은 힘들었고, 우회책과 버그, 장애가 많았습니다. Val Town의 아키텍처는 Clerk가 기대하는 방식과 크게 충돌했습니다.
핵심 문제는 Clerk가 여러분의 users 테이블이면서 동시에 sessions 테이블이 되려 했다는 점입니다. 요즘은 이런 식의 표현에서 조금 물러난 것 같지만, 시작점은 꽤 극단적이었습니다. 2021년 블로그 글 제목은 "users 테이블을 없애는 것을 고려해보세요"였습니다. 2023년에는 Users 테이블을 DELETE하라라는 YouTube 영상도 있었습니다. 저는 정말 그러지 말라고 강하게 권하고 싶습니다.
users 테이블을 서드파티 서비스에 맡기는 데에는 두 가지 큰 문제가 있습니다.
Clerk는 users 테이블의 대체재로는 꽤 좋지 않았습니다. 강한 rate limit이 있었고, 신뢰성도 그다지 높지 않았기 때문입니다. 처음 전환했을 때 저는 필요할 때마다 Clerk의 API에서 사용자 데이터를 불러오면 된다고 생각했습니다. 결국 우리는 사용자 설정, 아바타 URL, 이메일 같은 정보를 알아야 합니다. Clerk의 SDK는 이 점을 꽤 편리하게 만들어주었습니다. 전체 애플리케이션의 인증을 처리하는 rootAuthLoader에는 loadUser라는 작은 옵션이 있었고, 이 옵션이 요청을 대신 수행해주었습니다. 개발 환경에서는 잘 작동했습니다. 하지만 프로덕션에서 그 엔드포인트의 rate limit은 _초당 다섯 요청_이었습니다. 전체 계정 기준으로, 모든 사용자를 통틀어 말입니다. 난감하죠! 꽤 위험한 함정이었고, 우리는 이를 프로덕션에서 발견했습니다. 결국 그 옵션을 제거하는 방식으로 수정되었습니다.
이 rate limit은 특히 Val Town의 소셜 측면에서 큰 타격을 주었습니다. 예를 들어 소셜 웹사이트에서는 많은 페이지에 다른 사용자의 콘텐츠 목록이 있고, 그들을 식별하기 위해 사용자 이름과 아바타가 표시됩니다. Clerk의 기본 UI는 사용자가 오직 자기 자신의 아바타만 보고, 자기 설정과 정보만 필요로 하며, 그 모든 것을 멋진 JWT 토큰에서 얻을 수 있다는 가정에 기반하고 있습니다. Val Town 같은 소셜 웹사이트는 이 가정을 완전히 깨뜨립니다. 그리고 권장된 방식은 Clerk와 우리 users 테이블 사이에서 아바타와 기타 정보를 동기화하라는 것이었습니다. 그렇게 되면 이제 같은 정보에 대해 두 개의 권위 있는 원천이 생기고, 두 개의 users 테이블이라는 복잡성이 따라옵니다.
그래서 우리는 webhook을 사용해 Clerk의 데이터를 우리 데이터베이스와 동기화해야 했고, 그 결과 회원가입 과정은 복잡하고 까다로워졌습니다. 잠깐 동안 사용자는 Clerk 계정은 있지만 Val Town 데이터베이스의 row는 없는 상태가 됩니다. 또는 우리 플랫폼은 사용자 이름을 요구하기 때문에, 사용자가 Clerk 계정도 있고 데이터베이스 row도 있지만 계정은 아직 완성되지 않은 상태일 수도 있습니다. 사용자 설정 역시 Clerk가 제어하는 인증 전략 같은 것과, 우리가 필요로 하는 사용자 이름이나 에디터 설정 같은 것으로 나뉘어야 했습니다.
두 번째 문제는 Clerk가 모든 사용자 세션의 단일 장애 지점이 되었다는 것입니다. 쿠키 기반 사용자 세션은 보통 짧은 수명을 가지며 계속 갱신됩니다. 그래야 빠르게 무효화할 수 있기 때문입니다. 하지만 그것은 또한 사용자가 몇 분마다 세션 쿠키를 새 것으로 교체해야 한다는 뜻이기도 합니다. 그래서 누군가의 로그인 세션을 갱신해야 할 때면, Val Town의 한 서브도메인이 요청을 Clerk로 전달해 갱신을 처리했습니다. 우리는 sessions 테이블도 없었고, 세션에 대한 책임도 전혀 지고 있지 않았습니다.
인증에 대한 책임을 최대한 지지 않으려 한다면 그것도 좋습니다. 하지만 반대로 Clerk가 다운되면 웹사이트 전체가 다운됩니다. Clerk 장애는 로그인 및 로그아웃 흐름만 깨뜨리는 것이 아니라, 이미 로그인한 사람들에게도 사이트를 사용할 수 없게 만듭니다. 그리고 Clerk는 꽤 자주 다운되었고, 다운된 상태가 오래 지속되기도 했습니다. 2025년 5월 이후로 uptime은 두 개의 9와 세 개의 9 사이를 오락가락하고 있습니다. 그 이전 데이터는 없지만, 이 단일 장애 지점 때문에 사이트가 망가졌는데도 우리가 고칠 방법이 없었던 때를 저는 여러 번 기억합니다.
복잡한 시스템을 만들면서 배우는 어려운 교훈 하나는, 그 시스템의 신뢰성은 핵심 구성 요소들의 결합된 신뢰성 중 _최솟값_이라는 점입니다.
이 두 가지 큰 문제 외에도, 우리는 다른 버그와 문제들을 겪었습니다. 대부분은 결국 수정되었지만, 자동으로 이슈를 닫아버리는 "Stale Issue Bot"과 싸우는 데에도 많은 시간을 썼습니다.
그렇게 안 좋았다면 왜 바로 전환하지 않았을까요?
우선, 제가 쓴 "X에서 Y로 전환하기" 글이 이번으로 두 번째가 되기는 하지만, 그걸 습관으로 만들고 싶지는 않습니다. 결정을 내리고 그것을 유지하는 일은 개발 속도와 팀의 정신 건강에 좋습니다. 우리는 절대적으로 필요한 경우가 아니면 Val Town을 다시 쓰려고 하지 않습니다. 그리고 비판적인 글을 쓰는 일은 무언가를 만드는 일보다 덜 즐겁고 덜 긍정적입니다.
그리고 Clerk가 잘한 점도 있었습니다. 우리가 사용하던 모든 기술 스택, 즉 Remix, Fastify, Express를 위한 SDK를 제공했습니다. 또 그 프레임워크들의 빠른 변화도 꽤 잘 따라갔습니다. 저는 그 작업이 사실상 전업이라는 것을 알고 있습니다. 그리고 그들의 관리자 기능과 악용 방지 조치는 고객 지원 문제를 해결하고 사기꾼을 막는 데 꽤 괜찮았습니다.
Clerk가 확실히 빛나는 지점은 비교적 단순하고 프런트엔드 비중이 큰 앱이며, 소셜 요소가 없어서 users 테이블이 필요하지 않은 경우입니다. 시작하기는 정말 쉬웠고, 가격도 감당 가능했으며, Clerk 대시보드도 꽤 괜찮습니다.
게다가 인증 분야에는 정말 훌륭한 선택지가 많지도 않습니다. Clerk의 대체재에게 요구되는 기준은 사실 꽤 높았습니다. 많은 오픈 소스 인증 솔루션은 오래되었고 사실상 반쯤 버려진 상태입니다. authentication-as-a-service 플랫폼은 벤더 리스크가 있었고, Clerk에서 겪은 것과 비슷한 문제를 가질 가능성도 있었습니다. 어느 정도의 기술적 통제권이 적절한지는 맞추기 어렵습니다. 우리는 인증을 처음부터 직접 만들고 싶지는 않습니다. 그러면 Val Town이 새롭고 민망한 취약점에 노출될 수 있기 때문입니다. 하지만 그렇다고 공급자에게 너무 많은 책임을 넘기고 싶지도 않습니다. 특히 서드파티 세션 관리는 다시는 믿지 않을 생각입니다.
Better Auth는 시작부터 많은 조건을 충족했습니다. 코드 품질이 높고, 다양한 프레임워크와의 통합이 좋았으며, 독립적인 오픈 소스 프로젝트로도 정말 실용적이었습니다.
여전히 벤더 리스크는 있습니다. 거대하고 복잡한 코드베이스이고, 대부분 한 회사가 개발하고 있기 때문입니다. 벤더 리스크는 언제나 존재합니다. 하지만 이제 우리는 세션과 사용자 인증이 동작하기 위해 서드파티가 온라인 상태를 유지해야 하는 상황에는 더 이상 의존하지 않습니다.
아주 근소한 차이로 두 번째 후보는 WorkOS의 AuthKit이었습니다. 저는 WorkOS를 신뢰하고, AuthKit은 놀라울 정도로 매끄럽습니다. 하지만 두 벤더를 오가고 난 뒤에는, 독립적으로 동작할 수 있고 핵심이 오픈 소스인 무언가를 찾는 것이 제게 중요했습니다.
Better Auth의 대시보드와 유료 추가 기능도 아주 영리하다고 생각합니다. 우리는 모든 데이터를 직접 관리하고, 플러그인이 우리 사이트에 API를 제공해서 그들의 대시보드가 정보를 가져오고 간단한 사용자 관리를 할 수 있게 합니다. Better Auth의 유료 서비스는 'Infrastructure'라고 불리는데, 우리가 사용하는 방식에서는 기본적으로 stateless하며 세션 관리에는 관여하지 않습니다.
요컨대, 지금까지는 정말 더 나았습니다.
그리고 여기서는 마지못해 LLM들에게 공을 돌려야겠습니다. 로봇들의 보강 덕분에 우리는 2주간의 전환 기간 동안 Better Auth와 Clerk를 모두 지원하는 더 복잡한 경로를 택할 수 있었습니다. 인증을 처리하는 모든 엔드포인트는 두 종류의 쿠키를 모두 받아들였고, 사용자는 로그인 페이지가 제공하는 세션 유형을 따라 천천히 Better Auth로 옮겨갔습니다. 보안과 관련된 모든 일이 그렇듯, 스스로 문제를 만들지 않도록 모든 코드를 면밀히 읽고, 다시 쓰고, 테스트하는 일이 필요했습니다. 그리고 최종적인 순수 Better Auth 인증은 전부 손으로 직접 작성했습니다.
Better Auth는 Vals와도 꽤 잘 맞습니다. Better Auth starter template를 사용해 Val Town의 코드에 인증을 추가해볼 수 있습니다.
그 과정에서 많은 것을 배웠습니다. 상위 공급자의 uptime에 정말로 의존하게 되며, 자신이 그 위험에 얼마나 노출되어 있는지 깊이 생각해야 합니다. 어떤 제품은 많은 사용 사례에 잘 맞고 큰 성공을 거두더라도, 여러분의 특정 문제에는 여전히 맞지 않을 수 있습니다. 소프트웨어 세계는 빠르게 변하고, 여러분이 필요로 하는 바로 그 순간에는 적절한 해법이 없을 수 있지만 1년 뒤에는 나타날 수도 있습니다.
Twitter에 공유Bluesky에 공유Hacker News에 공유
채용 중입니다!
우리 팀에 합류해 프로그래밍의 미래를 함께 만들어 주세요.
© 2026 Val Town