[React] jwt-decode로 JWT Payload 읽기
포스트
취소

[React] jwt-decode로 JWT Payload 읽기

들어가며

로그인 후 서버에서 access token을 받으면, 그 안에 사용자 id나 권한 같은 기본 정보가 들어 있는 경우가 있습니다.

이 정보를 화면에 바로 보여주고 싶을 때 매번 사용자 정보 API를 다시 호출하는 대신, JWT의 payload를 읽어 활용할 수 있습니다.

React에서는 jwt-decode 라이브러리를 사용하면 JWT payload를 간단히 읽을 수 있습니다.


JWT 구조 이해하기

JWT는 보통 세 부분으로 나뉩니다.

Header.Payload.Signature

가운데에 있는 Payload에는 사용자 id, 권한, 만료 시간 같은 정보가 들어갈 수 있습니다.

1
2
3
4
5
6
{
  "sub": "user-1",
  "nickname": "taewok",
  "role": "USER",
  "exp": 1712061029
}

여기서 꼭 기억해야 할 점이 있습니다.

JWT decode는 복호화가 아닙니다. Base64로 인코딩된 값을 읽기 쉬운 형태로 바꾸는 것에 가깝습니다.

그래서 비밀번호나 주민등록번호 같은 민감한 정보는 절대 JWT payload에 넣으면 안 됩니다.


jwt-decode 설치하기

1
npm install jwt-decode

설치 후 import해서 사용할 수 있습니다.

1
import { jwtDecode } from "jwt-decode";

기본 사용법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { jwtDecode } from "jwt-decode";

interface TokenPayload {
  sub: string;
  nickname: string;
  role: "USER" | "ADMIN";
  exp: number;
}

const token = localStorage.getItem("accessToken");

if (token) {
  const decoded = jwtDecode<TokenPayload>(token);

  console.log(decoded.nickname);
  console.log(decoded.role);
}

TypeScript를 사용한다면 payload 타입을 직접 정의해두는 것이 좋습니다.

이렇게 하면 decoded.nickname, decoded.role처럼 값을 사용할 때 타입 도움을 받을 수 있습니다.


로그인 응답에서 토큰 읽기

로그인 API 응답 헤더에서 Authorization 값을 받는 경우도 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const handleLogin = async (credentials: LoginRequest) => {
  const response = await api.post("/api/auth/login", credentials);

  const authHeader = response.headers.authorization;
  const token = authHeader?.replace("Bearer ", "");

  if (!token) return;

  const decoded = jwtDecode<TokenPayload>(token);

  localStorage.setItem("accessToken", token);
  setUser({
    id: decoded.sub,
    nickname: decoded.nickname,
    role: decoded.role,
  });
};

Bearer 문자열을 제거한 뒤 실제 토큰만 decode합니다.


만료 시간 확인하기

JWT payload에는 exp가 들어 있는 경우가 많습니다.

exp는 초 단위 Unix timestamp입니다.

1
2
3
const isExpired = (exp: number) => {
  return Date.now() >= exp * 1000;
};

현재 시간은 밀리초 단위이고, exp는 초 단위이기 때문에 1000을 곱해 비교합니다.

1
2
3
if (isExpired(decoded.exp)) {
  console.log("토큰이 만료되었습니다.");
}

try-catch로 감싸기

토큰이 비어 있거나 형식이 잘못된 경우 jwtDecode에서 에러가 발생할 수 있습니다.

그래서 실제 코드에서는 try-catch로 감싸는 편이 안전합니다.

1
2
3
4
5
6
7
try {
  const decoded = jwtDecode<TokenPayload>(token);
  return decoded;
} catch {
  localStorage.removeItem("accessToken");
  return null;
}

잘못된 토큰이면 저장소에서 제거하고 로그인 상태를 초기화하는 식으로 처리할 수 있습니다.


언제 사용하면 좋을까요?

jwt-decode는 화면에 표시할 기본 사용자 정보를 빠르게 읽을 때 유용합니다.

예를 들어 닉네임, 역할, 토큰 만료 시간처럼 이미 토큰에 포함된 정보를 확인할 수 있습니다.

하지만 최신 사용자 정보가 반드시 필요하거나, 보안상 중요한 정보가 필요하다면 서버 API를 다시 호출하는 것이 더 적절합니다.


마무리

jwt-decode를 사용하면 React에서 JWT payload를 간단히 읽을 수 있습니다.

다만 decode는 검증이나 복호화가 아니기 때문에 보안 기능으로 오해하면 안 됩니다.

토큰에는 최소한의 정보만 넣고, 민감하거나 최신성이 중요한 데이터는 서버를 통해 다시 확인하는 흐름으로 설계하는 것이 좋습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

[React] SweetAlert2로 알림 모달 사용하기

[JWT] Access Token과 Refresh Token 로그인 흐름 이해하기