3P by GN⁺ 16시간전 | ★ favorite | 댓글 1개
  • Val Town은 2023년 Supabase에서 벗어나 데이터베이스는 Render, 인증은 Clerk로 옮겼지만, 사용자·세션 책임을 외부화하는 구조가 맞지 않아 한 달 전 Better Auth로 전환함
  • Clerk는 사용자 테이블을 없애는 방향을 제안했지만, Val Town은 소셜 기능 때문에 여러 사용자의 콘텐츠, 사용자명, 아바타를 자주 보여줘야 했고, Clerk API 제한과 동기화 때문에 사실상 사용자 테이블 두 개를 운영하는 복잡성이 생김
  • Clerk가 세션 갱신까지 맡으면서 단일 장애 지점이 됐고, Clerk 장애 시 로그인·로그아웃뿐 아니라 이미 로그인한 사용자도 전체 사이트를 쓰기 어려워졌으며, 2025년 5월 이후 상태 페이지 기준 가동률은 99%와 99.9% 사이를 오감
  • Val Town은 Clerk의 SDK, 관리 기능, 남용 방지, 대시보드가 유용했기 때문에 즉시 재작성하지 않았지만, 타사 세션 관리를 다시 신뢰하지 않겠다는 기준을 세움
  • Better Auth는 코드 품질, 프레임워크 통합, 독립적인 오픈소스 핵심이 요구에 맞았고, Val Town은 약 2주 동안 Clerk와 Better Auth를 함께 지원하며 두 종류의 쿠키를 받아 점진적으로 세션 이전을 진행함

전환 배경

  • Val Town은 2023년에 Supabase에서 벗어나 더 전통적인 데이터베이스 구성으로 이동하면서, 데이터베이스는 Render, 인증은 Clerk로 대체함
  • 2023년 말에는 Clerk에서 벗어나야 한다는 이슈가 등록됐고, 한 달 전 Better Auth로 전환하면서 해당 이슈가 닫힘
  • Clerk와 Supabase는 각각 5,000만 달러 투자, 50억 달러 가치로 1억 달러 투자를 유치한 성공적인 서비스지만, Val Town의 구조는 Clerk의 기대와 크게 충돌했음
  • 전환 과정에는 많은 우회책, 버그, 장애가 있었고, 특히 Clerk가 사용자 테이블과 세션 테이블을 모두 대신하려는 구조가 핵심 문제로 드러남

핵심 문제: 사용자 테이블과 세션 테이블의 외부화

  • Clerk를 사용자 테이블로 쓰기 어려웠던 이유

    • Clerk는 2021년 “Consider dropping your users table” 글과 2023년 “DELETE your Users table” 영상처럼 사용자 테이블을 없애는 방향을 강하게 제안함
    • Val Town은 초기 전환 시 사용자 설정, 아바타 URL, 이메일 같은 데이터를 필요할 때마다 Clerk API에서 가져올 수 있다고 봤음
    • Clerk SDK의 rootAuthLoader에는 애플리케이션 전체 인증을 처리하면서 사용자 데이터를 요청하는 loadUser 옵션이 있었고, 개발 환경에서는 잘 동작함
    • 프로덕션에서 해당 엔드포인트의 제한은 계정 전체, 모든 사용자 합산 초당 5개 요청이었고, 이 문제는 나중에 옵션 제거로 해결됨
    • Val Town처럼 소셜 기능이 있는 서비스는 여러 페이지에서 다른 사용자의 콘텐츠, 사용자명, 아바타를 보여줘야 하므로, 사용자가 자기 아바타와 설정만 JWT에서 읽는다는 Clerk 기본 UI의 가정과 맞지 않았음
    • Clerk 측 조언은 아바타와 기타 정보를 Clerk와 Val Town 사용자 테이블 사이에 동기화하는 것이었고, 결과적으로 같은 정보의 권위가 두 곳으로 나뉘어 사용자 테이블 두 개를 운영하는 복잡성이 생김
  • 웹훅 동기화가 만든 가입 흐름의 복잡성

    • Clerk 데이터를 Val Town 데이터베이스에 동기화하려면 웹훅을 써야 했고, 가입 과정은 복잡하고 까다로워짐
    • 가입 직후 잠시 동안 사용자는 Clerk 계정은 있지만 Val Town 데이터베이스 행은 없는 상태가 될 수 있었음
    • Val Town은 사용자명이 필수이기 때문에, 사용자가 Clerk 계정과 데이터베이스 행은 있지만 계정이 아직 완성되지 않은 상태에도 놓일 수 있었음
    • 사용자 설정은 인증 방식처럼 Clerk가 관리하는 항목과 사용자명, 에디터 설정처럼 Val Town이 필요한 항목으로 나뉘어야 했음

