본문으로 바로가기

OAuth vs JWT

OAuth 인가 코드 흐름(권한 위임 절차)을 5단계로 실행하고, 그 결과물인 토큰의 형식(JWT 3부분)을 해부·변조 시연으로 구분한다.

1 / 13OAuth와 JWT는 경쟁 관계가 아닙니다 — OAuth 2.0은 '권한을 위임하는 절차'(프로토콜)이고, JWT는 '토큰을 담는 봉투'(형식)입니다. 절차가 만든 토큰이 그 봉투에 담길 수 있을 뿐입니다.
사용자
인쇄 서비스
구글 인증 서버
① 권한 요청② 로그인·동의③ 인가 코드④ 코드→토큰 교환⑤ 토큰으로 API 호출

비밀번호 대신 '허락'을 건네는 절차

단계 목록 · 키보드 ←/→ 이동, Space 재생

OAuth 2.0은 '비밀번호 대신 허락을 건네는 절차'(프로토콜)이고 JWT는 '검증 가능한 주장을 담는 봉투'(토큰 형식)다 — 절차의 산출물이 그 봉투에 담기곤 할 뿐, 비교 대상이 아니다.

왜 헷갈리는가

"OAuth 쓸까 JWT 쓸까?"라는 질문 자체가 범주 오류다. 세션 vs JWT(상태 저장 위치), OAuth vs API 키(위임 방식), OIDC vs OAuth(신원 vs 권한)가 서로 다른 축인데 전부 '토큰'이라는 한 단어로 뭉개지며 혼란이 시작된다.

애니메이션이 보여주는 것

흐름 무대의 요점은 비밀번호가 구글 밖으로 나가지 않는다는 것이다. 인쇄 서비스가 받는 것은 일회용 코드였다가, 뒷채널에서 자기 비밀과 함께 액세스 토큰으로 바꾼다 — 코드를 도청당해도 client_secret 없이는 쓸모없다. 토큰의 scope는 '사진 읽기'로 제한된다.

해부 무대의 요점은 '읽을 수 있지만 고칠 수 없다'이다. payload는 base64일 뿐이라 누구나 읽는다(비밀 금지). 대신 서명이 header+payload에 묶여 있어, scope 한 글자만 고쳐도 검증이 무너진다. 서버는 DB 조회 없이 서명만으로 토큰을 믿을 수 있다 — 무상태 인증의 근거.

축을 나눠서 다시 보기

헷갈리는 짝들을 축별로 정리하면 이렇다.

  • OAuth 2.0: 제3자에게 내 자원의 '권한'을 위임하는 절차. 산출물은 액세스 토큰(형식 무관 — JWT일 수도, 불투명 문자열일 수도).
  • OIDC: OAuth 위에 '신원'(이 사람이 누구인가)을 얹은 확장 — ID 토큰(이건 JWT로 규격 고정)과 userinfo. '구글로 로그인'의 실체.
  • JWT: 서명된 클레임 봉투. OAuth 없이도 쓴다(마이크로서비스 간 내부 인증, 이메일 검증 링크).
  • 세션 vs JWT: 상태를 서버(세션 저장소)에 둘 것인가 토큰 안에 둘 것인가. JWT의 대가 — 만료 전 강제 폐기가 어렵다. 처방: 수명 짧은 액세스 토큰 + 리프레시 토큰 회전, 또는 중요한 작업만 서버 확인.
  • PKCE: 모바일·SPA처럼 client_secret을 숨길 수 없는 클라이언트를 위한 코드 교환 증명 — 지금은 모든 공개 클라이언트의 필수.

실무에서 저지르는 실수

JWT payload에 개인정보·권한 원본을 넣는 것(누구나 읽는다), alg:none·약한 비밀키 허용(서명 검증 우회), 만료를 며칠로 잡고 폐기 수단이 없는 것, 액세스 토큰을 localStorage에 두고 XSS에 노출하는 것 — 넷 다 '봉투의 성질'을 절차의 보안으로 착각한 데서 나온다.

기억할 것

  • OAuth = 위임 절차, JWT = 토큰 형식 — 층이 다르니 '무엇을 쓸까'의 대상이 아니다.
  • 인가 코드 흐름의 핵심: 비밀번호는 안 건너가고, 코드는 뒷채널에서 비밀과 함께 토큰이 된다.
  • JWT는 읽을 수 있어도 못 고친다 — 서명이 무상태 검증을 가능케 한다.
  • JWT의 대가는 폐기 — 짧은 만료 + 리프레시 회전으로 다스린다.
  • 로그인(신원)이 필요하면 OAuth가 아니라 OIDC를 찾아야 한다.
OAuth vs JWT | KIE