01 · Concept

인증/인가 전략

Session, JWT, OAuth 2.0 — 세 가지 핵심 인증 방식의 동작 원리와 트레이드오프를 비교합니다.

Session은 서버에 상태를 저장하는 전통적인 방식이고, JWT는 Stateless한 토큰 기반 인증입니다. OAuth 2.0은 제3자 인증(소셜 로그인)을 위한 표준 프로토콜입니다. 실무에서는 JWT Access Token + Refresh Token 조합이 가장 널리 사용되며, 보안을 위해 Refresh Token Rotation httpOnly 쿠키를 함께 적용합니다.

02 · Interactive Demo

인증 흐름 비교 다이어그램

각 인증 방식의 단계별 흐름을 시뮬레이션하고 장단점을 비교하세요.

// Express + express-session
app.use(session({
  secret: 'my-secret',
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: 24 * 60 * 60 * 1000, // 24h
  },
}));

app.post('/login', (req, res) => {
  // 인증 후 세션에 저장
  req.session.userId = user.id;
  res.json({ success: true });
});
Auth Flow
1. 로그인 요청
클라이언트 → 서버: ID/PW 전송
2. 세션 생성
서버: 세션 ID 생성 → 메모리/DB에 저장
3. 쿠키 전송
서버 → 클라이언트: Set-Cookie: sessionId=abc
4. 인증 요청
클라이언트: 매 요청마다 쿠키 자동 첨부
5. 세션 검증
서버: 세션 ID로 사용자 조회 → 인증 확인
03 · Code Example

코드 예시

실제 코드로 동작 원리를 확인하세요.

import jwt from 'jsonwebtoken';

// 토큰 발급
function generateTokens(user) {
  const accessToken = jwt.sign(
    { userId: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );

  const refreshToken = jwt.sign(
    { userId: user.id },
    process.env.REFRESH_SECRET,
    { expiresIn: '7d' }
  );

  return { accessToken, refreshToken };
}

// 인증 미들웨어
function authenticate(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];

  if (!token) return res.status(401).json({ error: 'No token' });

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(401).json({ error: 'Token expired' });
    }
    return res.status(403).json({ error: 'Invalid token' });
  }
}

// 클라이언트: Axios 인터셉터
api.interceptors.request.use((config) => {
  const token = getAccessToken();
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});
04 · Interview Point

면접 핵심 질문

Session: 서버가 세션 데이터를 메모리/DB에 저장하고, 클라이언트에는 세션 ID만 쿠키로 전송합니다. Stateful하여 즉시 무효화가 가능하지만, 서버 확장 시 세션 공유(Redis)가 필요합니다.

JWT: 서버가 서명된 토큰을 발급하고, 검증 시 DB 조회가 불필요합니다. Stateless하여 수평 확장이 쉽지만, 토큰 즉시 무효화가 어렵습니다(블랙리스트 필요). 실무에서는 Access Token(15분) + Refresh Token(7일) 조합이 일반적입니다.
1) 클라이언트가 인가 서버(Google 등)로 리다이렉트 2) 사용자가 권한 동의 3) 인가 서버가 인가 코드(code)를 콜백 URL로 전달 4) 서버가 인가 코드 + client_secret으로 access_token 교환 5) access_token으로 리소스 서버 API 호출

state 파라미터로 CSRF를 방지하고, PKCE(Proof Key for Code Exchange)로 인가 코드 탈취를 방지합니다. client_secret이 서버에서만 사용되어 보안이 강화됩니다.
Access Token은 짧은 만료(15분), Refresh Token은 긴 만료(7-30일)로 설정합니다. Access Token 만료 시 Refresh Token으로 새 Access Token을 발급받습니다.

보안 강화: 1) Refresh Token Rotation — 갱신 시 새 Refresh Token 발급 + 이전 토큰 무효화 2) Absolute Expiry — Refresh Token도 절대 만료 시간 설정 3) DB 저장 — Refresh Token을 DB에 저장하여 즉시 무효화 가능 4) httpOnly 쿠키에 저장하여 XSS 방지