이 글에서 얻는 것

  • Session vs Token: “무조건 JWT가 좋다"는 오해를 풀고, 상황에 맞는 선택 기준을 잡습니다.
  • JWT 구조: Header, Payload, Signature의 역할과 “Base64Url 인코딩"의 의미를 이해합니다.
  • Refresh Token 전략: 보안과 편의성을 모두 잡는 Access/Refresh 토큰 순환 구조를 배웁니다.

1. 세션(Session) 인증: “서버가 기억한다”

전통적인 방식입니다. 사용자가 로그인하면 서버는 메모리(또는 DB/Redis)에 “철수 로그인 했음"이라고 적고, 철수에게는 JSESSIONID 같은 **입장권(Session ID)**만 줍니다.

  • 장점:
    • 보안: 입장권(ID) 자체에는 아무 정보가 없습니다. 서버가 언제든 입장권을 무효화(강제 로그아웃)할 수 있습니다.
  • 단점:
    • 확장성(Scalability): 서버가 2대 이상이면 “A서버에 로그인한 철수"를 B서버도 알아야 합니다. (Sticky Session, Session Clustering 필요)

2. JWT(Token) 인증: “토큰이 증명한다”

서버는 아무것도 기억하지 않습니다(Stateless). 대신 토큰에 “나는 철수고, 관리자 권한이 있고, 1시간 동안 유효해"라는 정보를 적어서 도장(Signature)을 찍어 줍니다.

  • 장점:
    • 확장성: 어떤 서버든 토큰의 도장만 확인하면 되므로 서버를 늘리기 쉽습니다.
    • 모바일 친화적: 쿠키를 잘 안 쓰는 모바일 앱 환경에 적합합니다.
  • 단점:
    • 통제 불가: 토큰을 탈취당하면 만료될 때까지 막을 방법이 없습니다. (Blacklist를 만들면 결국 세션과 비슷해짐)
    • 데이터 크기: 토큰에 정보를 많이 담으면 네트워크 트래픽이 늘어납니다.

3. JWT 구조 해부

JWT는 aaaaa.bbbbb.ccccc 처럼 점 3개로 구분됩니다.

  1. Header: “나 HS256 알고리즘 썼어.”
  2. Payload: “내 이름은 철수(sub), 만료는 내일(exp).” (Base64로 인코딩되어 누구나 볼 수 있음! 비밀번호 넣으면 안 됨!)
  3. Signature: “Header + Payload + 서버의 비밀키"를 섞어서 만든 암호화 서명. (위변조 방지)

4. Access Token & Refresh Token 전략

JWT의 단점(탈취 시 위험)을 보완하기 위해 두 개의 토큰을 씁니다.

  1. Access Token: 유효기간 30분. API 요청할 때 씀. 탈취돼도 30분 뒤면 똥이 됩니다.
  2. Refresh Token: 유효기간 2주. DB(Redis)에 저장. Access Token이 죽으면 새거 발급받을 때 씀.

흐름:

  1. 로그인 → Access Token + Refresh Token 발급.
  2. Access Token으로 API 신나게 씀.
  3. 30분 뒤 401 에러(만료).
  4. 클라이언트가 Refresh Token 보내서 재발급 요청.
  5. 서버가 Refresh Token 확인(DB랑 비교) → 맞으면 새 Access Token 발급.

요약

  • 웹(Browser) 위주라면 Session이 보안상 더 안전하고 편할 수 있습니다.
  • **앱(Mobile)**이나 MSA 환경라면 JWT가 필수적입니다.
  • JWT를 쓸 때는 Refresh Token을 활용해 보안성을 높이고, HttpOnly Cookie에 저장하여 XSS를 방어하는 것이 좋습니다.