๐ŸŠJWT ํ† ํฐ ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ / axios interceptor๋ฅผ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ

์ด์ •์ˆ˜ยท1์ผ ์ „
0

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” JWT๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ† ํฐ ๋งŒ๋ฃŒ๋ฅผ ํŒ๋‹จํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ฒช์€ ๊ณ ๋ฏผ๊ณผAxios Interceptor์—์„œ React Hook ๋ฐ Custom Hook์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ๋ฏผํ–ˆ๋˜ ๊ณผ์ •์„ ๋‹ด์•˜์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ฃผ์–ด์ง„ ๋ฐฑ์—”๋“œ api๋ฅผ ์ด์šฉํ•ด์„œ ์œ ์ €๊ธฐ๋Šฅ(๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…, ์œ ์ €์ •๋ณด์ˆ˜์ •, ๋กœ๊ทธ์•„์›ƒ, ํšŒ์›ํƒˆํ‡ด)์„ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ธ์ฆ์—์„œ๋Š” JWT(Json Web Token)์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋•Œ๋ฌธ์— ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์™€ ์†Œํ†ตํ•  ์ˆ˜ ์—†๊ณ , ์„œ๋ฒ„์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์ƒํ™ฉ์„ ์•Œ ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์—์„œ ๋ช‡๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๐Ÿš€ ํ† ํฐ์„ ์–ธ์ œ ๊ฐฑ์‹ ํ•ด์•ผ ํ•˜๋‚˜์š”?

JWT์—๋Š” ๋งŒ๋ฃŒ๊ธฐํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋ช…์ด ๋ฌดํ•œํ•œ ํ† ํฐ์€ ํƒˆ์ทจ์‹œ ๋ณด์•ˆ์— ํฐ ์œ„ํ˜‘์ด ๋˜๊ธฐ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„์˜ ํ† ํฐ์€ ๋งŒ๋ฃŒ๊ธฐํ•œ expiration date๋ฅผ payload์— ๋ช…์‹œํ•˜๊ณ  ์žˆ๋Š”๋ฐ์š”. ๋ฌธ์ œ๋Š” ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ์ „๋‹ฌ๋ฐ›์€ ํ† ํฐ์—๋Š” expํ•ญ๋ชฉ์ด ๋ช…์‹œ๋˜์–ด์žˆ์ง€ ์•Š์•˜๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

// ๋””์ฝ”๋”ฉ๋œ Jwt์˜ payload
{
  "user": {
    "_id": "679252*********8f82",
    "email": "l***u@gmail.com"
  },
  "iat": 17******7 // 
}

ํ† ํฐ์ด ์–ด๋–ค ์ •๋ณด๋ฅผ ๋‹ด๋Š”์ง€ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด https://jwt.io/ ๋ฅผ ๋ฐฉ๋ฌธํ•˜๊ฑฐ๋‚˜ jwt-decode์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ„๋‹จํžˆ ๋””์ฝ”๋”ฉํ•ด๋ณผ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋Œ์•„์™€์„œ, ์›๋ž˜๋Š” refresh token, access token์ด ์ฃผ์–ด์ง€๊ฑฐ๋‚˜ ํ•˜๋‚˜์˜ ํ† ํฐ์˜ ๋งŒ๋ฃŒ๊ธฐ๊ฐ„์ด ๋˜๋ฉด ๋‹ค์‹œ ์ƒˆ๋กœ์šด ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์•„์•ผ ํ•˜์ง€๋งŒ ์ฃผ์–ด์ง„ ํ† ํฐ์—์„œ๋Š” ๋งŒ๋ฃŒ๊ธฐ๊ฐ„ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

1. ๋งŒ๋ฃŒ์‹œ๊ฐ„์ด ๋งž๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.

๋กœ๊ทธ์ธ ์ดํ›„์— ํ™•์ธํ•œ ํ† ํฐ์˜ iat ํ‚ค๊ฐ€ ๊ณผ๊ฑฐ์ธ์ง€ ๋ฏธ๋ž˜์ธ์ง€ ํŒ๋‹จํ•ด์„œ ๊ณผ๊ฑฐ๋ผ๋ฉด ๋ฐœ๊ธ‰์‹œ๊ฐ„์ด ๋งž์„๊ฑฐ๊ณ , ๋ฏธ๋ž˜๋ผ๋ฉด ๋งŒ๋ฃŒ์‹œ๊ฐ„์œผ๋กœ ํ™œ์šฉํ•˜๊ณ  ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ™•์ธ๊ฒฐ๊ณผ iat๋Š” ๊ณผ๊ฑฐ์‹œ๊ฐ„์œผ๋กœ ์˜ฌ๋ฐ”๋ฅธ ๋ฐœ๊ธ‰์‹œ๊ฐ„์œผ๋กœ ์‚ฌ์šฉ๋œ๊ฒƒ์ด ๋งž์•˜์Šต๋‹ˆ๋‹ค.

