YesCoding

Go to English
search:

[React] class λ₯Ό μ‚¬μš©ν•œ μ „μ—­ μƒνƒœ accessToken

thumbnail_accesstoken

React μ•±μ—μ„œ login ν›„ accessToken 을 μ„œλ²„λ‘œλΆ€ν„° λ°œκΈ‰λ°›μ•„ μ „μ—­ μƒνƒœλ‘œ κ΄€λ¦¬ν•˜μ—¬ 인증이 ν•„μš”ν•œ api μš”μ²­μ‹œλ§ˆλ‹€ header 에 넣어쀄 λ•Œ κ²ͺμ—ˆλ˜ troubleshooting κΈ°λ‘μž…λ‹ˆλ‹€.

μ›Ήμ—μ„œ 인증 κΈ°λŠ₯을 κ΅¬ν˜„ν•˜λŠ”λ°, 둜그인 성곡 ν›„ μ„œλ²„λ‘œλΆ€ν„° 받은 accessToken 을 μ €μž₯ν•  곳이 ν•„μš”ν–ˆλ‹€. μ²˜μŒμ—λŠ” λΈŒλΌμš°μ € localStorage 에 μ €μž₯을 ν•˜λ €κ³  ν–ˆλŠ”λ° νƒˆμ·¨ μœ„ν—˜μ΄ 높을 것 κ°™μ•„ μ•± μ „μ—­ μƒνƒœμ— μˆ¨κ²¨λ‘κ³  μ™ΈλΆ€μ—μ„œ νƒˆμ·¨ν•  수 없도둝 κ΅¬ν˜„κ³„νšμ„ λ°”κΎΈμ—ˆλ‹€.

μ „μ—­ μƒνƒœ: Recoil 을 μ“ΈκΉŒ? β†’ μ•ˆ λœλ‹€.

νŒ€ λ‚΄μ—μ„œ μ „μ—­ μƒνƒœλŠ” Recoil 라이브러리λ₯Ό μ“°κΈ°λ‘œ κ²°μ •ν–ˆμ—ˆκΈ° λ•Œλ¬Έμ— μ²˜μŒμ—λŠ” Recoil 둜 해보렀고 ν–ˆμœΌλ‚˜ μ‹€νŒ¨ν–ˆλ‹€. Recoil 은 React hook κΈ°λ°˜μ΄μ–΄μ„œ React component κ°€ μ•„λ‹Œ κ³³μ—μ„œλŠ” μ“Έ 수 μ—†κΈ° λ•Œλ¬Έμ— accessToken 을 μ €μž₯ν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©ν•  수 μ—†μ—ˆλ‹€.

api request λ₯Ό ν•˜κΈ° 전에 λͺ¨λ“  μš”μ²­μ΄ ν•œ ν•¨μˆ˜λ₯Ό ν†΅ν•΄μ„œ 가도둝 util ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄ λ‘μ—ˆλŠ”λ°, 이 ν•¨μˆ˜μ—μ„œ header 에 Bearer ${accessToken} 을 λ„£μ–΄μ£ΌκΈ° μœ„ν•΄μ„œλŠ” μ „μ—­ μƒνƒœμ— μ €μž₯λ˜μ–΄ μžˆλŠ” access Token 을 μ½μ–΄μ˜¬ 수 μžˆμ–΄μ•Ό ν•œλ‹€. 그런데 이 ν•¨μˆ˜λŠ” React component κ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— recoil 을 μ‚¬μš©ν•  수 μ—†μ—ˆλ‹€.

ν•΄κ²°: AccessToken class 둜 λ§Œλ“€μ–΄μ„œ μ“°μž.

둜그인 ν›„ μ„œλ²„λ‘œλΆ€ν„° λ°œκΈ‰λ°›μ€ accessToken 을 μ €μž₯ν•  AuthToken class λ₯Ό λ§Œλ“ λ‹€.

class AuthToken { private _token: string; constructor() { this._token = ""; } getToken() { return this._token; } setToken(newToken: string) { this._token = newToken; } } export const authToken = new AuthToken();

앱이 싀행될 λ•Œλ§ˆλ‹€ 이 AuthToken class λ˜ν•œ μƒˆλ‘œ μƒμ„±λœλ‹€. νŽ˜μ΄μ§€κ°€ λ¦¬λ‘œλ“œ 될 λ•Œλ§ˆλ‹€ 앱은 μž¬μ‹€ν–‰λ˜λŠ”λ°, μ΄λ•Œλ§ˆλ‹€ μƒˆλ‘œ token 을 κ°±μ‹  ν›„ μž¬λ°œκΈ‰ 받도둝 κ΅¬ν˜„ν•  κ²ƒμ΄λΌμ„œ AuthToken class 의 token 값이 μ΄ˆκΈ°ν™”λ˜μ–΄λ„ 상관이 μ—†λ‹€.

λŒ€μ‹  앱이 λ¦¬λ‘œλ“œ 되기 μ „κΉŒμ§€λŠ” 이 class λŠ” ν•œλ²ˆλ§Œ μƒμ„±λ˜μ–΄ this._token 을 λ³€κ²½ν•˜ 수 μžˆλŠ” 것은 setToken λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μ‹œμΌ°μ„ λ•Œ 뿐이라 μ•ˆμ „ν•˜λ‹€.

이제 authToken.setToken(accessToken); 을 sign-in μ½”λ“œ λ‹€μŒ 쀄에 λ„£μ–΄μ£Όλ©΄ μ „μ—­μƒνƒœλ‘œ accessToken 을 κ°€μ§ˆ 수 있게 되고, accessToken 이 μžˆμ–΄μ•Όλ§Œ ν˜ΈμΆœν•  수 μžˆλŠ” api 듀을 ν˜ΈμΆœν•  λ•Œ getToken 으둜 가져와 Authorization header 에 λ„£μ–΄μ£Όλ©΄ λœλ‹€.

axios 곡톡 ν•¨μˆ˜ μ˜ˆμ‹œ

export const request = async ({ ...options }: any) => { let accessToken = authToken.getToken(); // validate accessToken expiration if (accessToken && parseJwt(accessToken).exp < Date.now() / 1000) { // accessToken λ§Œλ£Œμ‹œ refresh token 으둜 μž¬λ°œκΈ‰ const response = await axiosInstance.post("/auth/refresh", { deviceId: localStorage.getItem("deviceId"), }); accessToken = response.data; authToken.setToken(accessToken); } // axios에 withCredentialsλ₯Ό true둜 μ„€μ •ν•΄μ€˜μ•Ό refreshToken cookieλ₯Ό 주고받을 수 μžˆλ‹€. axiosInstance.defaults.withCredentials = true; axiosInstance.defaults.headers.common[ "Authorization" ] = `Bearer ${accessToken}`; const onSuccess = (response: any) => response; const onError = (error: any) => { ... error flow throw error; }; try { const response = await axiosInstance(options); return onSuccess(response); } catch (error) { return onError(error); } };
Β© Copyright 2022, yesCoding