본문 바로가기

웰로 · Wello·Wello-biz Admin · 2026.03

토큰이 만료돼도 갱신은 한 번만

Next.js·Vue 통합 어드민 토큰 자동 갱신

Next.js 어드민과 Vue 어드민의 토큰 만료 대응과 로그인 쿠키 분리를 구현했습니다.

문제
탭을 2개 열고 작업하면 한쪽이 로그아웃된다는 내부 구성원의 요청이 있었습니다. 토큰은 만료돼도 자동 갱신되지 않았고, Next.js 어드민은 탭마다 토큰을 따로 들고 있어 다른 탭이 옛 토큰으로 요청했으며, 웰로·웰로비즈 어드민은 같은 이름의 쿠키가 서로 덮어써졌습니다.
결정
요청이 거절(401)되면 토큰을 갱신해 다시 보내도록 Next.js·Vue 어드민에 구현했습니다. 갱신용 토큰은 한 번 쓰면 무효가 돼 동시에 거절된 요청이 각자 갱신하면 첫 요청만 성공하고 나머지는 로그아웃되므로, 갱신은 한 번만 하고 나머지는 그 결과를 기다리게 했습니다. Next.js 어드민은 쿠키의 토큰이 요청과 다르면 다른 탭이 갱신한 것으로 보고 그 토큰으로 재시도하며, 쿠키는 접속 도메인별로 분리했습니다.
결과
탭 로그아웃과 쿠키 덮어쓰기가 해소돼 웰로·웰로비즈 어드민 모두에 적용했고, 이후 같은 요청은 없었습니다.

결과 근거: 이력서 기재 내용. 이 페이지에서 측정한 값이 아닙니다.

구조

토큰이 만료돼도 갱신은 한 번만
동시 API 요청…동시 API 요청: 대기401 복구 (갱신 후 재시도)✓401 복구 (갱신 후 재시도): 확정진행 중인 refresh 공유진행 중인 refresh 공유: 사용 안 함쿠키 토큰 비교쿠키 토큰 비교: 사용 안 함refresh APIrefresh API: 사용 안 함직접 다시 로그인직접 다시 로그인: 사용 안 함

  • 동시 API 요청 · 대기
  • 401 복구 (갱신 후 재시도) · 확정
전·후 비교

401 복구. 401 응답을 받으면 복구 로직이 갱신 후 재시도 절차를 시작합니다.

범례
  • 임시·화면 계산
  • 확정
  • 문제 발생
  • 대기
  • 복구

어드민은 로그인이 필요해 공개 캡처가 없어 흐름을 다시 그린 도식입니다. 실제 화면이 아닙니다.

판단

  • 동시에 401을 받은 요청이 토큰 갱신을 어떻게 나눠 쓸 것인가

    진행 중인 refresh Promise를 공유해 첫 요청만 갱신

    첫 요청만 refresh를 호출하고 나머지는 같은 결과를 기다립니다.

    선택하지 않음 · 요청마다 각자 refresh 호출 — 갱신용 토큰은 한 번 쓰면 무효가 되어, 동시에 거절된 요청이 각자 갱신하면 첫 요청만 성공하고 나머지는 만료로 처리돼 로그아웃됩니다.

  • 다른 탭·프레임이 먼저 갱신한 경우를 어떻게 다룰 것인가

    실패한 요청의 토큰과 쿠키 토큰을 비교

    쿠키 토큰이 다르면 다른 앱이 이미 갱신한 것으로 보고 refresh 없이 쿠키의 토큰으로 재시도합니다.

    선택하지 않음 · 항상 refresh부터 호출 — 갱신용 토큰은 한 번 쓰면 무효가 되므로, 다른 탭이 이미 갱신했다면 같은 토큰으로 또 갱신하는 것은 실패합니다.

  • 웰로·웰로비즈 어드민의 로그인 쿠키를 어떻게 나눌 것인가

    접속 도메인별로 쿠키 범위를 분리

    쿠키는 접속 도메인별로 분리하고, 상위 도메인에 남은 기존 쿠키는 옮기고 지워 두 어드민의 로그인이 서로 덮어쓰지 않게 했습니다.

    선택하지 않음 · 상위 도메인에 같은 이름으로 공유 — 웰로·웰로비즈 어드민을 각각 로그인해 함께 켜면 같은 이름의 쿠키가 서로의 로그인 정보를 덮어썼습니다.

문제와 해결

  1. 문제

    logout 요청이 401을 받으면 갱신 → 재시도 → 다시 401이 반복될 수 있습니다.

    해결

    logout 요청은 복구 대상에서 빼 무한 반복을 막았습니다.

이력서 원문

토큰이 만료돼도 갱신되지 않던 Next.js·Vue 어드민에 401 → 갱신 → 재시도를 구현하고, 웰로·웰로비즈 어드민의 쿠키를 접속 도메인별로 분리해 서로의 로그인 정보를 덮어쓰지 않게 했습니다.

  1. 문제

    탭을 2개 열고 작업하면 한쪽이 로그아웃된다는 내부 구성원의 요청이 있었습니다. 토큰은 만료돼도 자동 갱신되지 않았고, Next.js 어드민은 탭마다 토큰을 따로 들고 있어 다른 탭이 옛 토큰으로 요청했으며, 웰로·웰로비즈 어드민은 같은 이름의 쿠키가 서로 덮어써졌습니다.

  2. 기여

    요청이 거절(401)되면 토큰을 갱신해 다시 보내도록 Next.js·Vue 어드민에 구현했습니다. 갱신용 토큰은 한 번 쓰면 무효가 돼 동시에 거절된 요청이 각자 갱신하면 첫 요청만 성공하고 나머지는 로그아웃되므로, 갱신은 한 번만 하고 나머지는 그 결과를 기다리게 했습니다. Next.js 어드민은 쿠키의 토큰이 요청과 다르면 다른 탭이 갱신한 것으로 보고 그 토큰으로 재시도하며, 쿠키는 접속 도메인별로 분리했습니다.

  3. 결과

    탭 로그아웃과 쿠키 덮어쓰기가 해소돼 웰로·웰로비즈 어드민 모두에 적용했고, 이후 같은 요청은 없었습니다.