iat๋Š” unix timestamp ํ˜•์‹์œผ๋กœ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

2. axios ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ 401์‘๋‹ต์ด ์˜ฌ๊ฒฝ์šฐ ํ”„๋ก ํŠธ์—์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

์–ด๋–ค ์š”์ฒญ์—์„œ ์œ ํšจํ•œ ์ธ์ฆ ์ž๊ฒฉ ์ฆ๋ช…์ด ์—†์–ด ๋ฐœ์ƒ๋˜๋Š” statusCode 401 ์‘๋‹ต์˜ค๋ฅ˜๊ฐ€ ์˜ฌ ๊ฒฝ์šฐ ๋‘๊ฐ€์ง€ ๊ฒฝ์šฐ์˜ ์ˆ˜๋กœ ๋‚˜๋ˆ„์–ด์„œ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1๏ธโƒฃ ์š”์ฒญ ํ—ค๋”์— JWT๊ฐ€ ์žˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  401์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๋งŒ๋ฃŒ๋˜์—ˆ๊ฑฐ๋‚˜ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ํ† ํฐ์ธ ๊ฒฝ์šฐ์ด๋‹ค.

๋”ฐ๋ผ์„œ ํ•ด๋‹น ๊ฒฝ์šฐ์—๋Š” ํ”„๋ก ํŠธ์—์„œ ๊ด€๋ฆฌ์ค‘์ธ ์œ ์ €์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ์ฟ ํ‚ค์— ๋ณด๊ด€๋œ JWT์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ ํ™ˆ์œผ๋กœ ์ด๋™ํ•˜๋ฉฐ ์œ ์ €์—๊ฒŒ๋Š” ๊ฒฝ๊ณ ์ฐฝ ํ˜น์€ ์•Œ๋žŒ์œผ๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋งŒ๋ฃŒ๋˜์—ˆ์Œ์„ ์ ์ ˆํžˆ ์•Œ๋ ค์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ ์š”์ฒญ ํ—ค๋”์— JWT๊ฐ€ ์—†๋‹ค๋ฉด ๋กœ๊ทธ์ธ์„ ํ•˜์ง€ ์•Š๊ณ ์„œ ์ตœ์ดˆ์ ‘๊ทผํ–ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ JWT๋ฅผ ํ—ค๋”์— ํฌํ•จ์‹œ์ผœ์•ผ ํ•˜๋Š” ์š”์ฒญ์ด ์žˆ๋Š” ํŽ˜์ด์ง€์— ๋กœ๊ทธ์•„์›ƒ์ƒํƒœ์—์„œ์˜ ์ ‘๊ทผ์„ ๋ง‰์•„๋‘์–ด์„œ ์ด ๊ฒฝ์šฐ๋Š” ํฌ๋ฐ•ํ•˜์ง€๋งŒ, ์ผ๋‹จ ํ•ด๋‹น ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์•Œ๋ฆผ๊ณผ ํ•จ๊ป˜ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿš€ axios intercepter๋กœ 401์‘๋‹ต ์ฒ˜๋ฆฌํ•˜๊ธฐ

Axios ์ธํ„ฐ์…‰ํ„ฐ๋ž€?
Axios๋Š” JavaScript์—์„œ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. Axios์˜ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋กœ ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์š”์ฒญ์ด๋‚˜ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑ„์„œ ์›ํ•˜๋Š” ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ๋ชจ๋“  ์š”์ฒญ์— ํ† ํฐ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ์‘๋‹ต ๋กœ๊น…, ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋“ฑ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ํ™œ์šฉํ•ด์„œ ํ—ค๋”์— ํ† ํฐ์„ ์‹ฃ๊ฑฐ๋‚˜, ์‘๋‹ต์—๋Ÿฌ ์ƒํ™ฉ์— ๋”ฐ๋ฅธ ์ ์ ˆํ•œ ์—๋Ÿฌ๋ฅผ ํ•ธ๋“ค๋งํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
์ด์ œ 401์—๋Ÿฌ๊ฐ€ ๋‚œ ๊ฒฝ์šฐ๋ฅผ ์œ„ ์š”๊ตฌ์‚ฌํ•ญ๋Œ€๋กœ ์™„์„ฑํ•œ 401์—๋Ÿฌ ๋ฐœ์ƒ์‹œ ํ˜ธ์ถœ๋˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ด ์ฝ”๋“œ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

