반응형

JWT 인증에서 Access Token 자동 갱신 구현 (Axios 기반)

JWT 기반 인증을 사용할 때 Access Token은 일반적으로 짧은 만료 시간을 가집니다. 이는 보안을 강화하기 위한 전략이지만, 토큰이 만료될 때마다 사용자가 다시 로그인해야 한다면 UX는 매우 나빠지겠죠. 이를 해결하기 위해 Refresh Token을 이용한 자동 갱신 방식이 널리 사용됩니다.

이 글에서는 프론트엔드에서 Access Token이 만료되었을 때, 자동으로 /auth/refresh 엔드포인트를 호출해 토큰을 갱신하고 요청을 재시도하는 구현 방법을 설명합니다.

✅ 사용 기술: Axios + JWT + HttpOnly 쿠키 기반 인증


🎯 구현 목표

  1. API 요청 도중 Access Token이 만료되면 자동으로 /auth/refresh 호출
  2. 새 Access Token을 발급받고, 기존 실패한 요청을 재시도
  3. Refresh Token은 HttpOnly 쿠키에 저장되어 자동 포함됨
  4. Refresh 실패 시 로그아웃 처리

🔧 Axios 인스턴스 생성 및 인터셉터 설정

import axios from 'axios';

const api = axios.create({
  baseURL: 'https://your-api.com',
  withCredentials: true, // 쿠키 포함 필수 설정
});

let isRefreshing = false;
let failedQueue: any[] = [];

const processQueue = (error: any, token: string | null = null) => {
  failedQueue.forEach(prom => {
    if (error) prom.reject(error);
    else prom.resolve(token);
  });
  failedQueue = [];
};

api.interceptors.response.use(
  res => res,
  async err => {
    const originalRequest = err.config;

    if (err.response?.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        }).then(() => api(originalRequest));
      }

      originalRequest._retry = true;
      isRefreshing = true;

      try {
        await api.post('/auth/refresh'); // Refresh Token은 쿠키에 자동 포함됨
        processQueue(null);
        return api(originalRequest); // 실패한 요청 재시도
      } catch (refreshError) {
        processQueue(refreshError, null);
        window.location.href = '/login'; // 리프레시 실패 시 로그아웃 처리
        return Promise.reject(refreshError);
      } finally {
        isRefreshing = false;
      }
    }

    return Promise.reject(err);
  }
);

export default api;

🔁 흐름 정리

  1. 유저가 API 요청을 보냄
  2. 서버가 Access Token 만료로 401 Unauthorized 응답
  3. Axios 인터셉터가 이를 감지하고 /auth/refresh 호출
  4. Refresh Token은 HttpOnly 쿠키에 자동 포함됨
  5. 새 Access Token이 발급되면 원래 요청을 재시도
  6. Refresh 실패 시 로그인 페이지로 이동

✅ 보안 고려 사항

항목설명

withCredentials: true 쿠키를 요청에 포함하려면 반드시 설정
HttpOnly 쿠키 JS에서 토큰 접근 불가 → XSS 방어
SameSite=Strict 또는 Lax CSRF 방어용 쿠키 설정
Refresh Token 저장 위치 반드시 쿠키 (localStorage 금지)
Refresh 실패 시 처리 로그아웃 처리 or 알림 후 로그인 페이지 이동

🧠 마무리

Axios 인터셉터를 활용하면 토큰 갱신 로직을 모든 요청에 일관되게 적용할 수 있어, 보안과 UX 모두를 만족시키는 인증 흐름을 만들 수 있습니다.

'컴퓨터 > JWT' 카테고리의 다른 글

쿠키(Cookie) 옵션 완벽 정리  (0) 2025.05.19
반응형

🔐 쿠키(Cookie) 옵션 완벽 정리: HttpOnly, Secure, SameSite의 모든 것

웹 개발에서 인증과 보안을 고민할 때 가장 먼저 마주치는 개념 중 하나가 바로 **쿠키(Cookie)**입니다. 하지만 쿠키 설정 시 등장하는 HttpOnly, Secure, SameSite 옵션이 정확히 뭘 의미하고, 어떤 보안 이슈를 막아주는지 확실하게 아는 사람은 많지 않습니다.

이 글에서는 실무에서 꼭 알아야 할 쿠키 옵션들의 기능, 보안 목적, 사용 예시를 정리해드릴게요.


🍪 쿠키란?

쿠키는 클라이언트(브라우저)에 저장되는 작은 데이터 조각입니다.

  • 서버가 Set-Cookie 헤더로 값을 내려주면,
  • 브라우저는 쿠키를 저장하고,
  • 이후 같은 도메인 요청마다 자동으로 쿠키를 전송합니다.

