BackEnd

[์ธ์ฆ/์ธ๊ฐ€] RefreshToken์€ ์™œ Redis๋ฅผ ์‚ฌ์šฉํ•ด ๊ด€๋ฆฌํ• ๊นŒ? (with. RTR ๋ฐฉ์‹)

PgmJUN 2023. 6. 13. 13:38

 

redis

 

1. โ€œ์™œ?โ€ ๐Ÿค”

์šฐ๋ฆฌ๋Š” MySQL๊ณผ ๊ฐ™์€ ์ผ๋ฐ˜ DB๋ฅผ ๋‹ค๋ฃฐ ์ค„ ์•„๋Š”๋ฐ ์‚ฌ๋žŒ๋“ค์€
์™œ ๊ตณ์ด ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ Redis์— ์ €์žฅํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ–ˆ์œผ๋ฉฐ,
์™œ ๋‹ค๋“ค Redis๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์ €์žฅํ•˜๋Š” ์ง€ ๊ถ๊ธˆํ–ˆ์Šต๋‹ˆ๋‹ค.
 
์šฐ์„  JWT์— ๋Œ€ํ•ด์„œ ์ž์„ธํžˆ ๋ชจ๋ฅด์‹œ๋Š” ๋ถ„๋“ค์€ ํ•ด๋‹น ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•ด์„œ ํ•™์Šตํ•ด์ฃผ์‹œ๋ฉด ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
 
 


2. Redis๊ฐ€ ๋ญ”๋ฐ?

๋ ˆ๋””์Šค๋Š” ๋””์Šคํฌ๊ฐ€ ์•„๋‹Œ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” In-Memory ๋ฐฉ์‹์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ž…๋‹ˆ๋‹ค.
 
 

2-1. In-Memory?

In-Memory ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” MySQL๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ์ผ๋ฐ˜ DB๋“ค์ฒ˜๋Ÿผ SSD, HDD์™€ ๊ฐ™์€ ๋ณด์กฐ๊ธฐ์–ต์žฅ์น˜๊ฐ€ ์•„๋‹Œ, ํ”„๋กœ์„ธ์„œ๊ฐ€ ์ง์ ‘ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํ“จํ„ฐ์˜ ์ฃผ ๋ฉ”๋ชจ๋ฆฌ์ธ RAM์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
 
 

2-2. ๋””์Šคํฌ์— ์ €์žฅํ•˜๋Š” ๊ฒƒ๊ณผ ๋ฌด์Šจ์ฐจ์ด๊ฐ€ ์žˆ๋Š”๋ฐ?

ํŠน์ • ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์ปดํ“จํ„ฐ๋Š” ๋ณด์กฐ๊ธฐ์–ต์žฅ์น˜์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ RAM์œผ๋กœ ๋ถˆ๋Ÿฌ์™€ CPU๊ฐ€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณผ์ •์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

Disk-RAM-CPU ํ”Œ๋กœ์šฐ

์—ฌ๊ธฐ์„œ ์žฅ์ ์ด ํ™•์—ฐํžˆ ๋ณด์ด์ง€ ์•Š๋‚˜์š”?

RAM์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋ณด์กฐ๊ธฐ์–ต์žฅ์น˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ Loadํ•˜๋Š” ๋น„์šฉ์ด ์ ˆ์•ฝ๋ฉ๋‹ˆ๋‹ค.
๋•Œ๋ฌธ์— ์ธ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ ์—ฐ์‚ฐ์€ ๊ธฐ์กด ๋””์Šคํฌ ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฆ…๋‹ˆ๋‹ค.
 

ํ•˜์ง€๋งŒ ๋ณด์กฐ๊ธฐ์–ต์žฅ์น˜์™€๋Š” ๋‹ค๋ฅด๊ฒŒ RAM์€ ์ „์›์ด ๋Š์–ด์ง€๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋ถ€ ์ง€์›Œ์ง€๋Š” ํœ˜๋ฐœ์„ฑ ๋ฉ”๋ชจ๋ฆฌ(Volatile Memory)๋ผ๋Š” ํŠน์ง•์ด ์žˆ๋‹ค!

 