Clerk가 단일 장애 지점이 된 세션 구조

  • 쿠키 기반 사용자 세션은 보통 짧게 유지되고 계속 갱신되며, 그래야 빠르게 무효화할 수 있음
  • 이 구조에서는 몇 분마다 사용자가 세션 쿠키를 새 쿠키로 교환해야 했고, Val Town의 서브도메인이 Clerk로 요청을 전달해 갱신을 처리함
  • Val Town은 세션 테이블을 갖지 않았고 세션에 대한 책임도 지지 않았음
  • 이 방식은 인증 책임을 피하려는 경우에는 좋지만, Clerk가 내려가면 로그인과 로그아웃만 깨지는 것이 아니라 이미 로그인한 사용자에게도 전체 사이트가 사용할 수 없게 됨
  • Clerk는 자주, 그리고 긴 시간 동안 장애가 있었고, 2025년 5월 이후 상태 페이지 기준 가동률은 99%와 99.9% 사이를 오감
  • 복잡한 시스템의 신뢰성은 중요한 구성 요소들의 결합 신뢰성 중 최솟값에 묶임
  • 이 두 가지 큰 문제 외에도 Clerk 관련 다른 버그와 문제가 있었고, 대부분은 결국 수정됐지만 자동으로 이슈를 닫는 “Stale Issue Bot”과 씨름해야 했음

바로 전환하지 못한 이유

  • “X에서 Y로 전환”하는 작업은 개발 속도와 팀의 정신적 안정성을 해칠 수 있어, Val Town은 반드시 필요한 경우가 아니면 재작성하지 않으려 했음
  • Clerk는 Remix, Fastify, Express 등 Val Town이 쓰던 기술을 위한 SDK를 제공했고, 해당 프레임워크들의 변화도 꽤 잘 따라감
  • Clerk의 관리 기능과 남용 방지 기능은 고객 지원 문제를 해결하고 사기 사용자를 막는 데 도움이 됨
  • Clerk가 특히 잘 맞는 영역은 소셜 요소가 없고 사용자 테이블이 필요 없는 비교적 단순한 프런트엔드 중심 앱이었음
  • 시작하기 쉽고 가격도 감당 가능했으며, Clerk 대시보드도 꽤 좋았음
  • 인증 대안은 많지 않았고, 오픈소스 인증 솔루션 중에는 오래되고 사실상 방치된 것이 많았음
  • 인증 서비스형 플랫폼은 공급업체 리스크가 있고 Clerk와 같은 문제가 반복될 수 있었음
  • Val Town은 인증을 처음부터 직접 만들어 새롭고 민망한 취약점에 노출되고 싶지는 않았지만, 공급자에게 너무 많은 책임을 넘기고 싶지도 않았음
  • 특히 타사 세션 관리를 다시 신뢰하지 않겠다는 기준이 생김

Better Auth 선택과 전환 방식

  • Better Auth는 높은 코드 품질, 여러 프레임워크와의 좋은 통합, 독립적인 오픈소스 프로젝트로 실제 사용 가능하다는 점에서 많은 조건을 충족함
  • Better Auth도 대부분 한 회사가 개발하는 크고 복잡한 코드베이스이므로 공급업체 리스크는 남아 있음
  • 다만 세션과 사용자 인증이 동작하기 위해 제3자가 계속 온라인 상태여야 하는 의존성은 사라짐
  • WorkOSAuthKit도 강한 후보였고 매우 매끄러웠지만, 두 공급업체를 거친 뒤에는 독립적으로 동작하고 핵심이 오픈소스인 대안이 중요해짐
  • Better Auth의 대시보드와 유료 애드온도 Val Town의 요구에 맞았음
  • Val Town은 모든 데이터를 직접 관리하고, 플러그인이 Val Town 사이트에 API를 제공해 Better Auth 대시보드가 정보를 가져오고 가벼운 사용자 관리를 할 수 있게 함
  • Better Auth의 유료 서비스인 “Infrastructure”는 Val Town의 사용 방식에서는 사실상 상태 비저장에 가깝고 세션 관리에 관여하지 않음
  • 전환 기간에는 약 2주 동안 Better Auth와 Clerk를 동시에 지원함
  • 인증을 처리하는 모든 엔드포인트가 두 종류의 쿠키를 모두 받아들였고, 로그인 페이지가 Better Auth 세션을 제공하면서 사용자가 점진적으로 Better Auth로 이동함
  • 보안과 관련된 작업인 만큼 모든 코드를 꼼꼼히 읽고, 다시 쓰고, 테스트해야 했으며, 최종적인 순수 Better Auth 인증 코드는 전부 직접 작성함
  • Better Auth는 Vals와도 잘 맞으며, Val Town 코드에 인증을 추가하려면 Better Auth starter template을 사용할 수 있음

