개인과제

JWT(JSON Web Token) 기술 분석

choijming21 2025. 1. 17. 21:03
// 저장
sessionStorage.setItem('token', accessToken);
// 조회
sessionStorage.getItem('token');

인증 방식의 종류에는 '세션/쿠키 방식''JWT(JSON Web Token)' 방식이 있습니다.

 

 

세션/쿠키 방식: 서버가 세션 정보를 보관하고 관리(서버 부하)

  1. 사용자 로그인
  2. 서버가 세션 생성 및 세션 ID 발급
  3. 세션 ID를 쿠키에 저장해서 클라이언트에 요청마다 쿠키 전달

 

JWT(JSON Web Token)방식: 서버가 상태를 저장하지 않음(Stateless)

  1. 사용자 로그인
  2. 서버가 JWT 토큰 발급(토큰 자체에 필요한 정보가 담겨 있음)
  3. 클라이언트가 토큰 저장
  4. 서버는 토큰이 유효한지만 확인

 

 

 

 

 

 

Q. 쿠키, 세션, 토큰은 각각 무엇을 말하는 것인가요?

  • 쿠키
    • 브라우저에 저장되는 작은 데이터 조각
    • 서버가 클라이언트에 보내는 key-value 데이터
    • 모든 HTTP 요청에 자동으로 포함됨
  • 세션
    • 서버에서 유저의 정보를 저장하고 관리
    • 클라이언트는 세션ID만 가지고 있음
    • 서버 메모리를 사용하므로 서버에 부담
  • 토큰
    • 정보를 암호화하여 담은 문자열
    • 서버가 상태를 저장할 필요 없음
    • 클라이언트가 직접 관리

 

 

 

 

 

 

 

Q. Access token과 Refresh token은 왜 존재하나요?

 

Access Token: 메모리(Zustand, Context) 저장 권장

  • 실제 리소스에 접근할 때 사용하는 토큰
  • 짧은 유효기간(보통 30분 ~ 2시간)
  • 탈취 위험을 줄이기 위해 짧게 유지

 

Refresh Token: HttpOnly 쿠키 저장 권장

  • Access Token을 재발급 받기 위한 토큰
  • 긴 유효기간(보통 2주 ~ 1달)
  • Access Token이 만료되었을 때 새로 로그인하지 않고도 갱신 가능

 

 

 

 

 

 

 

Q. 각 token은 어디에 저장해야 안전한가요?

 

1. localStorage 

// 저장
localStorage.setItem('token', accessToken);
// 사용
const token = localStorage.getItem('token');

 

특징:

  • 브라우저를 닫아도 데이터 유지
  • 명시적으로 삭제하기 전까지 영구 보존
  • 도메인별로 약 5~10MB 저장 가능
  • 다른 탭에서도 데이터 공유

 

 

1-1. sessionStorage

// 저장
sessionStorage.setItem('token', accessToken);
// 조회
sessionStorage.getItem('token');

 

특징:

  • 브라우저/탭을 닫으면 데이터 삭제
  • 같은 도메인이라도 다른 탭과 데이터 공유 안됨
  • 페이지 새로고침해도 데이터 유지
  • 도메인별로 약 5~10MB 저장 가능

 

Storage 선택 기준:

  • localStorage: 장기간 보관이 필요한 데이터 (사용자 설정, 테마 등)
  • sessionStorage: 임시 데이터나 민감한 정보 (일회성 인증 코드 등)

 

 

 

2. Zustand

const useAuthStore = create((set) => ({
  token: null,
  setToken: (token) => set({ token }),
}));
  • 장점: XSS에 비교적 안전
  • 단점: 새로 고침시 초기화

 

 

 

3. Tanstack query

const useAuth = () => {
  const { data: token } = useQuery(['auth'], () => null);
  const setToken = (newToken) => 
    queryClient.setQueryData(['auth'], newToken);
};
  • 장점: 캐싱 시스템 활용
  • 단점: 새로 고침시 초기화, 과도한 설정

 

 

 

4. HttpOnly 쿠키

Set-Cookie: token=xxx; HttpOnly; Secure
  • 장점: 가장 안전(JS 접근 불가)
  • 단점: CSRF 공격 가능성

 

4-1. HttpOnly, Secure 옵션의 의미

 

A. HttpOnly

  • JavaScript로 쿠키 접근 불가능
  • document.cookie로 읽기 불가
  • XSS 공격 방지

B. Secure

  • HTTPS 프로토콜에서만 쿠키 전송
  • 암호화된 통신만 허용
  • 네트워크 상의 토큰 탈취 방지

 

 

 

 

 

 

지금 제 프로젝트로 보았을 때, Zustand로 토큰을 관리하는게 적절해보입니다.

크게 4가지 이유가 있습니다.

 

 

1. 과제의 API 스펙과 매칭

// 로그인 API 응답 형태
{
  "accessToken": "eyJhbGci...",  // JWT 토큰
  "userId": "유저 아이디",
  "success": true,
  "avatar": "프로필 이미지",
  "nickname": "유저 닉네임"
}
  • 서버가 토큰을 response body로 전달
  • HttpOnly 쿠키 설정을 지원하지 않음
  • 따라서 클라이언트에서 직접 토큰 관리가 필요함

 

2. 요구사항과 적합성

// Zustand store 예시
const useAuthStore = create((set) => ({
  token: null,
  user: null,
  setAuth: (token, user) => set({ token, user }),
  logout: () => set({ token: null, user: null })
}));
  • 과제에서 요구하는 zustand 상태관리 실습 가능
  • 권한별 라우팅 제어를 위한 전역 상태 관리 용이
  • 다른 컴포넌트에서도 쉽게 접근 가능

 

3. 구현의 편의성

// API 호출시 토큰 사용 예시
const { token } = useAuthStore();
const response = await axios.get('/user', {
  headers: { Authorization: `Bearer ${token}` }
});
  • 간단한 코드로 구현 가능
  • Tanstack query와 함께 사용하기 좋음
  • 상태 업데이트가 간편함
  • 작은 규모의 프로젝트에 적합한 복잡도
  • 빠른 개발 가능