3. Redis์˜ ํŠน์ง•

  • Key-Value์˜ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ์ ์€ ๋ฉ”๋ชจ๋ฆฌ๋กœ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž‘์„ฑ ์†๋„๊ฐ€ ๋น ๋ฆ„
  • Key-Value ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ‚ค๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ์กฐํšŒ ์„ฑ๋Šฅ์ด O(1)๊นŒ์ง€ ๋‚˜์˜จ๋‹ค๋Š” ์žฅ์ ์„ ๊ฐ€์ง
  • ์ธ๋ฉ”๋ชจ๋ฆฌ DB ๋ฐฉ์‹์œผ๋กœ ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅ
  • ํœ˜๋ฐœ์„ฑ์ธ In-Memory DB๋Š” ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅ๋  ํ•„์š”๊ฐ€ ์—†๋Š” Refresh token์„ ๊ด€๋ฆฌํ•˜๊ธฐ์— ์ถฉ๋ถ„
  • ์บ์‹œ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ ๋งŒ๋ฃŒ์ผ์„ ์ •ํ•  ์ˆ˜ ์žˆ์Œ

 
 

3-1. Redis์˜ ํŠน์ง•์ด Refresh Token ๋ณด๊ด€์— ์ด์ ์ด ๋˜๋Š” ์ด์œ 