const handle401Error = originalRequest => {
  const dispatch = useDispatch();
  const navigate = useNavigate();

  // iat๊ฐ€ ํ† ํฐ ๋ฐœ๊ธ‰์‹œ๊ฐ„์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ๋งž๋‹ค๊ณ  ํ™•์ธ๋จ.
  // ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ์ˆ˜๋™์œผ๋กœ ํ™•์ธํ•œ๋‹ค.
  // 1. ์—๋Ÿฌ๊ฐ€ ๋‚œ ์š”์ฒญ์— jwt๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ํ™•์ธ
  const hasToken = Boolean(originalRequest.header['Authorization']);

  if (hasToken) {
    // ์žˆ์—ˆ์œผ๋ฉด ํ† ํฐ ๋งŒ๋ฃŒ ์˜ค๋ฅ˜๋กœ ํŒ๋‹จ. -> ์ฟ ํ‚ค์™€ ์œ ์ € ์ƒํƒœ๋ฅผ ์ง€์šฐ๊ณ  ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
    dispatch(deleteUser()); // ๋ฆฌ๋•์Šค์˜ ์œ ์ €์ •๋ณด ์‚ญ์ œ
    removeCookie('jwt'); // ํ† ํฐ ์‚ญ์ œ
    alert('์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.๋กœ๊ทธ์ธํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.');
    navigate(PATH.auth);
  } else {
    // ์—†์—ˆ์œผ๋ฉด ํ† ํฐ ์—†์ด ์š”์ฒญ๋ณด๋‚ธ ๊ฒƒ์ด๋ฏ€๋กœ -> ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
    alert('์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.');
    navigate(PATH.auth);
  }
};

useDispatch, useNavigate๊ณผ ๊ฐ™์€ ๋ฆฌ์•กํŠธ ํ›…์€ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ํ˜น์€ ์ปค์Šคํ…€ ํ›… ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Axios Interceptor์ž์ฒด๋ฅผ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋งŒ๋“ค์–ด ๋‚ด๋ถ€์—์„œ Redux์ƒํƒœ ๋ณ€๊ฒฝ์„ ์œ„ํ•œ ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ œ๊ณต๋œ ๋ฐ๋ธŒ์„œ๋ฒ„ ๋ฟ ์•„๋‹ˆ๋ผ Open Api, supabase๋“ฑ ๋‹ค์–‘ํ•œ ์„œ๋ฒ„ ๋„๋ฉ”์ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋•Œ๋ฌธ์— ์ปค์Šคํ…€ํ›…์œผ๋กœ ๋งŒ๋“ค์–ด ๋‘๋ฉด ๊ฐ ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค API ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๋ฐ˜๋ณต์ ์ธ ์ฝ”๋“œ์—†์ด ๊ฐ„ํŽธํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

useAxiosInterceptor ์ปค์Šคํ…€ ํ›…

