axios interceptors를 통한 API 공통 사항 관리

ISOJ·2022년 7월 26일
0

JWT 토큰을 API 호출할 때 마다 Header에 실어보내야 하는데..

API 공통 사항 관리의 필요성

JWT 토큰 방식의 로그인을 구현하면서, 로그인 이후의 API 호출에 대해 전부 header에 토큰을 같이 실어 보내야 했다.

또한, 토큰의 유무 / 토큰이 유효한지 여부에 따라서도 해당 페이지를 그리지 않고 로그인 페이지로 리다이렉트를 시켜야할지에 대한 여부를 판단해야 했다.

그래서 처음에는 router.js의 router.beforEach에서 토큰의 유효성을 검증하고, 유효하지 않다고 판단될 시, login으로 리다이렉트 시키는 방법으로 구현하였다. (Vue 기준)

router.beforeEach((to, from, next) => {
	// JWT토큰이 없다면
  if (!localStorage.getItem('ACCESS_TOKEN')) {
    store.dispatch('auth/logout') // vuex의 로그아웃 로직 실행
  } 
  // vuex의 로그인 여부 확인
  const isLogin = store.getters["auth/isLogin"]
  // isLogin이 false일 경우
  if (!isLogin) {
  	// 로그인으로 리다이렉트
    next('/login')
  } else {
    // ...
  }
}

위의 방식으로는 여러 문제가 발생하고 있었다. 그 중,
1. 유효 기간이 지난 토큰을 가지고 있는 상태에서 라우터 이동을 막을 수 없었다.
2. 페이지를 유지한 상태에서 토큰이 없어지거나, 유효하지 않을 경우 API 호출을 막을 수 없었다.
두 가지 문제점을 가장 크게 느끼게 되어 다시 한번 생각하게 되었다.

토큰의 유효 기간이 만료된 경우에는 API request시에 서버에서 response를 내려줄 때 한번 걸러주기에 의도치 않게 API가 호출될 일은 없었지만, 그래도 옳지 않은 방법이므로 axios interceptors를 통해 관리하는 방법으로 개선하게 되었다.

axios interceptors

가장 먼저 axios interceptors를 사용하면서 개인적으로 느낀 interceptors의 가장 큰 이점은
1. axios로 요청하는 API 헤더에 공통된 값을 관리할 수 있다.
2. axios로 요청하는 API response에 대한 공통된 에러처리가 가능하다.
였던 것 같다.

공통 헤더 관리

공통으로 사용할 수 있는 axios 헤더를 다음과 같은 방법으로 설정할 수 있다.

axios.interceptors.request.use(
  request => {
    if (!!localStorage.getItem('ACCESS_TOKEN')) {
      request.headers["Authorization"] = `Bearer ${localStorage.getItem('ACCESS_TOKEN')}`
      request.headers["accept"] = "application/json"
    }
    return request
  },
  err => Promise.reject(err)
)

위와 같이 로컬 스토리지에 토큰이 존재하는지 여부를 보고 axios 공통 헤더로 토큰에 대한 key-value 값을 설정할 수 있다.

공통 response 처리

API 응답에 대한 response 및 에러를 공통으로 case화 하여 처리할 수 있었다.

axios.interceptors.response.use(
    (response) => response,
    (error) => {
    if (error.response) {
      switch (error.response.status) {
        case 503:
          	// ...
          break
        case 400:
          openModal({
            title: '파일을 읽을 수 없습니다.',
            content: '// ...',
          })
          break
        case 401:
          logout()
          break
        case 404:
          alert('404 에러')
          break
        case 405:
          openModal({
            title: '파일 업로드 불가',
            content: '// ...',
          })
          break
        case 406:
          alert('잠시 후 다시 시도해주세요.')
          break
        case 500:
          alert('업로드 실패.')
          break
      }
    return Promise.reject(error);
  }

와 같이 한번에 에러 케이스들에 대한 핸들링이 가능했다. interceptors를 사용한다면, JWT 로그인 관리 뿐만 아니라, 다방면에서도 유용하게 사용할 수 있을 것 같다.

profile
프론트엔드

0개의 댓글