์ด๋Ÿฌํ•œ Redis์˜ ํŠน์ง•์„ ํ† ๋Œ€๋กœ Refresh Token์„ ๋ณด๊ด€ํ•˜๋Š” ๊ฒƒ์ด ์ ํ•ฉํ•œ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•ด๋ณด์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์šฐ์„  RDB์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ์˜ ๋งŒ๋ฃŒ์ผ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ TTL(Time-To-Live)์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ, ์ด๋ฅผ ํ† ํฐ์˜ ๋งŒ๋ฃŒ์ผ๊ณผ ๋˜‘๊ฐ™์ด ๋งž์ถฐ๋‘์–ด ๊ด€๋ฆฌํ•˜๋ฉด ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด Redis์—์„œ๋„ ํ† ํฐ์ด ์‚ญ์ œ๋˜๋„๋ก ํ•˜์—ฌ ๋ฆฌ์†Œ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๋งŒ๋ฃŒ๋œ ํ† ํฐ๊นŒ์ง€ ๊ฐ–๊ณ ์žˆ๋„๋ก ํ•ด์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋‚ญ๋น„ํ•  ํ•„์š”๋Š” ์—†์ž–์•„์š”~)

  2. ๋Œ€์ฒด๋กœ 15๋ถ„~2์‹œ๊ฐ„ ๋‹จ์œ„๋กœ ๊ฐฑ์‹ ํ•˜๋Š” JWT Access Token์€ ์ƒˆ๋กญ๊ฒŒ ๊ฐฑ์‹ ํ•˜๊ธฐ ์œ„ํ•ด Refresh Token์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    ์ด๋ ‡๊ฒŒ ํ˜ธ์ถœ์˜ ๋นˆ๋„๊ฐ€ ๋Œ€์ฒด์ ์œผ๋กœ ๋†’์€ Refresh Token์€ RDB์— ์ €์žฅํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค In-Memory DB์— ์ €์žฅํ•ด๋‘๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์†๋„๊ฐ€ ๋น ๋ฅด๊ณ , ํ† ํฐ ReIssue ๋กœ์ง์˜ ๋ณ‘๋ชฉํ˜„์ƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค์Šต๋‹ˆ๋‹ค.

  3. ๋ชจ๋“  ๊ธฐ์ˆ  ์‚ฌ์šฉ์—๋Š” ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. RDB vs In-Memory DB์˜ ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„๋Š” ์†๋„์™€ ์•ˆ์ •์„ฑ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
    In-Memory ๋ฐฉ์‹์€ ๊ต‰์žฅํžˆ ๋›ฐ์–ด๋‚œ ์กฐํšŒ ์†๋„๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์–ด ํ˜ธ์ถœ์˜ ๋นˆ๋„๊ฐ€ ๋†’์€ ํ† ํฐ ReIssue ๋กœ์ง์˜ ๋ณ‘๋ชฉํ˜„์ƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ In-Memory DB๋Š” ํœ˜๋ฐœ์„ฑ ๋ฉ”๋ชจ๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ „์›์ด ๋Š์–ด์ง€๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋ถ€ ์ง€์›Œ์ง‘๋‹ˆ๋‹ค.
    ๊ทธ๋Ÿฐ๋ฐ ๋‹จ์ง€ Refresh Token๋งŒ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Redis๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ด ํŠธ๋ ˆ์ด๋“œ ์˜คํ”„๋Š” ์†์‹ค๋ณด๋‹ค ์ด๋“์ด ๋” ํด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. Refresh Token์ด ๋ชจ๋‘ ์‚ญ์ œ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์‚ฌ๊ฑด์€ ๋ชจ๋“  ์œ ์ €๊ฐ€ ์žฌ๋กœ๊ทธ์ธ์„ ํ•ด์•ผํ•œ๋‹ค๋Š” ์ ์ธ๋ฐ, ์›ฌ๋งŒํ•ด์„  ์ „์›์ด ๋Š์–ด์งˆ ์ผ์ด ์ž์ฃผ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ๋•Œ๋ฌธ์— ์œ ์ € ๊ฒฝํ—˜์— ๊ทธ๋ฆฌ ํฌ๋ฆฌํ‹ฐ์ปฌํ•˜๊ฒŒ ์ž‘์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด Master/Slave ๋ณต์ œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋†“์œผ๋ฉด Slave์— Master์˜ ๋ณ€๊ฒฝ์ด ๋ฐ˜์˜๋˜๋‹ค๊ฐ€ Master์— ์žฅ์•  ๋ฐœ์ƒ ์‹œ, Slave๋กœ FailOver๋˜์–ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฑฐ์˜ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฒฐ๋ก ์ ์œผ๋กœ ์œ„์™€ ๊ฐ™์€ ์ด์œ ๋“ค์— ์˜ํ•ด In-Memory DB์— ๊ด€๋ฆฌํ•ด๋„ ์ถฉ๋ถ„ํžˆ ํšจ์œจ์ ์ด๋ผ๋Š” ๊ฐœ์ธ์˜ ์ƒ๊ฐ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 


4. ๊ทธ๋Ÿผ RefreshToken์€ ์™œ DB์— ์ €์žฅํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฑด๋ฐ?

์šฐ์„  ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ๊ณผ ์—‘์„ธ์Šค ํ† ํฐ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์—‘์„ธ์Šค ํ† ํฐ: ์„œ๋ฒ„์— API๋ฅผ ์ง์ ‘ ์š”์ฒญ(Access)ํ•  ๋•Œ ์‚ฌ์šฉ
  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ ์—‘์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์„ ๋•Œ, ์—‘์„ธ์Šค ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰(Refresh)ํ•  ๋•Œ ์‚ฌ์šฉ

