세션 토큰 vs JWT: 잘못된 이분법

발행: (2026년 1월 2일 오후 07:56 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

“JWT‑only” 접근 방식

// User logs in
const jwt = sign(
  { userId: user.id, role: user.role },
  SECRET,
  { expiresIn: '7d' }
);
setCookie('token', jwt);

// Every request
const payload = verify(req.cookies.token, SECRET);
// Done. No database hit.

장점

  • 데이터베이스 쿼리 없음 – 모든 서버가 토큰을 검증할 수 있음.
  • “무상태” 인증 (그게 무슨 의미인지 알 수 있든 말든).

단점

  • 폐기 문제 – 사용자가 삭제되거나 해고되더라도, 해당 JWT는 최대 7 일 동안 유효합니다.
  • 구식 역할 데이터 – 사용자의 역할을 변경해도 이미 발급된 토큰에는 영향을 주지 않습니다.
  • ‘전역 로그아웃’ 없음 – 도난당한 노트북, 분실된 기기 등은 토큰이 만료될 때까지 계속 유효합니다.

결과: 요청당 약 0.97 ms의 빠른 속도와 초당 약 5,527 요청의 높은 처리량을 제공하지만, 토큰을 폐기할 수 없으며 데이터가 즉시 구식이 됩니다.

“세션‑전용” 접근 방식

// User logs in
const sessionId = randomBytes(32).toString('hex');
await db.session.create({
  id: sessionId,
  userId: user.id,
  expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
});
setCookie('sessionId', sessionId);

// Every request – database lookup
const session = await db.session.findUnique({
  where: { id: req.cookies.sessionId },
  include: { user: true }
});

if (!session || session.expiresAt /* … */) {
  // handle missing or expired session
}

Result: 안전하지만 느림; 데이터베이스가 제한 요소가 됩니다.

하이브리드 접근 방식이 효과적인 이유

하이브리드 방법은 액세스 토큰이 만료될 때만 스토리지를 접근합니다 (예: 전체 요청의 약 1 %). 나머지 99 %의 요청에 대해서는 네트워크 호출 없이 JWT‑수준의 속도를 얻을 수 있습니다.

Redis에 대한 간단한 참고

세션 스토리지를 PostgreSQL 대신 Redis로 교체하면 조회 시간이 ~2–3 ms로 감소하지만 모든 요청에 대해 여전히 외부 호출을 수행하게 됩니다. 하이브리드 접근 방식은 대부분의 트래픽에 대해 그 호출조차도 없애줍니다.

“마이크로서비스” 반론

“마이크로서비스는 데이터베이스를 공유하지 않으므로 JWT만이 토큰을 독립적으로 검증하는 유일한 방법이다.”

실제로 마이크로서비스는 이미 다음을 공유한다:

  • 영속성을 위한 데이터베이스(또는 클러스터)
  • 공유 상태를 위한 Redis(또는 다른 캐시)
  • 메시지 큐, 로깅, 모니터링 등

이미 캐시용 Redis가 있다면 세션 검증은 비용이 적다. 하이브리드 접근 방식은 99 %의 요청에 대해 네트워크 왕복을 피함으로써 여전히 승리한다.

해결책: 단기간 접근 토큰 + 장기간 리프레시 토큰

JWT와 세션 중 하나를 고르는 문제가 아니라, JWT + 세션을 결합해 각각의 장점을 살리는 방식입니다.

작동 방식

// User logs in
async function login(email, password) {
  const user = await authenticateUser(email, password);

  // Refresh token – stored in DB (valid for 30 days)
  const refreshToken = randomBytes(32).toString('hex');
  await db.session.create({
    userId: user.id,
    refreshToken,
    expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)
  });

  // Access token – NOT stored, just a JWT (valid for 15 minutes)
  const accessToken = jwt.sign(
    { userId: user.id, role: user.role },
    SECRET,
    { expiresIn: '15m' }
  );

  // Send tokens to the client
  res.cookie('accessToken', accessToken, { httpOnly: true });
  res.cookie('refreshToken', refreshToken, { httpOnly: true });
}
  • 접근 토큰 (JWT) – 짧은 수명, 로컬에서 검증, DB/Redis 조회 없음.
  • 리프레시 토큰 (세션) – 긴 수명, DB/Redis에 저장, 접근 토큰이 만료되었을 때 또는 사용자가 명시적으로 로그아웃할 때만 사용.

리프레시 흐름 (단순화)

// Refresh endpoint
async function refresh(req, res) {
  const { refreshToken } = req.cookies;
  const session = await db.session.findUnique({
    where: { refreshToken },
    include: { user: true }
  });

  if (!session || session.expiresAt /* … */) {
    // handle missing or expired refresh token
    return;
  }

  // Issue a new short‑lived access token
  const newAccessToken = jwt.sign(
    { userId: session.user.id, role: session.user.role },
    SECRET,
    { expiresIn: '15m' }
  );

  res.cookie('accessToken', newAccessToken, { httpOnly: true });
}

핵심 요점: 세션만 사용하면 인증 시스템이 DB 병목이 됩니다. 하이브리드 방식은 JWT의 빠른 검증 속도를 유지하면서 세션 방식의 제어 기능을 추가합니다.

전체 벤치마크 결과는 stat-tests/RESULTS.md에 있으며, 테스트 코드는 stat-tests/test-three-auth-strategies에서 확인할 수 있습니다.

Recommendations

  • Use the hybrid approach for virtually everything. It gives you JWT‑level speed with session‑level security.
    하이브리드 접근법을 거의 모든 경우에 사용하세요. JWT 수준의 속도와 세션 수준의 보안을 제공합니다.

  • JWT‑only only when tokens are extremely short‑lived (< 5 min) and you truly don’t care about revocation (rare).
    → 토큰이 매우 짧은 기간(< 5 분)만 유지되고, 실제로 폐기(리보케이션)를 신경 쓰지 않을 때만 JWT‑only를 사용하세요(드물게).

  • Session‑only only for tiny apps (< 10 req/sec) where simplicity outweighs performance concerns.
    → 단순함이 성능 우려보다 중요한 작은 앱(< 10 req/sec)일 때만 Session‑only를 사용하세요.

You don’t have to pick sides. Get the speed of JWTs and the control of sessions—just think about the trade‑offs instead of cargo‑culting a single approach.
→ 어느 쪽을 고집할 필요는 없습니다. JWT의 속도와 세션의 제어를 모두 얻으세요—단일 접근법을 맹목적으로 따르기보다 트레이드오프를 고민하세요.

Happy hacking!
행복한 해킹 되세요!

Back to Blog

관련 글

더 보기 »

Academic Suite 인증 및 인가

3.1 Academic Suite의 인증 접근 방식 Academic Suite는 JSON Web Token JWT를 사용한 stateless authentication 방식을 사용합니다. session‑based authentication과 달리…