남은 교훈

  • 업스트림 제공자의 가동 시간이 서비스 가동 시간에 직접 영향을 주므로, 그 리스크에 얼마나 노출돼 있는지 신중히 판단해야 함
  • 어떤 제품이 많은 사용 사례에 잘 맞고 크게 성공했더라도, 특정 문제에는 맞지 않을 수 있음
  • 소프트웨어 환경은 빠르게 바뀌며, 필요한 순간에는 없던 적절한 해법이 1년 뒤에 나타날 수도 있음
Hacker News 의견들
  • 나보다 똑똑한 사람이 왜 Postgres users 테이블을 서드파티 제공자에게 넘겨야 하는지 설명해줬으면 함
    Hetzner VM에 있는 테이블을 직접 유지하는 게 뭐가 그렇게 어려운지 모르겠음. 결제도 아니고 그냥 몇 개 필드가 있는 데이터일 뿐임

    • 몇 개 필드일 때는 그렇지만, 곧 그렇게 단순하지 않게 됨
      SSO, SAML, SCIM, OIDC, OAuth, 2단계 인증, 비밀번호 없는 인증, 검증 토큰 등이 붙고, 각 기능마다 널리 쓰이는 시스템과의 변형 통합까지 요구됨. 우리 회사에서는 한동안 지원 엔지니어 시간의 절반이 직접 만든 인증 시스템의 온갖 SSO 문제 처리에 들어갔음
    • 나도 비슷하게 이해가 안 됨. Supabase 같은 게 왜 존재하는지도 늘 의문이었고, 프론트엔드 개발 세계가 기본적으로 단순하고 안전하게 만들 수 있는 방식에서 얼마나 떨어져 있는지 보여주는 듯함
    • 커리어를 아키텍트로 올리고 싶지 않나? 박스 하나 그리고 User Management라고 이름 붙인 뒤 Clerk 같은 SaaS를 붙이면 관리되는 것으로 가정할 수 있음
      그러면 “이건 내가 구현해도 가치가 없다”고 느끼는 요구사항은 전부 그 마법의 블랙박스에 밀어 넣을 수 있음
    • 사람들은 인증을 망쳐서 해킹당하는 것을 매우 두려워함. 그래서 그 책임을 서드파티에 넘기고 신경 쓰지 않으려는 경향이 있음
    • 나도 똑같이 혼란스러움. 대략 보기엔 요구사항이 넓지 않은 범위에서는 데이터베이스를 직접 운영하고 Django 같은 것으로 인증을 관리하는 편이 더 쉬움
      엔터프라이즈 규모에서는 달라질 수도 있겠음
  • Better Auth의 Bereket임. 나도 바로 이 문제를 해결하려고 Better Auth를 시작했고, 이후 회사가 됐음
    다른 사람들이 같은 가치를 얻는 걸 보는 게 늘 기쁨. 아직 할 일이 많아서, 무엇을 개선하면 좋을지 알고 싶음

    • Python 백엔드 지원 계획이 있는지 궁금함. 아니면 우리가 쓸 수 있는 방법이 있는지 알고 싶음
    • 브라우저에서 인증이 복잡한 이유가 브라우저가 충분히 해주지 않기 때문이라고 보나?
  • “복잡한 시스템을 만들며 배우는 어려운 교훈은, 그 신뢰성이 핵심 부품들의 신뢰성 중 최솟값이라는 것이다”보다 더 나쁨
    실제로는 핵심 경로에 있는 모든 구성요소의 가용성 곱이 전체 가용성이 됨. 소프트웨어, 인증 계층, 클라우드 제공자가 각각 99% 가용성이고 셋 중 하나만 죽어도 서비스가 내려간다면 최종 가용성은 97%뿐임. 그런 구성요소가 11개면 가용성에서 “나인”이 하나도 남지 않음. 그래서 구성요소를 줄이고 신뢰성 높은 해법을 택하는 게 중요하며, 이 팀이 그 길을 택해서 좋음

    • 지난번 큰 Cloudflare 장애 때 이걸 어렵게 배움. 나는 Cloudflare를 쓰지 않았는데도, JWT 검증에 쓰는 Auth0 공개 키가 Cloudflare 뒤에서 제공되고 있어서 인증 체인이 통째로 깨졌고 앱이 몇 시간 동안 먹통이 됐음
  • 예전에 나온 Supabase 마이그레이션 글(https://blog.val.town/blog/migrating-from-supabase)도 재미있게 읽었음
    장기적인 엔지니어링 결정에 대해 솔직하고 좋은 글이 부족한데, 계속 블로그를 써줬으면 함

  • 최근 비슷한 과정을 겪음. Stack Auth로 시작했지만 극단적으로 빡센 속도 제한과 나쁜 성능 때문에 프로덕션에서 쓸 수 없었고, 속도 제한에 걸리지 않아도 느렸음
    이후 WorkOS AuthKit으로 옮겼고 훨씬 잘 동작하며 유용한 엔터프라이즈 기능도 지원함. 그래도 새 프로젝트라면 Better Auth 쪽에 끌림. 외부 인증 제공자의 상태와 내 사용자 상태를 동기화하는 건 버그의 온상이고, 인증 제공자에 가능한 한 상태를 적게 두는 게 도움이 되지만 그래도 일부는 남음. JWT 접근 토큰을 몇 분마다 갱신하는 것도 또 다른 버그의 온상이며, 인증을 직접 제어한다면 솔직히 그럴 필요가 없음. WorkOS는 완전한 API가 아니고, 과금 계정당 제품 하나와 고정된 환경 수(staging, production, 지원에 요청하면 하나 더)라는 가정 위에 만들어져 있음. 리다이렉트 URL 같은 것도 대시보드에서 허용 목록에 넣어야 하고, 에이전트가 쉽게 처리할 방법은 없어 보임. 인증 외주화는 별로 말이 안 된다고 봄. 상태를 여러 서비스에 덜 쪼갤수록 문제가 줄어듦. 결제처럼 불가피하거나 성능 때문에 특수 데이터베이스가 필요한 경우도 있지만, 좋은 라이브러리가 있다면 인증에는 정말 그럴 이유가 없음. 서비스를 쓰면 더 빨리 시작할 수 있다는 주장도 있지만, 내가 인증 서비스에서 겪은 문제는 고규모와 관련이 없었고 대부분 출시 전부터 터졌음

  • Clerk를 쓰고 있는데 꽤 불만족스러움. 제대로 된 RBAC가 없음
    역할이 사용자 자체가 아니라 조직에 묶여 있어서 전역 관리자 같은 개념을 둘 수 없고, 임의 키-값 쌍을 metadata에 저장하는 식으로 우회해야 함. 지난 몇 주·몇 달 사이에도 다운타임이 여러 번 있었고, 그때마다 앱 전체가 실패했음. 앞으로 다시 쓸지는 두 번 생각할 듯함

  • 초기에 Lucia를 선택해서 정말 다행이라고 느낌. 라이브러리는 사실상 종료하고, 인증을 직접 관리하고 호스팅하는 방법을 문서와 작은 유틸리티로 대체했음
    인증은 늘 직접 관리할 수 없는 크고 무서운 일처럼 제시되지만, 보안과 기본적인 솔팅이 어떻게 동작하는지 일주일 정도 배워보니 전체 동작 방식에 훨씬 자신감이 생겼음

    • https://lucia-auth.com/
      라이브러리를 폐기하고 인증을 처음부터 구현하는 학습 자료로 바꿨던 때가 기억남. 훌륭한 결정이었고, 작성자를 매우 존중함
  • Clerk와 Better Auth 비교는 거의 불공정하다고도 할 수 있음. 하나는 서비스고 하나는 라이브러리라서 사과와 오렌지 비교임
    스택에 통합되는 모든 서드파티 서비스는 책임 부담이 되고, 라이브러리도 그렇지만 정도가 덜함. 이제 더 많은 서비스가 라이브러리로 대체될 때가 됐고, Better Auth가 그 방식을 잘 보여줌. 프론트엔드, 백엔드, 데이터베이스에 통합되는 라이브러리라서 좋음

  • Tom의 글은 항상 읽을 만함
    Auth0passportjs를 기억하는 사람이 있나? 인증 서비스의 변화는 끝이 없지만, 표준도 계속 변하니 어쩔 수 없는 듯함

    • OAuth 2.xOIDC는 크게 변하지 않았음. 나는 아직도 Firebase와 함께 Passport.js를 씀