Frontend/JavaScript

[Axios] Axios ์ธํ„ฐ์…‰ํ„ฐ ์ ์šฉํ•˜๊ธฐ

_์„ฑํ˜ธ_ 2023. 5. 10. 04:44
728x90
๋ฐ˜์‘ํ˜•

์ธํ„ฐ์…‰ํ„ฐ(Interceptors)๋ž€? then ๋˜๋Š” catch๋กœ ์ฒ˜๋ฆฌ๋˜๊ธฐ ์ „์— ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ๋‹ค.

 

Axios ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์ ์šฉํ•˜๋ ค๋Š” ์ด์œ โ“

ํ† ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์„œ๋ฒ„์— ํ† ํฐ ์ธ์ฆ์„ ํ•„์š”๋กœ ํ•˜๋Š” API ์š”์ฒญ์„ ํ• ๋•Œ๋งˆ๋‹ค HTTP Authorization ์š”์ฒญ ํ—ค๋”์— ํ† ํฐ์„ ๋„ฃ์–ด์ค˜์•ผํ•˜๊ณ  401(Unauthorized) ์—๋Ÿฌ๊ฐ€ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋“ค์–ด์˜ค๋ฉด ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ด์ค€ ํ›„ ์žฌ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ณผ์ •์„ ํ•œ ๊ณณ์—์„œ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด Axios ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์ ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ง€์ • config๋กœ ์ƒˆ๋กœ์šด Axios ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋‹ˆ ๋”์šฑ ํŽธ๋ฆฌํ–ˆ๋‹ค. (baseURL, timeout ์„ค์ •) 

 

์ ์šฉํ•˜๋Š” ๊ณผ์ •

1) Axios ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

const instance = axios.create({
  // ์ƒ๋Œ€์ ์ธ URL์„ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌํ•˜๋ ค๋ฉด baseURL์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ํŽธ๋ฆฌํ•˜๋‹ค.
  // URL(์„œ๋ฒ„ ์ฃผ์†Œ) ์˜ˆ์‹œ - http://127.0.0.1:5500
  baseURL: URL,
  // ์š”์ฒญ์ด timeout๋ณด๋‹ค ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋ฉด ์š”์ฒญ์ด ์ค‘๋‹จ๋œ๋‹ค.
  timeout: 1000,
});

 

2) ์š”์ฒญ ์ธํ„ฐ์…‰ํ„ฐ ์ถ”๊ฐ€ํ•˜๊ธฐ

  • ์š”์ฒญ์ด ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ์ž‘์—… ์ˆ˜ํ–‰, ์š”์ฒญ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ์ž‘์—… ์ˆ˜ํ–‰์„ ํ•  ์ˆ˜ ์žˆ๋Š” 2๊ฐœ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค.
instance.interceptors.request.use(
  (config) => {
    // getToken() - ํด๋ผ์ด์–ธํŠธ์— ์ €์žฅ๋˜์–ด ์žˆ๋Š” ์•ก์„ธ์Šค ํ† ํฐ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
    const accessToken = getToken();

    config.headers['Content-Type'] = 'application/json';
    config.headers['Authorization'] = `Bearer ${accessToken}`;

    return config;
  },
  (error) => {
    console.log(error);
    return Promise.reject(error);
  }
);

 

3) ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ ์ถ”๊ฐ€ํ•˜๊ธฐ

  • ์‘๋‹ต ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ์ž‘์—… ์ˆ˜ํ–‰, ์‘๋‹ต ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ์ž‘์—… ์ˆ˜ํ–‰์„ ํ•  ์ˆ˜ ์žˆ๋Š” 2๊ฐœ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค.