์ด ๋‘˜์ด ๋ถ„๋ฆฌ๋œ ์ด์œ ๋Š” ๋ณด์•ˆ์ž…๋‹ˆ๋‹ค.
ํ† ํฐ์„ ํƒˆ์ทจ๋‹นํ•˜๋ฉด ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋‚ด ๊ณ„์ •์˜ ๊ถŒํ•œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋น„์Šค๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์œ„ํ—˜์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ ˆ๋Œ€ ๋…ธ์ถœ๋˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.
JWT ํ† ํฐ์€ Stateless๋ผ๋Š” HTTP์˜ ํŠน์ง•์— ์˜ํ•ด ํ•œ๋ฒˆ ๋ฐœ๊ธ‰๋˜๋ฉด ๊ทธ ๋’ค๋กœ ํ† ํฐ์˜ ์ƒํƒœ์— ๋Œ€ํ•ด ๊ด€๋ฆฌํ•  ์ˆ˜ ์—†์œผ๋ฉฐ,
๊ทธ๋ ‡๋‹ค๋ณด๋‹ˆ ํšŒ์›์ด ํ† ํฐ์„ ํ†ตํ•ด ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฑด์ง€, ํ•ด์ปค๊ฐ€ ํ† ํฐ์„ ํƒˆ์ทจํ•ด์„œ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฑด์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
 
๋•Œ๋ฌธ์— ์œ ์ € ์ธ์ฆ ์—ญํ• ์„ ๊ฐ€์ง„ ์—‘์„ธ์Šค ํ† ํฐ์€ ๋Œ€์ฒด๋กœ ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ์งง๊ฒŒ ์žก์Šต๋‹ˆ๋‹ค. (๋ณดํ†ต 30๋ถ„ ~ 2์‹œ๊ฐ„ ์ •๋„๋กœ ์ƒ๊ฐํ•˜๋Š”๋ฐ, ์„œ๋น„์Šค์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค)
์ด๋Ÿฌํ•œ ์—‘์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด ์—‘์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋•Œ๋ฌธ์— ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ ์—‘์„ธ์Šค ํ† ํฐ๋ณด๋‹ค ํ›จ์”ฌ ๊ธด ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. (์ €๋Š” ๋ณดํ†ต 1์ฃผ ~ 1๊ฐœ์›” ์ •๋„๋กœ ์ƒ๊ฐํ•˜๋Š”๋ฐ, ์„œ๋น„์Šค์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)
 
 

4-1. ๊ทธ๋Ÿผ ํ† ํฐ์ด ํƒˆ์ทจ๋‹นํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

์—‘์„ธ์Šค ํ† ํฐ๋งŒ ํƒˆ์ทจ ๋‹นํ•œ๋‹ค๋ฉด 30๋ถ„ ~ 2์‹œ๊ฐ„ ์ •๋„๋งŒ ์œ ์ €์˜ ๊ถŒํ•œ์„ ๋งˆ์Œ๋Œ€๋กœ ์ด์šฉํ•˜๊ณ  ๊ทธ ๋’ค์—” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ,
์—‘์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ์ด ๋ชจ๋‘ ํƒˆ์ทจ ๋‹นํ•˜๋ฉด ์ตœ์•…์˜ ๊ฒฝ์šฐ ํ•ด์ปค๋Š” ๊ณ„์†ํ•ด์„œ ์—‘์„ธ์Šค ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰ํ•˜๋ฉฐ ์œ ์ €์˜ ๊ถŒํ•œ์„ ์•…์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
 

4-2. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” Refresh Token์„ DB์— ์ €์žฅํ•ด๋†“๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์šฐ์„  ์œ„์˜ ๋ง ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(Redis)์— ์œ ์ € ์ •๋ณด์™€ Refresh Token์„ ์ €์žฅํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Key: ์œ ์ € ๊ณ ์œ ์ •๋ณด (ex. member Entity ID)
  • Value: RefreshToken

๊ทธ๋ฆฌ๊ณ  ์ด์™€ ํ•จ๊ป˜ Refresh Token Rotation(RTR) ๋ฐฉ์‹์œผ๋กœ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ์„ ๊ด€๋ฆฌํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
 
RTR ๋ฐฉ์‹์€ RefreshToken์„ DB์—์„œ ๊ด€๋ฆฌํ•  ๋•Œ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
ํ”Œ๋กœ์šฐ๋ฅผ ์‚ดํŽด๋ณผ๊นŒ์š”?
 
 