const useAxiosInterceptor = instance => {
  const dispatch = useDispatch();

  const onRequest = config => {
    const jwt = getCookie('jwt');
    if (jwt) {
      config.headers.Authorization = `bearer ${jwt}`;
    }
    return config;
  };

  const onErrorRequest = error => {
    return Promise.reject(error);
  };

  const onError = (status, message, errorDetail) => {
    const error = { status, message, errorDetail };
    throw error;
  };

  const handle401Error = async originalRequest => {
    // iat๊ฐ€ ํ† ํฐ ๋ฐœ๊ธ‰์‹œ๊ฐ„์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ๋งž๋‹ค๊ณ  ํ™•์ธ๋จ.
    // ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ์ˆ˜๋™์œผ๋กœ ํ™•์ธํ•œ๋‹ค.
    // 1. ์—๋Ÿฌ๊ฐ€ ๋‚œ ์š”์ฒญ์— jwt๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ํ™•์ธ
    const hasToken = originalRequest.headers['Authorization'].split(' ').at(1);
    if (hasToken) {
      // ์žˆ์—ˆ์œผ๋ฉด ํ† ํฐ ๋งŒ๋ฃŒ ์˜ค๋ฅ˜๋กœ ํŒ๋‹จ. -> ์ฟ ํ‚ค์™€ ์œ ์ € ์ƒํƒœ๋ฅผ ์ง€์šฐ๊ณ  ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
      alert('์‚ฌ์šฉ์ž ์ •๋ณด๊ฐ€ ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.ํ™ˆ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.');
      await dispatch(deleteUser());
      removeCookie('jwt');
      window.location.href = PATH.root;
    } else {
      // ์—†์—ˆ์œผ๋ฉด ํ† ํฐ ์—†์ด ์š”์ฒญ๋ณด๋‚ธ ๊ฒƒ์ด๋ฏ€๋กœ -> ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
      alert('์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.');
      await dispatch(deleteUser());
      removeCookie('jwt');
      window.location.href = PATH.auth;
    }
  };
  
  const onResponse = response => response;

  const onErrorResponse = error => {
    if (axios.isAxiosError(error)) {
      const originalRequest = error.config;
      const { method, url } = originalRequest;
      const { data: message, status: statusCode, statusText } = error.response;

   
      console.log(
        `[API] ${method.toUpperCase()} ${url} | ERROR ${statusCode} ${statusText} | ${message}`,
      );

      switch (statusCode) {
        case 400: {
          onError(statusCode, '์ž˜๋ชป๋œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.', message);
          break;
        }
        case 401: {
          handle401Error(originalRequest);
          break;
        }
        case 403: {
          onError(statusCode, '๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.', message);
          break;
        }
        case 404: {
          onError(statusCode, '์ฐพ์„ ์ˆ˜ ์—†๋Š” ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.', message);
          break;
        }
        case 500: {
          onError(statusCode, '์„œ๋ฒ„ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.', message);
          break;
        }
        default: {
          onError(statusCode, '์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', message);
        }
      }
    } else if (error && error.name === 'TimeoutError') {
      console.log(`[API] | Timeout ERROR ${error.toString()}`);
      onError(0, '์š”์ฒญ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.', '');
    } else {
      console.log(`[API] | ERROR ${error.toString()}`);
      onError(0, '์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', '');
    }
    return Promise.reject(error);
  };

  // interceptor ์ถ”๊ฐ€
  const setupInterceptors = () => {
    const requestInterceptor = instance.interceptors.request.use(onRequest, onErrorRequest);
    const responseInterceptor = instance.interceptors.response.use(onResponse, onErrorResponse);

    return { requestInterceptor, responseInterceptor };
  };

  // interceptor ์ œ๊ฑฐ
  const ejectInterceptors = (requestInterceptor, responseInterceptor) => {
    instance.interceptors.request.eject(requestInterceptor);
    instance.interceptors.response.eject(responseInterceptor);
  };

  useEffect(() => {
    const { requestInterceptor, responseInterceptor } = setupInterceptors();

    return () => {
      ejectInterceptors(requestInterceptor, responseInterceptor);
    };
  }, []);
};
export default useAxiosInterceptor;

๐Ÿ“š axios interceptor

  • instance.interceptors.request.use(์š”์ฒญ ์ „๋‹ฌ ์ „ ์ž‘์—… , ์š”์ฒญ ์˜ค๋ฅ˜์‹œ ์ž‘์—…)
  • instance.interceptors.response.use(200๋ฒˆ๋Œ€ ์ƒํƒœ์ฝ”๋“œ์‹œ ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š” ์ž‘์—…, ์‘๋‹ต ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„๋•Œ ์ž‘์—… )
  • instance.interceptors.request.eject() : ์ธํ„ฐ์…‰ํ„ฐ ์ œ๊ฑฐ

custom hook ์‚ฌ์šฉํ•˜๊ธฐ

function App() {
  useAxiosInterceptor(devAPI);
  return <RouterProvider router={router} />;
}

export default App;

์•ฑ์˜ ์ตœ์ƒ๋‹จ์—์„œ ์œ„์น˜์‹œ์ผœ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด์จŒ๋“  useAxiosInterceptor๊ฐ€ 'react-router'์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ๋˜๊ณ  ์žˆ๊ธฐ๋•Œ๋ฌธ์— ๊ธฐ์กด์˜ useNavigator์™€ ๊ฐ™์€ ํ›…์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๐Ÿ‘‰๋”ฐ๋ผ์„œ window.location.href๋กœ ์ด๋™์‹œ์ผœ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ useDispatch๊ฐ€ redux-persist์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— async-await ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ๊ฐ€ ์™„์ „ํžˆ ์—…๋ฐ์ดํŠธ ๋˜๊ณ  ๋‚œ๋’ค window.location.href๋กœ ๋ฆฌ๋””๋ ‰์…˜์ด ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

profile
keep on pushing

0๊ฐœ์˜ ๋Œ“๊ธ€