대표적인 활용 예:

  • 로그인 상태 유지 (세션 ID / JWT)
  • 장바구니 상태 저장
  • 사용자 설정 기억 (언어, 테마 등)

✅ 주요 쿠키 옵션 정리

옵션명설명방어하는 보안 위협
HttpOnly JS에서 쿠키 접근 불가 XSS (스크립트 탈취)
Secure HTTPS 연결에서만 전송 패킷 도청, MITM
SameSite 외부 요청 시 쿠키 전송 여부 제어 CSRF (요청 위조)
Path 특정 경로에만 쿠키 전송 제한된 범위 적용
Domain 서브도메인 공유 여부 도메인 스코프 설정
Max-Age / Expires 만료 시간 설정 자동 삭제
SameParty 제3자 쿠키 제한 회피 (실험적) Chrome Privacy Sandbox 대응
 

🔐 HttpOnly: JavaScript 접근 차단

Set-Cookie: token=abc123; HttpOnly
  • ✅ 쿠키를 JavaScript에서 document.cookie로 접근 불가
  • ✅ XSS 공격 시에도 쿠키를 훔칠 수 없음
  • ❌ JS로 토큰을 꺼내서 Authorization 헤더로 직접 보내야 하는 경우 사용 불가

💡 실무 팁: 인증 관련 쿠키(세션 ID, Access Token)는 반드시 HttpOnly 설정!


🔒 Secure: HTTPS에서만 전송

Set-Cookie: token=abc123; Secure
  • ✅ HTTPS 연결일 때만 서버로 쿠키 전송
  • ❌ HTTP 요청에는 전송되지 않음 (MITM 방지)
  • 📌 Secure이 없는 쿠키는 평문 HTTP 요청에 노출될 수 있음

💡 실무 팁: Secure 쿠키를 쓰려면 HTTPS 환경이 기본 전제입니다. 운영환경이라면 무조건 사용하세요.


🛡️ SameSite: CSRF 방어의 핵심

Set-Cookie: token=abc123; SameSite=Strict
값설명
Strict 다른 사이트에서 유입된 요청은 모두 쿠키 차단 (가장 안전)
Lax GET이나 a 링크, form 전송 등은 허용 / JS fetch 등은 차단
None 모든 외부 요청에 허용 (단, Secure 필수)
 

💡 실무 팁: 인증 관련 쿠키에는 보통 SameSite=Strict 또는 Lax를 설정합니다. None은 제3자 쿠키 용도로만 사용하세요.


📁 Path, Domain: 적용 범위 제어

Set-Cookie: theme=dark; Path=/settings
  • Path=/settings: /settings 이하에서만 전송
  • Domain=example.com: sub.example.com에서도 공유 가능

💡 실무 팁: 보안성 향상을 위해 불필요하게 넓은 범위는 피하세요.


⏰ Max-Age, Expires: 쿠키 수명

Set-Cookie: token=abc123; Max-Age=900
  • Max-Age=900: 900초(15분) 후 만료
  • Expires=Wed, 21 Oct 2025 07:28:00 GMT: 지정된 날짜/시간에 만료

설정이 없으면 세션 쿠키가 되어 브라우저 종료 시 삭제됩니다.


✅ 실무 예시: 로그인 쿠키 설정

Set-Cookie: access_token=eyJ...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=900
  • 🔐 JS 접근 불가 (HttpOnly)
  • 🔒 HTTPS 환경에서만 전송 (Secure)
  • 🛡️ CSRF 방지 (SameSite=Strict)
  • ⏰ 15분 후 자동 만료 (Max-Age)

🧠 마무리 요약

옵션설명권장 여부
HttpOnly JS 접근 차단 ✅ 항상 사용
Secure HTTPS에서만 전송 ✅ 운영환경 필수
SameSite 외부 요청 제한 ✅ CSRF 방어
Max-Age 유효 기간 설정 ✅ 필요시 사용
 

💬 마치며

쿠키는 단순한 저장소가 아니라, 보안 설정 하나로도 전체 서비스의 안정성을 좌우할 수 있는 민감한 요소입니다. 특히 인증과 세션 처리에 쿠키를 사용하는 경우에는 HttpOnly, Secure, SameSite는 사실상 필수 옵션이라고 생각하셔야 합니다.

보안은 구현보다 구성입니다.
조금만 신경 쓰면 더 안전한 서비스를 만들 수 있어요.

'컴퓨터 > JWT' 카테고리의 다른 글

JWT 인증에서 Access Token 자동 갱신 구현 (Axios 기반)  (0) 2025.05.19

+ Recent posts