ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Supabase][인증] signing key rotation 뒤 Edge Functions와 custom backend verifier를 같이 쓸 때 JWKS cache window를 어떤 순서로 따로 본다
    기타개발지식/풀스택개발 2026. 8. 17. 09:16

    IT 리서치 노트

    [Supabase][인증] signing key rotation 뒤 Edge Functions와 custom backend verifier를 같이 쓸 때 JWKS cache window를 어떤 순서로 따로 본다

    Supabase signing key rotation을 몇 번 운영하다 보면 rotate 자체보다 더 헷갈리는 구간이 남는다. 바로 Edge Functions와 custom backend verifier가 같은 JWT를 검증하는데도 회복 속도가 다를 때다. 2026년 8월 16일 기준 Supabase 공식 문서를 다시 보면 Edge Functions Verify JWT 잔존 설정은 rotation을 깨뜨릴 수 있고, JWKS endpoint는 Supabase Edge에서 10분 캐시되며, getClaims는 cached JWKS를 활용한 빠른 경로다. 이 글은 rotation 뒤 각 verifier의 JWKS cache window를 어떤 순서로 따로 봐야 일부 경로만 실패하는 상황을 짧게 자를 수 있는지 정리한다.

    1. 개요

    결론부터 말하면 Supabase signing key rotation 뒤에는 Edge Functions 설정층, getClaims 기반 앱 서버층, custom backend verifier층을 같은 회복 곡선으로 보지 않는 편이 맞다. Supabase가 제시하는 10분 Edge 캐시와 20분 대기 권장은 공통 기준선일 뿐, custom verifier의 내부 캐시까지 자동으로 정리해 주지는 않는다.

    그래서 일부 경로만 새 JWT를 거부하면 먼저 verifier별 마지막 성공 시각을 분리 기록해야 한다. rotate 완료 시각 하나만 적으면 왜 Edge Functions는 회복됐는데 custom backend만 실패하는지 설명이 안 된다.

    2. 어디서 실제로 막히는가

    실무에서 흔한 실패는 네 가지다. 첫째, Edge Functions Verify JWT 설정을 정리하지 않은 채 custom backend cache만 의심한다. 둘째, getClaims가 cached JWKS를 쓴다는 사실을 잊고 custom verifier와 같은 속도로 회복될 것이라 생각한다. 셋째, Supabase Edge 10분 캐시를 앱 내부 cache TTL과 같은 값으로 본다. 넷째, 정상 rotation 안정화와 긴급 revoke purge를 같은 runbook으로 적는다.

    Signing Keys 문서는 직접 JWT 검증 코드와 Edge Functions Verify JWT 잔존 설정이 회전을 깨뜨릴 수 있다고 경고한다. JWT guide는 JWKS endpoint가 Supabase Edge에서 10분 추가 캐시된다고 적고, standby key 생성이나 이전 key revoke 때 최소 20분 대기를 권장한다. getClaims reference는 cached JWKS endpoint를 써서 빠르다고 설명한다. 이 셋을 같이 읽으면 verifier별 cache 관찰 지점을 나누지 않으면 일부 경로 실패 원인을 설명할 수 없다는 결론이 나온다.

    • 증상: rotation 직후 Edge Functions는 정상인데 custom backend만 새 JWT를 거부한다.
    • 실패: Supabase Edge 10분 캐시와 앱 내부 JWKS cache를 같은 값으로 기록한다.
    • 막힘: getClaims 회복 시각과 custom verifier 회복 시각을 따로 적지 않는다.
    • 누락: Verify JWT 잔존 여부를 cache 문제와 분리하지 않는다.

    이미 긴급 revoke에서 purge와 session invalidation 순서 글을 다뤘다면, 이번 글은 그보다 앞단에서 정상 rotation 뒤 verifier별 안정화 창을 분리하는 이야기다.

    3. 실무에서 적용하는 순서

    가장 짧은 순서는 다섯 단계다. 첫째, rotation 시각과 access token TTL을 적는다. 둘째, Edge Functions Verify JWT 잔존 여부를 적는다. 셋째, getClaims 경로의 첫 정상 검증 시각을 기록한다. 넷째, custom verifier의 cache busting 위치와 첫 정상 검증 시각을 적는다. 다섯째, 둘 다 회복되기 전에는 revoke 판단을 미룬다.

    1. rotation 시각과 token TTL을 먼저 적는다.
    2. Edge Functions Verify JWT 잔존 여부를 확인한다.
    3. getClaims 경로의 첫 정상 시각을 적는다.
    4. custom verifier의 cache busting 지점과 첫 정상 시각을 적는다.
    5. 두 경로가 모두 회복되기 전에는 revoke를 미룬다.

    운영 메모에서는 verifier별로 확인, 기록, 비교, 저장, 재시도, 검토 항목을 따로 둬야 한다. Edge Functions 로그를 확인하고, getClaims 응답 회복 시각을 기록하고, custom verifier cache flush 시각을 저장하고, 세 값을 한 표에서 비교해야 한다. 이 절차를 분리하지 않으면 rotation 성공과 verifier 회복을 한 줄에 섞어 잘못 보고하게 된다.

    • rotation 완료 시각과 standby key 생성 시각을 기록한다.
    • Edge Functions 설정 화면과 함수 로그를 확인하고 메모를 업데이트한다.
    • getClaims 성공 응답 시각과 custom verifier 성공 시각을 비교한다.
    • cache busting, 프록시 purge, 재시도 결과를 분리 저장하고 검토한다.
    rotation_completed_at=2026-08-16T09:00:00Z
    token_ttl_minutes=60
    edge_verify_jwt_setting=disabled
    getclaims_recovered_at=2026-08-16T09:12:00Z
    custom_verifier_cache_bust_at=2026-08-16T09:15:00Z
    custom_verifier_recovered_at=2026-08-16T09:19:00Z
    revoke_decision=wait_until_all_verifiers_recovered

    이 순서를 쓰면 rotation 자체가 실패했는지, 아니면 특정 verifier만 stale cache를 더 오래 잡고 있는지 빠르게 갈린다. getClaims가 회복됐는데 custom verifier만 늦다면 Supabase 제품 경계보다 앱 내부 cache, 프록시 cache, 자체 RemoteJWKSet 설정을 먼저 봐야 한다.

    반대로 Edge Functions 쪽이 먼저 깨지면 cache 문제가 아니라 Verify JWT 설정이나 함수 코드 경계가 더 의심스럽다. 회전 뒤 장애를 모두 cache라고 부르면 실제 설정 오류를 늦게 찾게 된다.

    4. 공식 문서와 예시 화면으로 확인하기

    첫 공식 화면은 Signing Keys 문서의 회전 주의사항이다. Supabase는 직접 verifier나 Edge Functions Verify JWT 설정이 남아 있으면 rotation이 앱을 깨뜨릴 수 있다고 경고한다.

    Supabase는 직접 JWT 검증 코드나 Edge Functions Verify JWT 설정이 남아 있으면 rotation이 앱을 깨뜨릴 수 있다고 안내한다.
    Supabase는 직접 JWT 검증 코드나 Edge Functions Verify JWT 설정이 남아 있으면 rotation이 앱을 깨뜨릴 수 있다고 안내한다.

    즉 rotation 이후 첫 질문은 키가 바뀌었나가 아니라 어떤 경로가 아직 예전 검증 가정을 쓰고 있나이다. Edge Functions와 custom backend verifier를 같은 cache window로 묶으면 여기서 바로 엇갈린다.

    두 번째 자료는 JWT guide의 캐시 설명이다. Supabase는 JWKS endpoint가 Auth server에서 나오지만 Supabase Edge에서 10분 추가 캐시된다고 적고, standby key 생성이나 이전 key revoke 때 최소 20분 대기를 권장한다.

    Supabase JWT guide는 Edge 캐시 10분과 key 변경 시 최소 20분 대기 권장을 함께 설명한다.
    Supabase JWT guide는 Edge 캐시 10분과 key 변경 시 최소 20분 대기 권장을 함께 설명한다.

    이 숫자는 Edge 제품군과 custom verifier가 같은 속도로 새 키를 본다는 뜻이 아니다. 오히려 공통 기준선이 하나 있을 뿐, 앱 내부 캐시와 외부 verifier 캐시는 더 길게 남을 수 있다는 경고에 가깝다.

    세 번째 자료는 getClaims reference다. getClaims는 cached JWKS endpoint를 먼저 써서 빠르게 검증한다고 설명한다.

    getClaims는 cached JWKS endpoint를 활용하는 빠른 검증 경로라고 Supabase가 설명한다.
    getClaims는 cached JWKS endpoint를 활용하는 빠른 검증 경로라고 Supabase가 설명한다.

    그래서 getClaims 위주 서버와 createRemoteJWKSet 같은 custom verifier 서버는 같은 JWT를 검증하더라도 cache 관찰 지점이 다를 수 있다. 둘을 같은 타임라인에 뭉개면 회전 후 일부 경로만 실패하는 이유를 설명하기 어렵다.

    실무 triage는 verifier별 cache window를 구분하는 표부터 시작하는 편이 빠르다. Edge Functions, getClaims 경로, custom verifier는 같은 JWKS를 보더라도 관찰 지점과 cache flush 책임이 다르다.

    Edge Functions와 getClaims 경로와 custom verifier 경로를 cache window 기준으로 나눈 표다.
    Edge Functions와 getClaims 경로와 custom verifier 경로를 cache window 기준으로 나눈 표다.

    이미 Verify JWT와 getClaims 분기 글과 old JWT 유예와 revoke 시점 글을 정리했다면, 이번 표는 회전 뒤 각 verifier의 cache window를 별도 시간축으로 적는 후속편이다.

    마지막 자료는 rotation 이후 메모 예시다. verifier별로 마지막 성공 시각과 cache flush 관찰 지점을 나눠 적으면 '어느 경로만 아직 old key를 본다'는 질문이 짧아진다.

    rotation 뒤 verifier별 JWKS cache window를 기록할 때 남기면 좋은 최소 메모 예시다.
    rotation 뒤 verifier별 JWKS cache window를 기록할 때 남기면 좋은 최소 메모 예시다.

    긴급 revoke처럼 purge가 필요한 사건과, 정상 rotation 뒤 안정화 시간을 보는 사건을 이 메모 한 장으로 분리할 수 있다. 회전 완료 시각 하나만 적는 기록보다 훨씬 설명력이 높다.

    5. 주의사항과 리스크

    첫 번째 리스크는 Supabase가 안내하는 20분 대기를 모든 verifier의 회복 완료 시각으로 오해하는 것이다. 두 번째 리스크는 getClaims와 custom verifier의 회복 곡선을 따로 기록하지 않는 것이다. 세 번째 리스크는 정상 rotation 안정화와 긴급 revoke purge를 같은 메모에 섞는 것이다.

    • Supabase Edge cache와 앱 내부 cache는 같은 경계가 아니다.
    • Verify JWT 설정층과 JWKS cache 층을 분리한다.
    • revoke 판단은 verifier별 회복 기록 이후에만 내린다.

    6. 결론

    Supabase signing key rotation 뒤 일부 경로만 실패한다면, verifier별 JWKS cache window를 따로 적는 편이 가장 빠르다. Edge Functions 설정층, getClaims 경로, custom backend verifier 경로를 각각 적어야 rotation 완료와 개별 회복 시각을 구분할 수 있다.

    요약하면 회전 시각 하나보다 verifier별 첫 정상 시각이 더 중요하다. 그 기록이 있어야 정상 안정화와 비상 purge runbook을 섞지 않는다.

    같은 분기에서 실제 장애 triage까지 이어가려면 getClaims는 정상인데 custom verifier만 stale일 때 cache purge와 fallback 경로를 분리하는 follow-up 글을 함께 두는 편이 좋다. verifier별 cache window를 기록한 뒤에도 어느 경로가 stale인지 더 짧게 구분할 수 있다.

    그리고 rotation이 끝난 뒤 verify_jwt=false 함수와 signed-in 함수의 종료 기준 자체를 따로 문서화해야 하는 장면까지 이어가려면 새 signing key rotation 종료 기준 글을 같이 두는 편이 좋다. cache window와 함수 종료 기준을 분리해 적어야 회전 완료 보고가 덜 섞인다.

    7. 참고 링크

    1. https://supabase.com/docs/guides/auth/signing-keys
    2. https://supabase.com/docs/guides/auth/jwts
    3. https://supabase.com/docs/reference/javascript/auth-getclaims
    반응형