Hello Kitty Eyes Shut
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ’ป๊ณต๋ถ€ ๊ธฐ๋ก/๐Ÿ“Œ Backend

[Backend] JWT

๋ฐ˜์‘ํ˜•

 

 

 

๐Ÿ“Œ JWT๋ž€

JWT (Json Web Token)์ด๋ž€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ (Authentication)๊ณผ ๊ถŒํ•œ ๋ถ€์—ฌ (Authorization)๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹์ด๋‹ค.

์ด ํ† ํฐ์€ ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๊ฐ„์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ตํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋ฉฐ,

ํŠนํžˆ HTTP ํ—ค๋”๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ ๊ฐ€๋Šฅํ•˜๊ณ , ์ž์ฒด์ ์œผ๋กœ ์ธ์ฆ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋œ๋‹ค.

JWT๋Š” ๊ทธ ์ž์ฒด๋กœ ๋””์ง€ํ„ธ ์„œ๋ช…์ด ํฌํ•จ๋œ JSON ๊ฐ์ฒด์ด๋ฉฐ, ์„ธ์…˜ ์—†์ด ์ธ์ฆ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

 


๐Ÿ” JWT์˜ ์ •์˜

๊ณต์‹ ๋ช…์„ธ๋ฅผ ํ†ตํ•ด ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด, JWT๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋œ๋‹ค.

A compact, URL-safe means of representing claims to be transferred between two parties.

 

์ฆ‰, ๋‘ ์ฃผ์ฒด ์‚ฌ์ด์—์„œ ํด๋ ˆ์ž„ (Claims)์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ์ž‘๊ณ , URL-safeํ•œ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ๋œป์ด๋‹ค.

์—ฌ๊ธฐ์—์„œ ๋งํ•˜๋Š” ํด๋ ˆ์ž„(Clamis)์€ ์‚ฌ์šฉ์ž ID, ๊ถŒํ•œ, ํ† ํฐ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ๋“ฑ์˜ ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์„ ์˜๋ฏธํ•œ๋‹ค.

 


JWT๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

xxxxx.yyyyy.zzzzz

 

์ด ์„ธ ๋ถ€๋ถ„์€ ๊ฐ๊ฐ ๋‹ค์Œ์˜ ํ‘œ์™€ ๊ฐ™์€ ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š”๋‹ค.

๊ตฌ์„ฑ ์š”์†Œ ์„ค๋ช…
Header ํ† ํฐ์˜ ํƒ€์ž…๊ณผ ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ณด
Payload ์‚ฌ์šฉ์ž ์‹๋ณ„ ์ •๋ณด ๋ฐ ํด๋ ˆ์ž„์„ ํฌํ•จํ•œ ๋ณธ๋ฌธ ๋ฐ์ดํ„ฐ
Signature ํ† ํฐ์ด ๋ณ€์กฐ๋˜์ง€ ์•Š์•˜์Œ์„ ์ฆ๋ช…ํ•˜๋Š” ์„œ๋ช… ๊ฐ’

 

์ตœ์ข…์ ์œผ๋กœ, ๊ฐ๊ฐ Base64Url ์ธ์ฝ”๋”ฉ๋˜์–ด์„œ . (dot) ์œผ๋กœ ์—ฐ๊ฒฐ๋œ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด์ด ๋œ๋‹ค.

 


๐Ÿงฑ ๊ตฌ์„ฑ ์š”์†Œ ์ƒ์„ธ ๋ถ„์„

1๏ธโƒฃ Header

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (ex. HS256, RS256 ๋“ฑ)
  • typ: ํ† ํฐ ํƒ€์ž… (JWT)

์ด ํ—ค๋”๋Š” ์–ด๋–ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ช…ํ• ์ง€์— ๋Œ€ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์ด๋‹ค.

 


2๏ธโƒฃ Payload

{
  "sub": "user123",
  "name": "์†Œ์—ฐ",
  "role": "ADMIN",
  "exp": 1750600000
}

 

Payload๋Š” ์‹ค์ œ๋กœ ํ† ํฐ์ด ๋‹ด๊ณ  ์‹ถ์€ ํด๋ ˆ์ž„ (Claims)์˜ ์ง‘ํ•ฉ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์ด๋Ÿฌํ•œ ํด๋ ˆ์ž„์€ ํฌ๊ฒŒ ๋‹ค์Œ ์„ธ ๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜๋œ๋‹ค.

  • Registered claims (ํ‘œ์ค€ ํด๋ ˆ์ž„): iss, exp, sub, aud ๋“ฑ
  • Public claims (๊ณต๊ฐœ ํด๋ ˆ์ž„): ์ถฉ๋Œ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด URI๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ถ€์—ฌ ํ•„์š”
  • Private claims (์‚ฌ์„ค ํด๋ ˆ์ž„): ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ๋…์ž์ ์ธ ๊ทœ์น™

โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ

์ด๋•Œ, Payload๋Š” ์•”ํ˜ธํ™”๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ˆ„๊ตฌ๋“ ์ง€ ํ† ํฐ์„ ๋””์ฝ”๋”ฉํ•ด์„œ ๋‚ด๋ถ€ ์ •๋ณด๋ฅผ ์—ด๋žŒํ•  ์ˆ˜ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ์ ˆ๋Œ€ Payload์— ํฌํ•จํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

 

 


3๏ธโƒฃ Signature

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

 

์„œ๋ช…์€ ํ† ํฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

๋”ฐ๋ผ์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ† ํฐ์„ ์œ„์กฐํ•˜๋”๋ผ๋„, ์„œ๋ช…์ด ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ฒ„๋Š” ์ด๋ฅผ ๊ฒ€์ฆ ์‹คํŒจ๋กœ ๊ฐ„์ฃผํ•˜์—ฌ ๊ฑฐ๋ถ€ํ•œ๋‹ค.

 


โœˆ๏ธ ์™œ JWT๋ฅผ ์‚ฌ์šฉํ• ๊นŒ?

JWT๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ ๋‹ค์Œ์˜ ๋„ค ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  • ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ (Stateless): ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๋ฅผ ๊ธฐ์–ตํ•˜์ง€ ์•Š์•„๋„ ๋ผ์„œ ํ™•์žฅ์„ฑ(Scalability) ์šฉ์ด
  • ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์— ์œ ์—ฐํ•จ: HTTP ํ—ค๋”, ์ฟ ํ‚ค, ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅ
  • Cross-Origin ์ง€์›: RESTful API ๋“ฑ CORS ํ™˜๊ฒฝ์— ์œ ๋ฆฌ
  • ์„œ๋ช… ๊ธฐ๋ฐ˜ ๊ฒ€์ฆ์œผ๋กœ ์œ„๋ณ€์กฐ ๋ฐฉ์ง€

 


๐Ÿ” JWT์™€ OAuth์˜ ์ฐจ์ด์ 

๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด JWT์™€ OAuth๋ฅผ ํ˜ผ๋™ํ•˜๋Š”๋ฐ,

Oauth๋Š” ์ธ์ฆ ๋ฐฉ์‹์ด๊ณ , JWT๋Š” ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด๋Š” ํ˜•์‹์ด๋‹ค.

์ด๋Ÿฌํ•œ JWT๋Š” OAuth์˜ ์•ก์„ธ์Šค ํ† ํฐ ํฌ๋งท ์ค‘ ํ•˜๋‚˜๋กœ ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ•œ๋‹ค.

 


๐Ÿง  ๊ฒฐ๋ก 

JWT๋Š” ๋‹จ์ˆœํ•˜๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ ์ธ์ฆ ๋งค์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

๊ธฐ์กด์˜ ์„ธ์…˜ ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹์ด ์„œ๋ฒ„์— ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค๋ฉด,

JWT๋Š” ํ† ํฐ ๊ทธ ์ž์ฒด์— ๋ชจ๋“  ์ƒํƒœ ์ •๋ณด๋ฅผ ๋‹ด๋Š” ๋ฐฉ์‹์ด๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„๋Š” ๋ฌด์ƒํƒœ(stateless)๋กœ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ,

์ด๋Š” ๋ถ„์‚ฐ ์‹œ์Šคํ…œ, ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค, ์„œ๋ฒ„๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜ ๋“ฑ์—์„œ ๋”์šฑ ๋น›์„ ๋ฐœํ•œ๋‹ค.

๋ฐ˜์‘ํ˜•

'๐Ÿ’ป๊ณต๋ถ€ ๊ธฐ๋ก > ๐Ÿ“Œ Backend' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Backend] RedisTemplate  (1) 2025.06.28
[Backend] Redis TTL + JWT  (0) 2025.06.22
[Backend] Java 17 VS Java 21  (2) 2025.06.17
[Backend] CI ์„ค์ •์—์„œ distribution  (0) 2025.06.17
[Backend] Listํ˜• ๋ช…๋ น์–ด  (0) 2025.01.12