(์ขŒ) ํ† ํฐ ์ €์žฅ ๋ฐ ๊ฐฑ์‹  ํ”Œ๋กœ์šฐ / (์šฐ) RefreshToken ๋งŒ๋ฃŒ ์‹œ ํ”Œ๋กœ์šฐ

(์ขŒ) ํ† ํฐ ์ €์žฅ ๋ฐ ๊ฐฑ์‹  ํ”Œ๋กœ์šฐ / (์šฐ) RefreshToken ๋งŒ๋ฃŒ ์‹œ ํ”Œ๋กœ์šฐ

 

 
 
Access Token์ด ๋งŒ๋ฃŒ๋˜์–ด ํ† ํฐ์„ ๊ฐฑ์‹ ์‹œํ‚ค๋Š” ์‹œ์ ์—
ํด๋ผ์ด์–ธํŠธ๋Š” ํ† ํฐ ๊ฐฑ์‹ ์„ ์œ„ํ•ด ํ† ํฐ ๊ฐฑ์‹  API ์— AccessToken, RefreshToken์„ ๋‹ด์•„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
์ „๋‹ฌ๋ฐ›์€ ํ† ํฐ์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด, AccessToken์„ ํ†ตํ•ด ์œ ์ € ์ •๋ณด(member PK)๋ฅผ ์–ป๊ณ ,
DB์—์„œ ์œ ์ € ์ •๋ณด์— ํ•ด๋‹นํ•˜๋Š” Refresh Token ์„ ์กฐํšŒํ•ด์˜ต๋‹ˆ๋‹ค.
 
์ด๋•Œ 'DB์—์„œ ์กฐํšŒํ•ด์˜จ Refresh Token'๊ณผ ํด๋ผ์ด์–ธํŠธ์—์„œ '์š”์ฒญ์— ๋‹ด์•„ ๋ณด๋‚ธ Refresh Token' ์ด ๋™์ผํ•˜๋‹ค๋ฉด ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.
์ƒˆ๋กœ ๋ฐœ๊ธ‰๋œ Access Token, RefreshToken์€ ํด๋ผ์ด์–ธํŠธ ์ธก์— ์ „์†ก๋˜๋ฉฐ, ์ƒˆ๋กœ์šด RefreshToken์€ DB์— ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.
 
์ด๋ ‡๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ Refresh Token์„ 1ํšŒ์šฉ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
 
 

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ RTR ๋ฐฉ์‹์œผ๋กœ ์–ด๋–ป๊ฒŒ ํƒˆ์ทจ๋กœ ์ธํ•œ ํ”ผํ•ด๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š”๊ฑธ๊นŒ์š”?

 
ํƒˆ์ทจ ํ”Œ๋กœ์šฐ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
 
