본문 바로가기
웹/웹 지식

[웹 지식] 액세스 토큰 + 리프레시 토큰 협동 과정

by 클레어몬트 2025. 4. 3.

https://claremont.tistory.com/entry/%EC%9B%B9-%EC%A7%80%EC%8B%9D-%ED%86%A0%ED%81%B0token-vs-API-%ED%82%A4

 

[웹 지식] 토큰(token) vs API 키

토큰하면 어떤 것이 먼저 떠오르는가? 필자는 유희왕의 토큰 카드가 가장 먼저 떠오른다..ㅋㅋ실제로 토큰의 쓰임새는 크게 다르지 않다ㅎ 오늘은 토큰에 대해 알아보는 시간을 갖고, API 키와

claremont.tistory.com

 

 

이전의 포스팅에서 API 키 vs 토큰에 대해서 다뤄보았다

오늘은 토큰에서 액세스 토큰과 리프레시 토큰을 같이 사용하는 이유와, 그 협동 과정에 대해 설명하려 한다!

토큰~

 

현대 웹 서비스에서 로그인 기능은 단순한 사용자 인증을 넘어서, 보안편의성을 동시에 만족시켜야 한다. 이러한 요구를 충족하기 위해 많이 사용하는 방식이 바로 JWT(JSON Web Token) 기반의 인증 시스템이다. 이 시스템에서는 두 가지 주요 토큰, 즉 액세스 토큰(Access Token)리프레시 토큰(Refresh Token)을 활용한다!

 

1. 액세스 토큰: 짧은 유효기간 (15분-1시간)

액세스 토큰은 로그인 인증이 성공했을 때 발급되는 토큰으로, 사용자가 로그인된 상태에서 API를 호출할 수 있게 해주는 권한 증표이다

  • 역할: 사용자 인증 정보(주로 user id, role 등)를 담고 있으며, 백엔드 서버는 이 토큰을 검증함으로써 요청자의 신원을 확인한다

※ 유효기간이 짧은 이유: 유출되더라도 피해를 최소화하기 위해서

// 예시: 액세스 토큰 페이로드
{
  "sub": "1234567890",
  "name": "홍길동",
  "role": "user",
  "exp": 1712131532
}

 

 

그런데, 매번 로그인하는 것은 사용자에게 불편하므로 사용자 경험을 심하게 떨어뜨린다

따라서 같이 사용하는 것이 리프레시 토큰~~

2. 리프레시 토큰: 긴 유효시간 (7일)

리프레시 토큰은 만료된 액세스 토큰을 갱신하는 데 사용된다. 사용자는 로그인 이후 별도로 다시 로그인하지 않아도 자동으로 새로운 액세스 토큰을 발급받을 수 있다!

  • 역할: 새로운 액세스 토큰을 재발급받기 위한 인증 수단

+ 보안 고려사항: 서버 or DB에 저장하거나, HttpOnly 쿠키로 클라이언트에 저장하여 노출을 최소화해야 한다

※ 유효기간이 긴 이유: 사용자 경험을 해치지 않기 위해서

 

[액세스 토큰 + 리프레시 토큰 정리표]

 

이 둘을 함께 사용하면 다음과 같은 구조를 구현할 수가 있다

  1. 사용자가 로그인하면 두 개의 토큰을 한 번에 발급한다.
  2. 클라이언트는 액세스 토큰을 활용하여 API 요청을 한다.
  3. 액세스 토큰이 만료되면, 클라이언트는 리프레시 토큰을 백엔드로 보내 새로운 액세스 토큰을 요청한다.
  4. 리프레시 토큰도 만료되었거나 위조된 경우, 로그아웃 처리를 유도한다.

 

 

그렇다면 실서비스에서는 어떻게 활용하나?

  • 액세스 토큰은 로컬 스토리지보다 HttpOnly 쿠키에 저장하는 것이 보안상 안전하다
  • 리프레시 토큰은 서버 DB에 저장하고, 토큰 일치 여부를 서버에서 확인하는 방식으로 보안을 강화할 수 있다
  • 토큰 재발급 시 기존 리프레시 토큰을 무효화하고 새로 발급하는 방식(로테이션 방식)을 적용하면 탈취 위험을 줄일 수 있다

 

토큰 흐름 예시

[로그인 성공]
 └─> 액세스 토큰 & 리프레시 토큰 발급
       └─ 액세스 토큰 → 클라이언트 저장
       └─ 리프레시 토큰 → 서버 저장 or HttpOnly 쿠키

[API 요청]
 └─> 액세스 토큰 검증
       └─ 유효 → 정상 처리
       └─ 만료 → 리프레시 토큰으로 갱신 요청

[리프레시 요청]
 └─> 서버에서 리프레시 토큰 검증
       └─ 유효 → 새로운 액세스 토큰 발급
       └─ 무효 → 재로그인 요청

 

 

POST /api/v1/auth/login
{
  "access_token": "짧은_수명",
  "refresh_token": "긴_수명"
}

 

  • access_token: 서버에 API 요청 보낼 때 Authorization 헤더에 포함
  • refresh_token: 클라이언트(프론트엔드 or 앱) 내부의 안전한 저장소에 보관

 

 

 

if) access_token이 만료되었을 때

사용자는 다시 로그인하지 않고 다음 API를 호출한다!

POST /api/v1/auth/refresh
{
  "refresh_token": "저장된_refresh_token"
}

 

그러면 서버는 다음을 수행:

  1. refresh_token 유효성 검사 (DBRedis에서 확인 or JWT 자체 검증)
  2. 유효하다면, 새로운 access_token을 발급해서 응답
  3. (선택) 기존 refresh_token도 갱신해줄 수 있음

 

 

여기서 access_token을 교체 후

클라이언트는 새 access_token을 Authorization 헤더에 넣고 요청을 재시도한다

 

(http)

Authorization: Bearer 새 access_token

 

 

 

 

사용된 리프레시 토큰은 DB에 저장해 블랙리스트로 처리해버린다(재사용 방지)

 

 

 

 

 

 

개인적인 내 생각으로는 리프레시 토큰의 관리가 소홀해질 경우 심각한 보안 사고로 이어질 수 있으므로 반드시 서버 저장, 쿠키 설정, 만료 처리 등의 비즈니스 로직을 잘 짜고 보안 가이드라인을 철저히 지켜야 한다..!