{"id":2626,"date":"2026-10-20T12:59:18","date_gmt":"2026-10-20T12:59:18","guid":{"rendered":"https:\/\/wayhope.kro.kr\/?p=2626"},"modified":"2026-10-21T13:01:07","modified_gmt":"2026-10-21T13:01:07","slug":"access-token-refresh-token-refresh-token-rotation","status":"publish","type":"post","link":"https:\/\/wayhope.kro.kr\/?p=2626","title":{"rendered":"Access Token, Refresh Token, Refresh Token Rotation"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\uc6f9 \uc11c\ube44\uc2a4\ub098 \uac8c\uc784 \uc11c\ubc84\uc5d0\uc11c \ub85c\uadf8\uc778 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \ub54c \uc911\uc694\ud55c \uac1c\ub150 \uc911 \ud558\ub098\uac00 Access Token\uacfc Refresh Token\uc744 \uc774\uc6a9\ud55c \uc778\uc99d \uad6c\uc870\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc0ac\uc6a9\uc790\uac00 \ub85c\uadf8\uc778\ud558\uba74 \uc11c\ubc84\ub294 \uc778\uc99d \uc815\ubcf4\ub97c \ubc14\ud0d5\uc73c\ub85c \ud1a0\ud070\uc744 \ubc1c\uae09\ud55c\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc774 \ud1a0\ud070\uc744 \uc0ac\uc6a9\ud574 API \uc694\uccad\uc744 \ubcf4\ub0b4\uba70, \ud1a0\ud070\uc774 \ub9cc\ub8cc\ub418\uba74 \uac31\uc2e0 \uc808\ucc28\ub97c \uac70\uce5c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud558\uc9c0\ub9cc Refresh Token\uc744 \uc624\ub7ab\ub3d9\uc548 \ub3d9\uc77c\ud558\uac8c \uc720\uc9c0\ud558\uba74 \ud1a0\ud070 \ud0c8\ucde8 \uc2dc \uacf5\uaca9\uc790\uac00 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0c8\ub85c\uc6b4 Access Token\uc744 \ubc1c\uae09\ubc1b\uc744 \uc218 \uc788\ub2e4. \uc774\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \ub300\ud45c\uc801\uc778 \ubcf4\uc548 \uae30\ubc95\uc774 **Refresh Token Rotation(\ub9ac\ud504\ub808\uc2dc \ud1a0\ud070 \ub85c\ud14c\uc774\uc158)**\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uae00\uc5d0\uc11c\ub294 \uc138 \uac00\uc9c0 \uac1c\ub150\uc758 \uc5ed\ud560\uacfc \ub3d9\uc791 \uc6d0\ub9ac, \uc11c\ubc84 \uad6c\ud604 \uad6c\uc870, \ubcf4\uc548\uc0c1 \uc8fc\uc758\uc810\uc744 \uc0b4\ud3b4\ubcf8\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access Token\uc774\ub780?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token\uc740 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc758 \ubcf4\ud638\ub41c \ub9ac\uc18c\uc2a4\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub3c4\ub85d \ubc1c\uae09\ubc1b\ub294 \uc778\uc99d\u00b7\uc778\uac00\uc6a9 \ud1a0\ud070\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \uac8c\uc784 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \ud50c\ub808\uc774\uc5b4\uc758 \ud504\ub85c\ud544\uc744 \uc870\ud68c\ud558\uac70\ub098 \uc778\ubca4\ud1a0\ub9ac\ub97c \ud655\uc778\ud558\ub824\uba74 \uc11c\ubc84\uc5d0 \uc790\uc2e0\uc758 \uc694\uccad \uad8c\ud55c\uc744 \uc99d\uba85\ud574\uc57c \ud55c\ub2e4. \uc774\ub54c Access Token\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/api\/player\/inventory HTTP\/1.1\nHost: api.example.com\nAuthorization: Bearer ACCESS_TOKEN<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc11c\ubc84\ub294 \uc804\ub2ec\ubc1b\uc740 \ud1a0\ud070\uc744 \uac80\uc99d\ud55c \ub4a4 \uc720\ud6a8\uc131, \ub9cc\ub8cc \uc5ec\ubd80, \uad8c\ud55c \ub4f1\uc744 \ud655\uc778\ud558\uace0 \uc694\uccad\uc744 \ucc98\ub9ac\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token\uc758 \uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc9e7\uc740 \uc218\uba85: \ud0c8\ucde8\ub418\ub354\ub77c\ub3c4 \uacf5\uaca9\uc790\uac00 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \uc904\uc778\ub2e4.<\/li>\n\n\n\n<li>API \uc811\uadfc: \ubcf4\ud638\ub41c \ub9ac\uc18c\uc2a4\uc5d0 \ub300\ud55c \uc694\uccad\uc744 \uc778\uc99d\u00b7\uc778\uac00\ud558\ub294 \ub370 \uc0ac\uc6a9\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uad8c\ud55c \uc81c\ud55c: \ud2b9\uc815 \uc0ac\uc6a9\uc790, \ub9ac\uc18c\uc2a4, \uad8c\ud55c \ubc94\uc704\uc5d0 \ub9de\uac8c \uc81c\ud55c\ud560 \uc218 \uc788\ub2e4.<\/li>\n\n\n\n<li>\ub9cc\ub8cc: \ub9cc\ub8cc\ub41c \ud1a0\ud070\uc740 \uc77c\ubc18\uc801\uc778 API \uc778\uc99d\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token\uc740 JWT \ud615\uc2dd\uc77c \uc218\ub3c4 \uc788\uace0, \uc11c\ubc84\uac00 \uc800\uc7a5\uc18c\uc5d0\uc11c \uc870\ud68c\ud558\ub294 \ubd88\ud22c\uba85\ud55c \ubb38\uc790\uc5f4(opaque token)\uc77c \uc218\ub3c4 \uc788\ub2e4. JWT\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uace0 \ud574\uc11c \uc790\ub3d9\uc73c\ub85c \uc548\uc804\ud574\uc9c0\ub294 \uac83\uc740 \uc544\ub2c8\ub2e4. \uc11c\uba85, \ub9cc\ub8cc \uc2dc\uac04, \ubc1c\uae09\uc790, \ub300\uc0c1 \uc11c\ubc84 \ub4f1\uc758 \uac80\uc99d\uc774 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Refresh Token\uc774\ub780?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token\uc740 Access Token\uc774 \ub9cc\ub8cc\ub418\uc5c8\uc744 \ub54c \uc0c8\ub85c\uc6b4 Access Token\uc744 \ubc1c\uae09\ubc1b\uae30 \uc704\ud574 \uc0ac\uc6a9\ud558\ub294 \uc7a5\uae30 \uc778\uc99d \uc790\uaca9 \uc99d\uba85\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token\uc758 \uc218\uba85\uc744 \uc9e7\uac8c \uc124\uc815\ud558\uba74 \ud0c8\ucde8 \uc704\ud5d8\uc744 \uc904\uc77c \uc218 \uc788\uc9c0\ub9cc, \uc0ac\uc6a9\uc790\uac00 \uc9e7\uc740 \uc8fc\uae30\ub9c8\ub2e4 \ub2e4\uc2dc \ub85c\uadf8\uc778\ud574\uc57c \ud558\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token\uc740 \uc774 \ubb38\uc81c\ub97c \ud574\uacb0\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ub2e4\uc74c\uacfc \uac19\uc740 \uc815\ucc45\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud56d\ubaa9<\/th><th>Access Token<\/th><th>Refresh Token<\/th><\/tr><\/thead><tbody><tr><td>\uc8fc\uc694 \ubaa9\uc801<\/td><td>API \uc811\uadfc<\/td><td>Access Token \uac31\uc2e0<\/td><\/tr><tr><td>\uc608\uc2dc \uc218\uba85<\/td><td>10\ubd84<\/td><td>7\uc77c<\/td><\/tr><tr><td>\uc0ac\uc6a9 \ube48\ub3c4<\/td><td>API \uc694\uccad\ub9c8\ub2e4<\/td><td>\uac31\uc2e0 \uc2dc\uc810<\/td><\/tr><tr><td>\uac80\uc99d \uc704\uce58<\/td><td>API \uc11c\ubc84 \ub610\ub294 \ub9ac\uc18c\uc2a4 \uc11c\ubc84<\/td><td>\uc778\uc99d \uc11c\ubc84<\/td><\/tr><tr><td>\ud0c8\ucde8 \uc2dc \uc704\ud5d8<\/td><td>\uc81c\ud55c\ub41c \uc2dc\uac04 \ub3d9\uc548 API \uc811\uadfc<\/td><td>\uc0c8 Access Token \ubc1c\uae09 \uac00\ub2a5<\/td><\/tr><tr><td>\uc800\uc7a5 \ubc29\uc2dd<\/td><td>\uba54\ubaa8\ub9ac \ub4f1<\/td><td>\ubcf4\uc548\uc774 \ud655\ubcf4\ub41c \uc800\uc7a5\uc18c<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\ud45c\uc758 \uc218\uba85\uc740 \uc124\uba85\uc744 \uc704\ud55c \uc608\uc2dc\uc774\uba70, \uc2e4\uc81c \uc218\uba85\uc740 \uc11c\ube44\uc2a4\uc758 \ubcf4\uc548 \uc815\ucc45\uc5d0 \ub530\ub77c \uacb0\uc815\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud575\uc2ec\uc740 Refresh Token\uc744 \uc77c\ubc18 API \uc694\uccad\uc5d0 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\ub294 \uac83\uc774\ub2e4. Refresh Token\uc740 \uac31\uc2e0 \uc5d4\ub4dc\ud3ec\uc778\ud2b8\uc5d0\ub9cc \uc804\ub2ec\ud558\uace0, \uc11c\ubc84\ub294 \uc774\ub97c \uac80\uc99d\ud55c \ub4a4 \uc0c8\ub85c\uc6b4 Access Token\uc744 \ubc1c\uae09\ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access Token\uacfc Refresh Token\uc758 \uc804\uccb4 \ub3d9\uc791 \uad6c\uc870<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ud074\ub77c\uc774\uc5b8\ud2b8 \ub85c\uadf8\uc778<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc544\uc774\ub514\u00b7\ube44\ubc00\ubc88\ud638 \ub610\ub294 \ub2e4\ub978 \uc778\uc99d \uc218\ub2e8<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc778\uc99d \uc11c\ubc84<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc0ac\uc6a9\uc790 \uc778\uc99d \ud6c4 \ub450 \ud1a0\ud070 \ubc1c\uae09<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">API \uc694\uccad\uc5d0 \uc0ac\uc6a9<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc9e7\uc740 \uc218\uba85<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud1a0\ud070 \uac31\uc2e0\uc5d0 \uc0ac\uc6a9<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc0c1\ub300\uc801\uc73c\ub85c \uae34 \uc218\uba85<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token \ub9cc\ub8cc<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">API \uc694\uccad \uc2e4\ud328 \ub610\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ub9cc\ub8cc \uac10\uc9c0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token\uc73c\ub85c \uac31\uc2e0 \uc694\uccad<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc11c\ubc84\uac00 Refresh Token \uac80\uc99d<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc0c8 Access Token \ubc1c\uae09<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rotation \uc801\uc6a9 \uc2dc \uc0c8 Refresh Token\ub3c4 \ud568\uaed8 \ubc1c\uae09<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uad6c\uc870\ub97c \uc0ac\uc6a9\ud558\uba74 \uc0ac\uc6a9\uc790\uac00 \ub9e4\ubc88 \ub85c\uadf8\uc778\ud558\uc9c0 \uc54a\uace0\ub3c4 \uc11c\ube44\uc2a4\ub97c \uacc4\uc18d \uc774\uc6a9\ud560 \uc218 \uc788\ub2e4. \ub2e4\ub9cc Refresh Token\uc774 \ub9cc\ub8cc\ub418\uac70\ub098 \ud3d0\uae30\ub418\uba74 \ub2e4\uc2dc \uc778\uc99d\ud574\uc57c \ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Refresh Token Rotation\uc774\ub780?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token Rotation\uc740 Refresh Token\uc744 \ud55c \ubc88 \uc0ac\uc6a9\ud560 \ub54c\ub9c8\ub2e4 \uc0c8\ub85c\uc6b4 Refresh Token\uc73c\ub85c \uad50\uccb4\ud558\uace0, \uae30\uc874 \ud1a0\ud070\uc744 \ubb34\ud6a8\ud654\ud558\ub294 \ubcf4\uc548 \uae30\ubc95\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc77c\ubc18\uc801\uc778 Refresh Token \ubc29\uc2dd\uacfc Rotation \ubc29\uc2dd\uc758 \ucc28\uc774\ub294 \uae30\uc874 \ud1a0\ud070\uc744 \uacc4\uc18d \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294\uc9c0\uc5d0 \uc788\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\uc77c\ubc18 Refresh Token \ubc29\uc2dd<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token A<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token B<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token A\uac00 \ub9cc\ub8cc\ub418\uac70\ub098 \ud3d0\uae30\ub420 \ub54c\uae4c\uc9c0 \ubc18\ubcf5\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Refresh Token Rotation \ubc29\uc2dd<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token A<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud3d0\uae30<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token B<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Access Token B<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\uc74c \uac31\uc2e0\uc5d0\ub294 B\ub97c \uc0ac\uc6a9\ud558\uace0, \uc0c8\ub85c\uc6b4 Refresh Token C\ub97c \ubc1c\uae09\ubc1b\ub294\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token A\ub97c \uc0ac\uc6a9\ud574 \uac31\uc2e0\uc5d0 \uc131\uacf5\ud558\uba74 \uc11c\ubc84\ub294 \uc0c8\ub85c\uc6b4 \ud1a0\ud070 \uc30d\uc744 \ubc1c\uae09\ud55c\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uae30\uc874 Refresh Token A: \uc0ac\uc6a9 \ubd88\uac00<\/li>\n\n\n\n<li>\uc0c8\ub85c\uc6b4 Access Token B: API \uc694\uccad\uc5d0 \uc0ac\uc6a9<\/li>\n\n\n\n<li>\uc0c8\ub85c\uc6b4 Refresh Token B: \ub2e4\uc74c \uac31\uc2e0\uc5d0 \uc0ac\uc6a9<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774\ud6c4 Refresh Token B\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e4\uc2dc \uc0c8\ub85c\uc6b4 \ud1a0\ud070\uc73c\ub85c \uad50\uccb4\ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\uc65c \uae30\uc874 \ud1a0\ud070\uc744 \ud3d0\uae30\ud558\ub294\uac00?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\ud1a0\ud070\uc774 \ud0c8\ucde8\ub418\uc5c8\uc744 \ub54c\ub97c \uc0dd\uac01\ud574 \ubcf4\uc790.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc77c\ubc18\uc801\uc778 \ubc29\uc2dd\uc5d0\uc11c\ub294 \uacf5\uaca9\uc790\uac00 \ud0c8\ucde8\ud55c Refresh Token\uc744 \ubc18\ubcf5\ud574\uc11c \uc0ac\uc6a9\ud574 \uc0c8\ub85c\uc6b4 Access Token\uc744 \ubc1c\uae09\ubc1b\uc744 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rotation \ubc29\uc2dd\uc5d0\uc11c\ub294 \uc815\uc0c1 \uc0ac\uc6a9\uc790\uac00 \uba3c\uc800 \ud1a0\ud070\uc744 \uac31\uc2e0\ud574 \uae30\uc874 \ud1a0\ud070\uc744 \ud3d0\uae30\ud588\ub2e4\uba74, \uacf5\uaca9\uc790\uac00 \ud0c8\ucde8\ud55c \uc774\uc804 \ud1a0\ud070\uc744 \uc0ac\uc6a9\ud558\ub824\ub294 \uc21c\uac04 \uc11c\ubc84\uac00 \uc7ac\uc0ac\uc6a9\uc744 \uac10\uc9c0\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc11c\ubc84\ub294 \uae30\uc874 \ud1a0\ud070\uacfc \uc0c8 \ud1a0\ud070\uc758 \uad00\uacc4\ub97c \ucd94\uc801\ud574 \ud574\ub2f9 \ud1a0\ud070 \uacc4\uc5f4(token family)\uc744 \uc2dd\ubcc4\ud558\uace0, \ud544\uc694\ud558\uba74 \ud604\uc7ac \uc720\ud6a8\ud55c Refresh Token\uae4c\uc9c0 \ud3d0\uae30\ud55c\ub2e4. \ub2e4\ub9cc \uc11c\ubc84\ub294 \uc815\uc0c1 \uc0ac\uc6a9\uc790\uc640 \uacf5\uaca9\uc790 \uc911 \ub204\uac00 \uc774\uc804 \ud1a0\ud070\uc744 \uc0ac\uc6a9\ud588\ub294\uc9c0 \ud56d\uc0c1 \ud310\ubcc4\ud560 \uc218 \uc5c6\uc73c\ubbc0\ub85c, \uc815\uc0c1 \uc0ac\uc6a9\uc790\ub3c4 \ub2e4\uc2dc \ub85c\uadf8\uc778\ud574\uc57c \ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Refresh Token Rotation\uc758 \ub3d9\uc791 \uacfc\uc815<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\ub85c\uadf8\uc778 \ubc0f \ucd5c\ucd08 \ud1a0\ud070 \ubc1c\uae09 \uc11c\ubc84\uac00 Access Token A\uc640 Refresh Token A\ub97c \ubc1c\uae09\ud55c\ub2e4. \uc11c\ubc84\ub294 Refresh Token\uc758 \ud574\uc2dc, \ub9cc\ub8cc \uc2dc\uac04, \uc0ac\uc6a9\uc790 ID, \ud1a0\ud070 \uacc4\uc5f4 \ub4f1\uc758 \uc815\ubcf4\ub97c \uc800\uc7a5\ud55c\ub2e4.<\/li>\n\n\n\n<li>Access Token \ub9cc\ub8cc \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 Refresh Token A\ub97c \uc778\uc99d \uc11c\ubc84\uc758 \uac31\uc2e0 \uc5d4\ub4dc\ud3ec\uc778\ud2b8\ub85c \uc804\ub2ec\ud55c\ub2e4.<\/li>\n\n\n\n<li>Refresh Token \uac80\uc99d \uc11c\ubc84\ub294 \ud1a0\ud070\uc758 \uc874\uc7ac \uc5ec\ubd80, \ud574\uc2dc \uc77c\uce58, \ub9cc\ub8cc \uc5ec\ubd80, \ud3d0\uae30 \uc5ec\ubd80, \uc0ac\uc6a9\uc790 \uc138\uc158 \uc0c1\ud0dc \ub4f1\uc744 \uac80\uc99d\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uae30\uc874 \ud1a0\ud070 \ud3d0\uae30 \ubc0f \uc0c8 \ud1a0\ud070 \ubc1c\uae09 \uc11c\ubc84\ub294 Refresh Token A\ub97c \uc0ac\uc6a9 \uc644\ub8cc \uc0c1\ud0dc\ub85c \ubcc0\uacbd\ud558\uace0 Access Token B\uc640 Refresh Token B\ub97c \ubc1c\uae09\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uc774\uc804 \ud1a0\ud070 \uc7ac\uc0ac\uc6a9 \uac10\uc9c0 \uc774\ubbf8 \ud3d0\uae30\ub41c Refresh Token A\uac00 \ub2e4\uc2dc \uc81c\ucd9c\ub418\uba74 \uc7ac\uc0ac\uc6a9 \uac00\ub2a5\uc131\uc744 \uac10\uc9c0\ud55c\ub2e4. \uc815\ucc45\uc5d0 \ub530\ub77c \ud574\ub2f9 \ud1a0\ud070 \uacc4\uc5f4\uc758 \ud65c\uc131 Refresh Token\uc744 \ubaa8\ub450 \ud3d0\uae30\ud558\uace0 \uc7ac\uc778\uc99d\uc744 \uc694\uad6c\ud55c\ub2e4.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uad6c\uc870\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub2e8\uc21c\ud788 \ud1a0\ud070 \ubb38\uc790\uc5f4\uc744 \uad50\uccb4\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4. \ud1a0\ud070\uc758 \ubc1c\uae09 \uc774\ub825\uacfc \ud3d0\uae30 \uc0c1\ud0dc\ub97c \uc11c\ubc84\uac00 \uad00\ub9ac\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc11c\ubc84\ub294 Refresh Token\uc744 \uc5b4\ub5bb\uac8c \uad00\ub9ac\ud558\ub294\uac00?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">JWT Access Token\uc740 \uc11c\uba85\uacfc \ud074\ub808\uc784\uc744 \uac80\uc99d\ud574 \ubcc4\ub3c4\uc758 DB \uc870\ud68c \uc5c6\uc774 \ucc98\ub9ac\ud558\ub3c4\ub85d \uc124\uacc4\ud560 \uc218 \uc788\ub2e4. \ubc18\uba74 Rotation\uc744 \uc801\uc6a9\ud55c Refresh Token\uc740 \uc7ac\uc0ac\uc6a9 \uac10\uc9c0\uc640 \ud3d0\uae30\ub97c \uc704\ud574 \uc11c\ubc84 \uce21 \uc0c1\ud0dc \uad00\ub9ac\uac00 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 MySQL\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud14c\uc774\ube14\uc744 \ub458 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE refresh_tokens (\n    id BIGINT AUTO_INCREMENT PRIMARY KEY,\n\n    user_id BIGINT NOT NULL,\n\n    -- \uc6d0\ubcf8 \ud1a0\ud070\uc774 \uc544\ub2cc \ud574\uc2dc\uac12\n    token_hash CHAR(64) NOT NULL UNIQUE,\n\n    -- \uac19\uc740 \ub85c\uadf8\uc778 \uc138\uc158\uc5d0\uc11c \ubc1c\uae09\ub41c \ud1a0\ud070\uc758 \uacc4\uc5f4\n    token_family_id CHAR(36) NOT NULL,\n\n    -- \uc774\uc804 \ud1a0\ud070\uacfc \ub2e4\uc74c \ud1a0\ud070\uc758 \uad00\uacc4\n    replaced_by_token_id BIGINT NULL,\n\n    expires_at DATETIME NOT NULL,\n    revoked_at DATETIME NULL,\n    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n\n    INDEX idx_user_id (user_id),\n    INDEX idx_token_family_id (token_family_id),\n\n    FOREIGN KEY (replaced_by_token_id)\n        REFERENCES refresh_tokens(id)\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uac01 \ud544\ub4dc\uc758 \uc5ed\ud560\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud544\ub4dc<\/th><th>\uc5ed\ud560<\/th><\/tr><\/thead><tbody><tr><td><code>user_id<\/code><\/td><td>\ud1a0\ud070 \uc18c\uc720\uc790 \uc2dd\ubcc4<\/td><\/tr><tr><td><code>token_hash<\/code><\/td><td>\ud1a0\ud070 \uc6d0\ubb38 \ub300\uc2e0 \ud574\uc2dc\ub97c \uc800\uc7a5\ud574 \uc720\ucd9c \ud53c\ud574 \uac10\uc18c<\/td><\/tr><tr><td><code>token_family_id<\/code><\/td><td>\uac19\uc740 \ub85c\uadf8\uc778 \uc138\uc158\uc758 \ud1a0\ud070 \uacc4\uc5f4 \uc2dd\ubcc4<\/td><\/tr><tr><td><code>replaced_by_token_id<\/code><\/td><td>\uae30\uc874 \ud1a0\ud070\uc744 \ub300\uccb4\ud55c \ud1a0\ud070 \ucd94\uc801<\/td><\/tr><tr><td><code>expires_at<\/code><\/td><td>\ud1a0\ud070 \ub9cc\ub8cc \uc2dc\uac01<\/td><\/tr><tr><td><code>revoked_at<\/code><\/td><td>\ud1a0\ud070 \ud3d0\uae30 \uc2dc\uac01<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><code>replaced_by_token_id<\/code>\ub294 \uc0c8 \ud1a0\ud070\uacfc \uc774\uc804 \ud1a0\ud070\uc758 \uad00\uacc4\ub97c \ucd94\uc801\ud558\uae30 \uc704\ud55c \uc120\ud0dd\uc801 \uc124\uacc4\ub2e4. \ud1a0\ud070 \uacc4\uc5f4 ID\uc640 \ud3d0\uae30 \uc0c1\ud0dc\ub9cc\uc73c\ub85c \uad00\ub9ac\ud558\ub294 \uad6c\ud604\ub3c4 \uac00\ub2a5\ud558\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh Token \uc6d0\ubb38\uc744 DB\uc5d0 \uadf8\ub300\ub85c \uc800\uc7a5\ud558\uc9c0 \uc54a\ub294 \uac83\uc774 \ubc14\ub78c\uc9c1\ud558\ub2e4. \uc11c\ubc84\ub294 \ucda9\ubd84\ud788 \uc548\uc804\ud55c \ubb34\uc791\uc704 \ud1a0\ud070\uc744 \uc0dd\uc131\ud558\uace0, \uc6d0\ubb38\uc744 \ud574\uc2dc\ud574 \uc800\uc7a5\ud55c \ub4a4 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uc6d0\ubb38\uc744 \ud55c \ubc88 \uc804\ub2ec\ud55c\ub2e4. \uc774\ud6c4 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \ubcf4\ub0b8 \uc6d0\ubb38\uc744 \ub3d9\uc77c\ud55c \ubc29\uc2dd\uc73c\ub85c \ud574\uc2dc\ud574 DB\uc758 \uac12\uacfc \ube44\uad50\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e8, \ud574\uc2dc \uc800\uc7a5\ub9cc\uc73c\ub85c \ud1a0\ud070 \ud0c8\ucde8 \ubb38\uc81c\uac00 \ud574\uacb0\ub418\ub294 \uac83\uc740 \uc544\ub2c8\ub2e4. \uc804\uc1a1 \uad6c\uac04 \uc554\ud638\ud654, \ud074\ub77c\uc774\uc5b8\ud2b8 \uc800\uc7a5\uc18c \ubcf4\ud638, \ub9cc\ub8cc \ubc0f \ud3d0\uae30 \uc815\ucc45\uc774 \ud568\uaed8 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Node.js + TypeScript\ub85c \uad6c\ud604\ud558\ub294 Rotation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\uc74c\uc740 Express, MySQL, TypeScript\ub97c \uc0ac\uc6a9\ud558\ub294 \uc11c\ubc84\uc758 \ud575\uc2ec \uac31\uc2e0 \ub85c\uc9c1\uc774\ub2e4. \ud1a0\ud070 \uc0dd\uc131\uacfc \ud574\uc2dc \ud568\uc218\ub294 \ubcc4\ub3c4\uc758 \uc720\ud2f8\ub9ac\ud2f0\ub85c \ubd84\ub9ac\ud588\ub2e4\uace0 \uac00\uc815\ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Refresh Token \uac31\uc2e0 API<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Router } from \"express\";\nimport type { Request, Response } from \"express\";\nimport crypto from \"node:crypto\";\nimport jwt from \"jsonwebtoken\";\nimport { pool } from \".\/database\";\n\nconst router = Router();\n\nfunction hashToken(token: string): string {\n  return crypto\n    .createHash(\"sha256\")\n    .update(token)\n    .digest(\"hex\");\n}\n\nfunction createRefreshToken(): string {\n  \/\/ 256\ube44\ud2b8\uc758 \uc554\ud638\ud559\uc801\uc73c\ub85c \uc548\uc804\ud55c \ub09c\uc218\n  return crypto.randomBytes(32).toString(\"base64url\");\n}\n\nfunction createAccessToken(userId: number): string {\n  return jwt.sign(\n    { sub: String(userId) },\n    process.env.JWT_ACCESS_SECRET!,\n    { expiresIn: \"10m\" }\n  );\n}\n\nrouter.post(\n  \"\/auth\/refresh\",\n  async (req: Request, res: Response) =&gt; {\n    const refreshToken = req.body.refreshToken;\n\n    if (\n      typeof refreshToken !== \"string\" ||\n      refreshToken.length === 0\n    ) {\n      return res.status(400).json({\n        message: \"Refresh token is required\",\n      });\n    }\n\n    const connection = await pool.getConnection();\n\n    try {\n      await connection.beginTransaction();\n\n      const tokenHash = hashToken(refreshToken);\n\n      \/\/ \ud1a0\ud070 \ud589\uc744 \uc7a0\uac00 \ub3d9\uc2dc\uc5d0 \ubc1c\uc0dd\ud558\ub294 \uac31\uc2e0\uc744 \uc81c\uc5b4\ud55c\ub2e4.\n      const &#91;rows] = await connection.execute&lt;any&#91;]&gt;(\n        `SELECT *\n         FROM refresh_tokens\n         WHERE token_hash = ?\n         FOR UPDATE`,\n        &#91;tokenHash]\n      );\n\n      const storedToken = rows&#91;0];\n\n      if (!storedToken) {\n        await connection.rollback();\n\n        return res.status(401).json({\n          message: \"Invalid refresh token\",\n        });\n      }\n\n      \/\/ \uc774\ubbf8 \ud3d0\uae30\ub41c \ud1a0\ud070\uc774 \ub2e4\uc2dc \uc0ac\uc6a9\ub418\uc5c8\ub2e4.\n      if (storedToken.revoked_at) {\n        \/\/ \uac19\uc740 \ud1a0\ud070 \uacc4\uc5f4\uc758 \ud65c\uc131 \ud1a0\ud070\uc744 \ubaa8\ub450 \ud3d0\uae30\ud55c\ub2e4.\n        await connection.execute(\n          `UPDATE refresh_tokens\n           SET revoked_at = UTC_TIMESTAMP()\n           WHERE token_family_id = ?\n             AND revoked_at IS NULL`,\n          &#91;storedToken.token_family_id]\n        );\n\n        await connection.commit();\n\n        return res.status(401).json({\n          message: \"Refresh token reuse detected\",\n        });\n      }\n\n      if (\n        new Date(storedToken.expires_at).getTime()\n        &lt;= Date.now()\n      ) {\n        await connection.rollback();\n\n        return res.status(401).json({\n          message: \"Refresh token expired\",\n        });\n      }\n\n      const newRefreshToken = createRefreshToken();\n      const newRefreshTokenHash = hashToken(newRefreshToken);\n\n      const accessToken = createAccessToken(\n        storedToken.user_id\n      );\n\n      \/\/ \uc774\uc804 \ud1a0\ud070 \ud3d0\uae30\n      await connection.execute(\n        `UPDATE refresh_tokens\n         SET revoked_at = UTC_TIMESTAMP()\n         WHERE id = ?\n           AND revoked_at IS NULL`,\n        &#91;storedToken.id]\n      );\n\n      \/\/ \uc0c8 Refresh Token \uc800\uc7a5\n      const &#91;insertResult] = await connection.execute&lt;any&gt;(\n        `INSERT INTO refresh_tokens (\n           user_id,\n           token_hash,\n           token_family_id,\n           expires_at\n         )\n         VALUES (\n           ?, ?, ?,\n           DATE_ADD(UTC_TIMESTAMP(), INTERVAL 7 DAY)\n         )`,\n        &#91;\n          storedToken.user_id,\n          newRefreshTokenHash,\n          storedToken.token_family_id,\n        ]\n      );\n\n      \/\/ \uc774\uc804 \ud1a0\ud070\uc774 \uc5b4\ub5a4 \ud1a0\ud070\uc73c\ub85c \uad50\uccb4\ub418\uc5c8\ub294\uc9c0 \uae30\ub85d\n      await connection.execute(\n        `UPDATE refresh_tokens\n         SET replaced_by_token_id = ?\n         WHERE id = ?`,\n        &#91;insertResult.insertId, storedToken.id]\n      );\n\n      await connection.commit();\n\n      return res.json({\n        accessToken,\n        refreshToken: newRefreshToken,\n        tokenType: \"Bearer\",\n        expiresIn: 600,\n      });\n    } catch (error) {\n      await connection.rollback();\n\n      return res.status(500).json({\n        message: \"Token refresh failed\",\n      });\n    } finally {\n      connection.release();\n    }\n  }\n);\n\nexport default router;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uad50\uc721\uc6a9 \ud575\uc2ec \uc608\uc81c\ub2e4. \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0\uc11c\ub294 MySQL \ub4dc\ub77c\uc774\ubc84 \ud0c0\uc785, \uc624\ub958 \ucc98\ub9ac, \ud1a0\ud070 \ud328\ubc00\ub9ac \uc815\ucc45, \ucfe0\ud0a4 \ucc98\ub9ac, \ub85c\uadf8\uc544\uc6c3\uacfc \uc138\uc158 \ud3d0\uae30 \ub85c\uc9c1 \ub4f1\uc744 \ubcf4\uc644\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ucf54\ub4dc\uc5d0\uc11c \uc911\uc694\ud55c \ubd80\ubd84<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\ud1a0\ud070 \ud574\uc2dc \uc800\uc7a5<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const tokenHash = hashToken(refreshToken);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc804\ub2ec\ud55c \ud1a0\ud070 \uc6d0\ubb38\uc744 DB\uc5d0 \uc800\uc7a5\ud558\ub294 \ub300\uc2e0 \ud574\uc2dc\ub97c \uc870\ud68c \ud0a4\ub85c \uc0ac\uc6a9\ud55c\ub2e4. Refresh Token\uc740 \ucda9\ubd84\ud55c \uc5d4\ud2b8\ub85c\ud53c\ub97c \uac00\uc9c4 \ub09c\uc218\uc5ec\uc57c \ud558\uba70, \ube44\ubc00\ubc88\ud638\ucc98\ub7fc \ub0ae\uc740 \uc5d4\ud2b8\ub85c\ud53c\ub97c \uac00\uc9c4 \uac12\uacfc\ub294 \ud2b9\uc131\uc774 \ub2e4\ub974\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud2b8\ub79c\uc7ad\uc158\uacfc \ud589 \uc7a0\uae08<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT *\nFROM refresh_tokens\nWHERE token_hash = ?\nFOR UPDATE;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc5ec\ub7ec \uc694\uccad\uc774 \ub3d9\uc77c\ud55c Refresh Token\uc73c\ub85c \ub3d9\uc2dc\uc5d0 \uac31\uc2e0\uc744 \uc2dc\ub3c4\ud560 \uc218 \uc788\ub2e4. \ud589 \uc7a0\uae08\uacfc \ud2b8\ub79c\uc7ad\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \uae30\uc874 \ud1a0\ud070 \ud3d0\uae30\uc640 \uc0c8 \ud1a0\ud070 \ubc1c\uae09\uc744 \uc6d0\uc790\uc801\uc73c\ub85c \ucc98\ub9ac\ud558\ub294 \ub370 \ub3c4\uc6c0\uc774 \ub41c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e8, \uc2e4\uc81c \ub3d9\uc2dc \uc694\uccad \ucc98\ub9ac\uc5d0\uc11c\ub294 \ub450 \ubc88\uc9f8 \uc694\uccad\uc774 \uc7a0\uae08 \ud574\uc81c \ud6c4 \ud3d0\uae30\ub41c \ud1a0\ud070\uc744 \uc77d\uace0 \uc7ac\uc0ac\uc6a9 \uac10\uc9c0 \uc815\ucc45\uc744 \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4. \ubaa8\ubc14\uc77c \ub124\ud2b8\uc6cc\ud06c \uc7ac\uc2dc\ub3c4\ub098 \uc5ec\ub7ec API \uc694\uccad\uc758 \ub3d9\uc2dc \uac31\uc2e0\ub3c4 \uace0\ub824\ud574\uc57c \ud55c\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uac31\uc2e0 \uc694\uccad\uc744 \ub2e8\uc77c\ud654\ud558\uace0, \uc11c\ubc84\uc5d0\uc11c\ub3c4 \uc6d0\uc790\uc801\uc778 \uc0c1\ud0dc \uc804\uc774\ub97c \ubcf4\uc7a5\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud1a0\ud070 \uacc4\uc5f4 \uc804\uccb4 \ud3d0\uae30<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE refresh_tokens\nSET revoked_at = UTC_TIMESTAMP()\nWHERE token_family_id = ?\n  AND revoked_at IS NULL;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774\ubbf8 \ud3d0\uae30\ub41c \ud1a0\ud070\uc774 \ub2e4\uc2dc \uc0ac\uc6a9\ub418\uc5c8\ub2e4\uba74 \ud574\ub2f9 \ub85c\uadf8\uc778 \uc138\uc158\uc758 \ud65c\uc131 Refresh Token\uae4c\uc9c0 \ubb34\ud6a8\ud654\ud55c\ub2e4. \uacf5\uaca9\uc790\uac00 \ud0c8\ucde8\ud55c \ud1a0\ud070\uc73c\ub85c \uacc4\uc18d \uc778\uc99d\uc744 \uc720\uc9c0\ud558\ub294 \uac83\uc744 \ucc28\ub2e8\ud558\uae30 \uc704\ud55c \uc870\uce58\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\ub9cc \uc774 \uc608\uc81c\uc5d0\ub294 \uba87 \uac00\uc9c0 \ucd94\uac00 \ubcf4\uc644\uc774 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ub9cc\ub8cc\ub41c \ud1a0\ud070\uc758 \uc7ac\uc0ac\uc6a9\uacfc \uc815\uc0c1\uc801\uc778 \ud3d0\uae30 \ud1a0\ud070\uc758 \uc7ac\uc0ac\uc6a9\uc744 \uad6c\ubd84\ud558\ub294 \uc815\ucc45<\/li>\n\n\n\n<li>\uc0c8 \ud1a0\ud070\uc744 \ubc1c\uae09\ud55c \ub4a4 \uc751\ub2f5\uc774 \uc720\uc2e4\ub41c \uacbd\uc6b0\uc758 \uc7ac\uc2dc\ub3c4 \ucc98\ub9ac<\/li>\n\n\n\n<li>Access Token \ubc1c\uae09\uacfc DB \ud2b8\ub79c\uc7ad\uc158 \uc0ac\uc774\uc758 \uc2e4\ud328 \ucc98\ub9ac<\/li>\n\n\n\n<li>\ub85c\uadf8\uc544\uc6c3, \ube44\ubc00\ubc88\ud638 \ubcc0\uacbd, \uacc4\uc815 \uc815\uc9c0 \uc2dc \ud1a0\ud070 \uacc4\uc5f4 \ud3d0\uae30<\/li>\n\n\n\n<li>Refresh Token\uc758 \uc808\ub300 \ucd5c\ub300 \uc218\uba85\uacfc \ube44\ud65c\uc131 \ub9cc\ub8cc \uc815\ucc45<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ud2b9\ud788 \uc0c8 \ud1a0\ud070\uc744 \ubc1c\uae09\ud55c \ub4a4 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc751\ub2f5\uc744 \ubc1b\uc9c0 \ubabb\ud558\uba74 \uae30\uc874 \ud1a0\ud070\uc740 \uc774\ubbf8 \ud3d0\uae30\ub418\uc5c8\uc744 \uc218 \uc788\ub2e4. \uc774 \uacbd\uc6b0 \ubb34\uc870\uac74 \uac19\uc740 \ud1a0\ud070\uc73c\ub85c \uc7ac\uc2dc\ub3c4\ud558\uba74 \uc7ac\uc0ac\uc6a9 \uac10\uc9c0\ub85c \ucc98\ub9ac\ub420 \uc218 \uc788\ub2e4. \ubb34\uc81c\ud55c \uc7ac\uc0ac\uc6a9 \ud5c8\uc6a9 \ub300\uc2e0 \uc81c\ud55c\ub41c \uc7ac\uc2dc\ub3c4 \uc815\ucc45\uc774\ub098 \uc7ac\uc778\uc99d\uc744 \uace0\ub824\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c\ub294 \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud558\ub294\uac00?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ud074\ub77c\uc774\uc5b8\ud2b8\ub294 Access Token\uc744 API \uc694\uccad\uc5d0 \uc0ac\uc6a9\ud558\uace0, \ub9cc\ub8cc \uc2dc Refresh Token\uc73c\ub85c \uac31\uc2e0\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function refreshAccessToken(\n  refreshToken: string\n) {\n  const response = await fetch(\"\/auth\/refresh\", {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application\/json\",\n    },\n    body: JSON.stringify({ refreshToken }),\n  });\n\n  if (!response.ok) {\n    \/\/ \uc7ac\uc778\uc99d\uc774 \ud544\uc694\ud55c \uc0c1\ud0dc\n    throw new Error(\"Re-authentication required\");\n  }\n\n  const tokens = await response.json();\n\n  \/\/ \uae30\uc874 \ud1a0\ud070\uc744 \uc0c8 \ud1a0\ud070\uc73c\ub85c \uad50\uccb4\n  return {\n    accessToken: tokens.accessToken,\n    refreshToken: tokens.refreshToken,\n  };\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc2e4\uc81c \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \ubc18\ud658\ub41c \uc0c8 Refresh Token\uc744 \uc548\uc804\ud558\uac8c \uc800\uc7a5\ud558\uace0, \uae30\uc874 Refresh Token\uc744 \ub354 \uc774\uc0c1 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6f9 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c\ub294 Refresh Token\uc744 <code>HttpOnly<\/code>, <code>Secure<\/code>, \uc801\uc808\ud55c <code>SameSite<\/code> \uc18d\uc131\uc744 \uc801\uc6a9\ud55c \ucfe0\ud0a4\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\uc2dd\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4. \ucfe0\ud0a4 \uae30\ubc18 \uc778\uc99d\uc5d0\uc11c\ub294 CSRF \ubc29\uc5b4\ub3c4 \ud568\uaed8 \uc124\uacc4\ud574\uc57c \ud55c\ub2e4. \ubaa8\ubc14\uc77c \uc571\uc5d0\uc11c\ub294 \uc6b4\uc601\uccb4\uc81c\uc758 \ubcf4\uc548 \uc800\uc7a5\uc18c\ub97c \uace0\ub824\ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc2e4\ubb34\uc5d0\uc11c \ubc18\ub4dc\uc2dc \uace0\ub824\ud560 \ubcf4\uc548 \uc815\ucc45<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud56d\ubaa9<\/th><th>\uad8c\uc7a5 \uc124\uacc4<\/th><\/tr><\/thead><tbody><tr><td>Access Token \uc218\uba85<\/td><td>\uc9e7\uac8c \uc124\uc815\ud558\uace0 \uad8c\ud55c \ubc94\uc704 \ucd5c\uc18c\ud654<\/td><\/tr><tr><td>Refresh Token \uc218\uba85<\/td><td>\uc808\ub300 \ucd5c\ub300 \uc218\uba85 \ubc0f \ube44\ud65c\uc131 \ub9cc\ub8cc \uc124\uc815<\/td><\/tr><tr><td>Rotation<\/td><td>\uac31\uc2e0\ud560 \ub54c\ub9c8\ub2e4 \uc0c8 Refresh Token \ubc1c\uae09<\/td><\/tr><tr><td>\uc7ac\uc0ac\uc6a9 \uac10\uc9c0<\/td><td>\uc774\uc804 \ud1a0\ud070 \uc7ac\uc0ac\uc6a9 \uc2dc \uc704\ud5d8 \ud3c9\uac00 \ud6c4 \uc138\uc158 \ud3d0\uae30<\/td><\/tr><tr><td>\uc800\uc7a5<\/td><td>\ud1a0\ud070 \uc6d0\ubb38 \ub178\ucd9c \ucd5c\uc18c\ud654, \uc11c\ubc84\uc5d0\ub294 \ud574\uc2dc \uc800\uc7a5<\/td><\/tr><tr><td>\ud1b5\uc2e0<\/td><td>HTTPS \ud544\uc218<\/td><\/tr><tr><td>\ub85c\uadf8\uc544\uc6c3<\/td><td>\ud574\ub2f9 \ud1a0\ud070 \uacc4\uc5f4 \ud3d0\uae30<\/td><\/tr><tr><td>\ub3d9\uc2dc \uac31\uc2e0<\/td><td>\ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad \ub2e8\uc77c\ud654 \ubc0f \uc11c\ubc84 \uce21 \uc6d0\uc790\uc131 \ubcf4\uc7a5<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth 2.0 \ubcf4\uc548 \ubaa8\ubc94 \uc0ac\ub840\uc778 RFC 9700\uc740 \uacf5\uac1c \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 Refresh Token\uc5d0 \ub300\ud574 \ud1a0\ud070 Rotation \ub610\ub294 DPoP\uc640 \uac19\uc740 \uc1a1\uc2e0\uc790 \uc81c\ud55c \ubc29\uc2dd\uc744 \ud1b5\ud55c \uc7ac\uc0ac\uc6a9 \ubc29\uc9c0 \uba54\ucee4\ub2c8\uc998\uc744 \uc694\uad6c\ud55c\ub2e4. Rotation\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ud1a0\ud070 \uacc4\uc5f4\uacfc \uc7ac\uc0ac\uc6a9 \uac10\uc9c0\ub97c \uc62c\ubc14\ub974\uac8c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc815\ub9ac<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Access Token: API\uc5d0 \uc811\uadfc\ud560 \ub54c \uc0ac\uc6a9\ud558\ub294 \ub2e8\uae30 \uc778\uc99d \uc790\uaca9 \uc99d\uba85<\/li>\n\n\n\n<li>Refresh Token: \uc0c8\ub85c\uc6b4 Access Token\uc744 \ubc1c\uae09\ubc1b\uae30 \uc704\ud55c \uc7a5\uae30 \uc790\uaca9 \uc99d\uba85<\/li>\n\n\n\n<li>Refresh Token Rotation: \uac31\uc2e0\ud560 \ub54c\ub9c8\ub2e4 Refresh Token\uc744 \uad50\uccb4\ud558\uace0 \uae30\uc874 \ud1a0\ud070\uc744 \ud3d0\uae30\ud558\ub294 \ubc29\uc2dd<\/li>\n\n\n\n<li>Reuse Detection: \ud3d0\uae30\ub41c Refresh Token\uc774 \ub2e4\uc2dc \uc0ac\uc6a9\ub418\uc5c8\ub294\uc9c0 \uac10\uc9c0\ud558\ub294 \ubcf4\uc548 \uba54\ucee4\ub2c8\uc998<\/li>\n\n\n\n<li>Token Family: \uac19\uc740 \ub85c\uadf8\uc778 \uc138\uc158\uc5d0\uc11c \uc774\uc5b4\uc9c4 \ud1a0\ud070\ub4e4\uc744 \ubb36\uc5b4 \uad00\ub9ac\ud558\ub294 \uac1c\ub150<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ud575\uc2ec\uc740 \ud1a0\ud070\uc758 \uc218\uba85\uc744 \uc9e7\uac8c \uc124\uc815\ud558\ub294 \uac83\ub9cc\uc73c\ub85c\ub294 \ucda9\ubd84\ud558\uc9c0 \uc54a\ub2e4\ub294 \uc810\uc774\ub2e4. Refresh Token \ud0c8\ucde8\uc5d0 \ub300\uc751\ud558\ub824\uba74 \ud1a0\ud070\uc758 \uc218\uba85, \uc800\uc7a5 \ubc29\uc2dd, \ud3d0\uae30 \uc0c1\ud0dc, \uc7ac\uc0ac\uc6a9 \uac10\uc9c0, \ub3d9\uc2dc\uc131 \uc81c\uc5b4\ub97c \ud558\ub098\uc758 \uc778\uc99d \uc2dc\uc2a4\ud15c\uc73c\ub85c \uc124\uacc4\ud574\uc57c \ud55c\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc6f9 \uc11c\ube44\uc2a4\ub098 \uac8c\uc784 \uc11c\ubc84\uc5d0\uc11c \ub85c\uadf8\uc778 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \ub54c \uc911\uc694\ud55c \uac1c\ub150 \uc911 \ud558\ub098\uac00 Access Token\uacfc Refresh Token\uc744 \uc774\uc6a9\ud55c \uc778\uc99d \uad6c\uc870\ub2e4. \uc0ac\uc6a9\uc790\uac00 \ub85c\uadf8\uc778\ud558\uba74 \uc11c\ubc84\ub294 \uc778\uc99d \uc815\ubcf4\ub97c \ubc14\ud0d5\uc73c\ub85c \ud1a0\ud070\uc744 \ubc1c\uae09\ud55c\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc774 \ud1a0\ud070\uc744 \uc0ac\uc6a9\ud574 API \uc694\uccad\uc744 \ubcf4\ub0b4\uba70, \ud1a0\ud070\uc774 \ub9cc\ub8cc\ub418\uba74 \uac31\uc2e0 \uc808\ucc28\ub97c \uac70\uce5c\ub2e4. \ud558\uc9c0\ub9cc Refresh Token\uc744 \uc624\ub7ab\ub3d9\uc548 \ub3d9\uc77c\ud558\uac8c \uc720\uc9c0\ud558\uba74 \ud1a0\ud070 \ud0c8\ucde8 \uc2dc \uacf5\uaca9\uc790\uac00 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0c8\ub85c\uc6b4 Access Token\uc744 \ubc1c\uae09\ubc1b\uc744 \uc218 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2626","post","type-post","status-publish","format-standard","hentry","category-dev-logs"],"_links":{"self":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts\/2626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2626"}],"version-history":[{"count":1,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts\/2626\/revisions"}],"predecessor-version":[{"id":2627,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts\/2626\/revisions\/2627"}],"wp:attachment":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}