1. ๋กœ๊ทธ์ธ ์‹œ์— ์œ ์ €๋Š” Access Token๊ณผ Refresh Token์„ ์‘๋‹ต๋ฐ›์Šต๋‹ˆ๋‹ค.
(์ด๋•Œ Redis์— Refresh Token์ด MemberId(Key):RefreshToken(Value) ํ˜•ํƒœ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

2. ์ด๋•Œ ์œ ์ €์—๊ฒŒ AccessToken, Refresh Token์„ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์—์„œ ํ•ด์ปค๊ฐ€ ํ† ํฐ์„ ํƒˆ์ทจํ•ฉ๋‹ˆ๋‹ค.
 
3. ํ•ด์ปค๋Š” ํƒˆ์ทจํ•œ AccessToken์„ ํ†ตํ•ด ์œ ์ €์˜ ๊ถŒํ•œ์„ ์‚ฌ์šฉํ•˜๋˜ ์ค‘ ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
(์ด๋•Œ ๋‹น์—ฐํžˆ ๊ฐ™์€ ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ €๋„ ๋งŒ๋ฃŒ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.)

์ด๋•Œ ์œ ์ €๊ฐ€ ๋จผ์ € ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒฝ์šฐ(4-1)์™€ ํ•ด์ปค๊ฐ€ ๋จผ์ € ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒฝ์šฐ(4-2) ๋กœ ๋‘ ๊ฐ€์ง€ ์ƒํ™ฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 
4-1. ์ด๋•Œ ์œ ์ €๊ฐ€ ๋จผ์ € ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒฝ์šฐ, DB์˜ RefreshToken๋„ ๊ฐฑ์‹ ๋˜๋ฉฐ
์ดํ›„์— ํ•ด์ปค๊ฐ€  ํ† ํฐ ๊ฐฑ์‹ ์„ ์š”์ฒญํ–ˆ์„ ๋•Œ DB์— ์ €์žฅ๋œ RefreshToken๊ณผ ํ•ด์ปค๊ฐ€ ๊ฐฑ์‹ ์„ ์œ„ํ•ด ์š”์ฒญ์— ๋‹ด์•„๋ณด๋‚ธ RefreshToken์ด ๋‹ฌ๋ผ์„œ ํ† ํฐ ๊ฐฑ์‹ ์— ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.
 
4-2. ํ•ด์ปค๊ฐ€ ๋จผ์ € ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒฝ์šฐ, DB์˜ RefreshToken๋„ ๊ฐฑ์‹ ๋˜๋ฉฐ
์ดํ›„์— ์œ ์ €๊ฐ€ ํ† ํฐ ๊ฐฑ์‹ ์„ ์š”์ฒญํ–ˆ์„ ๋•Œ DB์— ์ €์žฅ๋œ RefreshToken๊ณผ ์œ ์ €๊ฐ€ ๊ฐฑ์‹ ์„ ์œ„ํ•ด ์š”์ฒญ์— ๋‹ด์•„๋ณด๋‚ธ RefreshToken์ด ๋‹ฌ๋ผ์„œ ํ† ํฐ ๊ฐฑ์‹ ์— ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿผ ์œ ์ €๋Š” ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์•ผ ํ•˜๋ฉฐ, ์žฌ๋กœ๊ทธ์ธ ์‹œ์— DB์˜ RefreshToken๋„ ๊ฐฑ์‹ ๋˜์–ด ๊ณต๊ฒฉ์ž๊ฐ€ ๊ฐ€์ง„ RefreshToken๊ณผ DB์˜ RefreshToken์˜ ์ƒํƒœ๊ฐ€ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
๋–„๋ฌธ์— ํ•ด์ปค๋Š” ๋‹ค์Œ ํ† ํฐ ๊ฐฑ์‹ ์—์„œ ์‹คํŒจํ•˜๊ฒŒ ๋˜๋ฉฐ ์œ ์ €์˜ ๊ถŒํ•œ์„ ์•…์šฉํ•  ์ˆ˜ ์—†๊ฒŒ๋ฉ๋‹ˆ๋‹ค.
 
 
์ด๋ ‡๋“ฏ RTR ๋ฐฉ์‹์œผ๋กœ RefreshToken์„ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜๋ฉด
ํ•ด์ปค๊ฐ€ Refresh Token์„ ํƒˆ์ทจํ•ด๋„, ์‹ค์ œ ํšŒ์›์˜ Access Token์ด ๋งŒ๋ฃŒ๋˜์–ด ํ† ํฐ์„ ๊ฐฑ์‹ ํ•˜๋Š” ์ˆœ๊ฐ„ Redis์˜ Refresh Token์ด ๋ณ€๊ฒฝ๋˜์–ด ํ•ด์ปค๊ฐ€ ํƒˆ์ทจํ•œ ์ด์ „์˜ Refresh Token์€ ๋งŒ๋ฃŒ๋˜์–ด ํ•ด์ปค๋Š” ๋”์ด์ƒ ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰ ๋ฐ›์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
 

๋ฌผ๋ก  ์‹ค์ œ ํšŒ์›์ด ํ† ํฐ ํƒˆ์ทจ ์ดํ›„, ํ•œ๋™์•ˆ ๋กœ๊ทธ์ธ์„ ํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋ฉด ๊ทธ ๋™์•ˆ์€ ํ•ด์ปค๊ฐ€ ๊ณ„์†ํ•ด์„œ ํšŒ์›์˜ ๊ถŒํ•œ์„ ์•…์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๋•Œ๋ฌธ์— HTTPS ์„ค์ •์ด๋‚˜ httpOnly, Secure ์„ค์ •์„ ํ•œ ์ฟ ํ‚ค๋กœ JWT ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•์œผ๋กœ
ํ†ต์‹  ๊ณผ์ •์˜ ์•ˆ์ „์„ฑ์„ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋ฉฐ, ํ† ํฐ ํƒˆ์ทจ ๊ฐ€๋Šฅ์„ฑ์„ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 
 


5. Redis๋„ @Transactional๋กœ ํŠธ๋žœ์žญ์…˜ ์„ค์ •์ด ๊ฐ€๋Šฅํ•œ๊ฐ€์š”?

Spring Data Redis์˜ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์‚ดํŽด๋ณธ ๊ฒฐ๊ณผ
Redis๋Š” ํŠธ๋žœ์žญ์…˜์„ RedisConfig์˜ ์ถ”๊ฐ€์ ์ธ ์„ค์ •์„ ํ†ตํ•ด @Transactional๋กœ JPA์™€ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ฌถ์–ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
 

template.opsForValue().set("thing1", "thing2");

template.opsForValue().get("thing1");

 
ํ•˜์ง€๋งŒ JPA์™€ ๊ฐ™์ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ 1์ฐจ ์บ์‹œ์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์™€ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ๋Š” thing1์ด set() ๋ฉ”์„œ๋“œ๋กœ Redis์— Insert๋œ ํ›„ ํŠธ๋žœ์žญ์…˜์ด EXEC(commit) ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์—
template.opsForValue().get("thing1"); ์˜ ๊ฒฐ๊ณผ๊ฐ€ null์ด ๋ฉ๋‹ˆ๋‹ค.

JPA๋Š” DB์— flush ๋˜์ง€ ์•Š์•„๋„ 1์ฐจ ์บ์‹œ์— ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์„œ,
์กฐํšŒ ์‹œ์— 1์ฐจ ์บ์‹œ์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ Redis๋Š” 1์ฐจ ์บ์‹œ๋ผ๋Š” ๊ฒƒ์ด ์กด์žฌํ•˜์ง€ ์•Š์•„์„œ
DB์— ์ปค๋ฐ‹๋˜๊ธฐ ์ „์—๋Š” ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๋ฐœ์ƒํ•œ ๋ณ€๊ฒฝ์„ ์กฐํšŒํ•ด์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 
์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๊ณต์‹๋ฌธ์„œ์—์„œ ์ฐธ๊ณ ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
https://docs.spring.io/spring-data/redis/reference/redis/transactions.html
 


๊ธ€์„ ๋งˆ์น˜๋ฉฐ

๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉฐ ๋Š๋‚€ ๊ฒƒ์€ ํ•ญ์ƒ 100% ์ข‹์€ ๊ธฐ์ˆ ์ด๋‚˜ ๋ฐฉ๋ฒ•์€ ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๋ง์”€๋“œ๋ฆฐ ๋ถ€๋ถ„ ์ด์™ธ์—๋„ ์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ์•„์‰ฝ๋‹ค๊ณ  ๋Š๋ผ์‹  ๋ถ€๋ถ„๋“ค์ด ์žˆ๋‹ค๋ฉด ๊ผญ ์ถ”๊ฐ€ํ•ด์„œ ๋”์šฑ ๊ฐœ์„ ๋œ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ๊ฐœ๋ฐœ์ž๋กœ ์„ฑ์žฅํ•˜์‹ค ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.
๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!
 
 
 
 
reference
https://puleugo.tistory.com/154
https://kth990303.tistory.com/431

728x90
๋ฐ˜์‘ํ˜•