instance.interceptors.response.use(
  (response) => {
    if (response.status === 404) {
      console.log('404 ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ€์•ผ ํ•จ!');
    }

    return response;
  },
  async (error) => {
    if (error.response?.status === 401) {
      // isTokenExpired() - ํ† ํฐ ๋งŒ๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜
      // tokenRefresh() - ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
      if (isTokenExpired()) await tokenRefresh();

      const accessToken = getToken();

      error.config.headers = {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      };

      // ์ค‘๋‹จ๋œ ์š”์ฒญ์„(์—๋Ÿฌ๋‚œ ์š”์ฒญ)์„ ํ† ํฐ ๊ฐฑ์‹  ํ›„ ์žฌ์š”์ฒญ
      const response = await axios.request(error.config);
      return response;
    }
    return Promise.reject(error);
  }
);

 

๐Ÿ™‡๐Ÿป ์ ์šฉ ํ›„ ์ „์ฒด ์ฝ”๋“œ

axios_interceptor.js

import URL from './server_url.js';
import { getToken, isTokenExpired, tokenRefresh } from './token.js';

const instance = axios.create({
  baseURL: URL,
  timeout: 1000,
});

instance.interceptors.request.use(
  (config) => {
    const accessToken = getToken();

    config.headers['Content-Type'] = 'application/json';
    config.headers['Authorization'] = `Bearer ${accessToken}`;

    return config;
  },
  (error) => {
    console.log(error);
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  (response) => {
    if (response.status === 404) {
      console.log('404 ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ€์•ผ ํ•จ!');
    }

    return response;
  },
  async (error) => {
    if (error.response?.status === 401) {
      if (isTokenExpired()) await tokenRefresh();

      const accessToken = getToken();

      error.config.headers = {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      };

      const response = await axios.request(error.config);
      return response;
    }
    return Promise.reject(error);
  }
);

export default instance;

 

์„œ๋ฒ„์— ํ† ํฐ ์ธ์ฆ์„ ํ•„์š”๋กœ ํ•˜๋Š” API ์š”์ฒญ์„ ํ•˜๋Š” ์˜ˆ์‹œ(๊ธฐ์กด ์ฝ”๋“œ -> ์ ์šฉ ํ›„ ์ฝ”๋“œ)

import instance from '../../modules/axios_interceptor.js';

// ๊ธฐ์กด ์ฝ”๋“œ
// async function getUser() {
//   try {
//     const response = await axios.get(`${URL}/api/user`, {
//       headers: {
//         'Content-Type': 'application/json',
//         Authorization: `Bearer ${accessToken}`,
//       },
//     });
//     console.log(response);
//   } catch (error) {
//     console.log(error);
//   }
// }

// ์ ์šฉ ํ›„ ์ฝ”๋“œ
async function getUser() {
  try {
    // ์œ„์—์„œ ์ง€์ •ํ•œ baseURL ๋’ค์— ๋‹ค์Œ URL์ด ๋ถ™๋Š”๋‹ค.
    const response = await instance.get('/api/user');
    console.log(response);
  } catch (error) {
    console.log(error);
  }
}

 

๐Ÿ“š ์ฐธ๊ณ ํ•œ ์‚ฌ์ดํŠธ

 

์ธํ„ฐ์…‰ํ„ฐ | Axios Docs

์ธํ„ฐ์…‰ํ„ฐ then ๋˜๋Š” catch๋กœ ์ฒ˜๋ฆฌ๋˜๊ธฐ ์ „์— ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑŒ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. axios.interceptors.request.use(function (config) { return config; }, function (error) { return Promise.reject(error); }); axios.interceptors.response.use(f

axios-http.com

 

axios interceptor๋กœ 401 ์ฒ˜๋ฆฌํ•˜๊ธฐ

ํ”„๋กœ์ ํŠธ์— Axios๋ฅผ ๋„์ž…ํ•˜๋ฉด์„œ interceptor๋ฅผ ์‚ฌ์šฉํ•ด์„œ401์— ๋Œ€ํ•œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด๋ณธ ๊ฒฝํ—˜, token์„ ๊ฐ€์ ธ์˜ค๋Š” ๋กœ์ง์„ ๋ฆฌํŒฉํ† ๋งํ•œ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹คํด๋ผ์ด์–ธํŠธ์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ fetch()๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜

velog.io