ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Supabase][Auth] custom mailer에서 scanner 선열림이 의심될 때 ConfirmationURL 대신 Token 입력 복구 화면을 언제 먼저 둘까
    카테고리 없음 2026. 7. 14. 20:13

    IT 리서치 노트

    [Supabase][Auth] custom mailer에서 scanner 선열림이 의심될 때 ConfirmationURL 대신 Token 입력 복구 화면을 언제 먼저 둘까

    Supabase custom mailer invite 흐름에서 메일 링크를 눌렀는데 바로 invalid link나 otp_expired가 뜨면 재발송부터 넣기 쉽다. 하지만 2026년 7월 14일 기준 Supabase 공식 문서를 다시 보면 email prefetching이 잦은 환경에서는 ConfirmationURL을 그대로 수락시키기보다 Token 입력형 복구 화면을 두는 편이 낫다고 안내한다. 이 글은 scanner 선열림이 의심될 때 클릭형 링크를 유지할지, Token 입력 fallback을 먼저 열지 판단하는 기준을 정리한 것이다.

    1. 개요

    결론부터 말하면 발송 직후 verify 실패가 먼저 찍히는 패턴이면 재발송보다 Token 입력형 복구 화면을 먼저 검토한다. scanner가 ConfirmationURL을 먼저 소모한 상황에서는 링크를 다시 열게 하는 것보다 사용자의 실제 입력 행위를 검증 기준으로 다시 세우는 편이 더 안정적이다.

    반대로 실패가 늦게 발생하거나 재발송 뒤 구링크를 다시 눌렀다면 Token 입력 화면보다 새 링크 유효 범위를 더 분명하게 안내하는 쪽이 먼저다. 즉 fallback 화면은 모든 실패를 받는 만능 경로가 아니라, prefetch 패턴이 잡혔을 때 여는 특수 경로다.

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

    운영에서 가장 자주 섞이는 것은 세 종류의 실패다. 첫째는 메일 보안 스캐너가 먼저 링크를 열어 사용자의 첫 클릭 전에 토큰이 소모되는 경우다. 둘째는 사용자가 오래 뒤에 눌러 실제로 만료되는 경우다. 셋째는 재발송 뒤 새 링크 대신 기존 탭이나 기존 메일을 다시 눌러 구링크를 재사용하는 경우다.

    이 세 상황은 겉으로 보면 모두 invalid link, email link expired, otp_expired처럼 보일 수 있다. 그런데 대응은 완전히 다르다. scanner 선열림은 클릭형 링크 자체를 잠시 접고 입력형 fallback을 열어야 하고, 실제 만료는 재발송과 만료 시간 안내가 먼저이며, 구링크 재사용은 새 링크만 유효하다는 메시지와 탭 상태 정리가 핵심이다.

    문제는 많은 팀이 action_link만 저장하고 verify 실패 이벤트를 발송 성공 이벤트와 분리하지 않는다는 점이다. 그러면 첫 실패가 발송 3초 뒤였는지, 43분 뒤였는지조차 남지 않는다. scanner 선열림을 복구 UX 문제로 풀어야 하는지, 단순 만료 문제로 풀어야 하는지 판단 근거가 사라진다.

    • 증상: 발송 직후 첫 verify 실패가 나온다.
    • 실패: click link 경로와 token 입력 경로를 같은 수락 UX로 뭉갠다.
    • 막힘: 재발송을 먼저 넣었다가 scanner가 또 먼저 열어 버린다.
    • 누락: failure 시각, redirect_to, verification_type을 같은 trace에 남기지 않는다.
    실패 모습 먼저 볼 로그 해석
    발송 10초 내 첫 실패 발송 시각과 verify 실패 시각 scanner 선열림 가능성이 높다
    오래 뒤 첫 실패 만료 창과 사용자 클릭 시각 실제 만료 가능성이 높다
    재발송 뒤에도 동일 실패 resend_count와 current link id 구링크 재사용이나 동일 fallback 반복을 본다

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

    운영 순서는 다섯 단계가 가장 실용적이다. 먼저 발송 성공 이벤트와 verify 실패 이벤트를 분리한다. 두 번째로 failure 시각이 발송 직후인지 아닌지 본다. 세 번째로 직후 실패면 Token 입력 fallback 화면으로 보낸다. 네 번째로 그 화면에서 email과 token을 받아 verifyOtp를 호출한다. 마지막으로 fallback 경로로도 실패하면 새 링크 재발송 여부와 구링크 재사용 여부를 다시 자른다.

    1. 발송 성공과 verify 실패를 다른 이벤트 이름으로 남긴다.
    2. 첫 실패 시각이 발송 직후인지 먼저 본다.
    3. 직후 실패면 Token 입력 fallback으로 보낸다.
    4. fallback 화면에서 verifyOtp를 직접 호출한다.
    5. 그래도 실패하면 재발송과 구링크 재사용을 다시 분리한다.
    1. 메일 발송 시각을 기록한다.
    2. verify 실패 시각을 기록한다.
    3. 발송 직후 실패면 Token 입력 화면을 연다.
    4. email, token, type 값을 입력받아 verifyOtp를 실행한다.
    빠르게 적용하는 기준

    메일 보안이 강한 B2B 고객이나 조직 메일 환경이라면 클릭형 링크를 기본으로 두되, 발송 직후 첫 실패가 잡히면 곧바로 Token 입력 fallback 버튼을 보여 주는 편이 좋다. 반대로 일반 소비자 메일 환경에서 직후 실패 패턴이 거의 없다면 링크형 UX를 유지하고 만료 안내와 재발송 UI를 먼저 다듬는 쪽이 낫다.

    이때 복구 화면은 새 링크 발급 화면과 구분해야 한다. 사용자가 지금 가진 메일 안에서 다시 살릴 수 있는 경로가 Token 입력 fallback이고, 현재 메일 자체를 더 이상 못 믿겠다면 그때 재발송으로 넘어간다.

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

    첫 자료는 Supabase 이메일 템플릿 가이드의 email prefetching 구간이다. 여기서는 조직 메일 보안 스캐너가 ConfirmationURL을 사용자가 누르기 전에 먼저 열 수 있다고 설명한다. 즉 링크를 눌렀는데 곧바로 invalid나 expired가 뜨는 현상은 사용자 실수보다 메일 인프라 특성일 수 있다.

    Supabase는 이메일 보안 스캐너가 ConfirmationURL을 먼저 열어 링크를 소모할 수 있다고 설명한다.
    Supabase는 이메일 보안 스캐너가 ConfirmationURL을 먼저 열어 링크를 소모할 수 있다고 설명한다.

    이 설명은 custom mailer 운영 기준을 바꾼다. 클릭형 magic link만 믿지 말고, 실제 사용자가 다시 진입할 수 있는 복구 UX를 별도로 준비해야 한다.

    두 번째 자료는 같은 문서의 Option 1 구간이다. Supabase는 ConfirmationURL 대신 Token 값을 메일에 넣고, 사용자를 앱의 입력 화면으로 보내 직접 verifyOtp를 호출하는 복구 경로를 제안한다. scanner 선열림이 잦은 환경이라면 이 경로가 가장 먼저 검토할 fallback이 된다.

    Supabase는 링크 선소비가 잦으면 Token 입력형 복구 화면을 별도 페이지로 두는 방식을 안내한다.
    Supabase는 링크 선소비가 잦으면 Token 입력형 복구 화면을 별도 페이지로 두는 방식을 안내한다.

    핵심은 링크를 바로 수락하는 대신, 사용자 화면에서 email과 token을 다시 조합해 검증하는 것이다. 이렇게 하면 메일 본문 링크가 먼저 열려도 사용자의 실제 입력 행위를 수락 기준으로 다시 세울 수 있다.

    세 번째 자료는 troubleshooting 문서의 root cause 구간이다. 이 문서는 발송 직후 연속으로 403과 otp_expired가 찍히면 email prefetching을 먼저 의심하라고 적는다. 이 타이밍 정보가 token 입력 fallback 전환 기준이 된다.

    Supabase troubleshooting 문서는 발송 직후 verify 실패가 반복되면 email prefetching을 먼저 의심하라고 안내한다.
    Supabase troubleshooting 문서는 발송 직후 verify 실패가 반복되면 email prefetching을 먼저 의심하라고 안내한다.

    즉 token 입력형 복구 화면은 모든 사용자에게 기본으로 보여 줄 화면이 아니라, 발송 직후 verify 실패 패턴이 잡혔을 때 먼저 여는 대응 경로에 가깝다. 로그가 없으면 이 전환 시점을 정할 수 없다.

    실무에서는 클릭형 흐름과 token 입력형 흐름을 언제 바꿀지 표로 고정해 두는 편이 좋다. 발송 후 몇 초 만에 실패가 났는지, 사용자가 메일을 실제로 열었는지, 재발송이 이미 한 번 있었는지를 같이 보면 support 응답이 짧아진다.

    scanner 선열림, 단순 만료, 구링크 재사용을 분리하는 fallback 전환표다.
    scanner 선열림, 단순 만료, 구링크 재사용을 분리하는 fallback 전환표다.

    이미 scanner 선소비와 재발송 기준 글이 만료와 재발송을 갈랐다면, 이번 표는 그다음 단계인 사용자 복구 UX 선택판이다.

    마지막 자료는 입력형 복구 화면에서 verifyOtp를 호출하는 안전한 예시다. 중요한 점은 메일 링크를 그대로 다시 열게 하지 않고, 사용자가 email과 token을 입력하거나 붙여 넣은 뒤 검증을 수행하는 것이다.

    Token 입력형 fallback은 verifyOtp 호출과 실패 로그 분리를 함께 설계해야 안정적이다.
    Token 입력형 fallback은 verifyOtp 호출과 실패 로그 분리를 함께 설계해야 안정적이다.

    이 구조를 잡아 두면 custom mailer 필드 저장 글의 redirect_to와 verification_type을 그대로 복구 화면 분기에도 재사용할 수 있다.

    5. 주의사항과 리스크

    Token 입력 fallback을 너무 빨리 기본 경로로 바꾸면 일반 사용자 UX가 불필요하게 길어진다. 사용자가 이메일에서 링크 하나만 눌러 끝날 수 있는 상황까지 모두 입력형으로 돌리면 성공률이 오히려 떨어질 수 있다.

    반대로 scanner 선열림이 반복되는데도 모든 실패에 재발송만 붙이면 실패 루프가 길어진다. 링크를 한 번 더 보내도 스캐너가 먼저 열면 동일한 문제가 다시 생긴다. 따라서 fallback 전환은 감으로 하지 말고 발송 직후 실패 패턴, 고객 메일 환경, 재발송 반복 여부로 판단해야 한다.

    • 주의: fallback 화면이 곧 재발송 화면은 아니다.
    • 주의: verifyOtp 타입을 invite로 고정하지 않으면 다른 flow와 섞일 수 있다.
    • 주의: redirect_to와 verification_type을 함께 저장하지 않으면 화면 복구가 다시 꼬인다.

    6. 결론

    Supabase custom mailer에서 scanner 선열림이 의심될 때는 재발송부터 넣기보다 사용자의 실제 입력 행위를 기준으로 다시 verify하는 Token 입력 fallback이 더 빠를 수 있다. 핵심은 failure 타이밍과 verify 경로를 로그로 남겨, 클릭형 링크를 유지할지 복구 화면으로 전환할지 운영 기준을 분명히 세우는 것이다.

    다음 단계가 필요하다면 scanner 선소비와 재발송 기준 글, custom mailer 필드 저장 글을 함께 묶어 보면 복구 UX와 발송 로그 기준이 더 선명해진다.

    7. 참고 링크

    1. https://supabase.com/docs/guides/auth/auth-email-templates
    2. https://supabase.com/docs/guides/troubleshooting/otp-verification-failures-token-has-expired-or-otp_expired-errors-5ee4d0
    3. https://supabase.com/docs/guides/auth/auth-email-passwordless
    4. https://supabase.com/docs/guides/auth/redirect-urls
    5. https://supabase.com/docs/reference/javascript/auth-verifyotp
Designed by Tistory.