[ RN ] Axios + Redux

Happhee·2021년 12월 22일
0

[ImagineCup] NVP

목록 보기
4/8
post-thumbnail

react native에서 웹서버에 데이터를 요청하거나 요청한 데이터를 받아올 때 사용하는 API로

Fetch, Axios 가 있다.

🖥 Axios란

Promise based HTTP client for the browser and node.js

  • node.js와 브라우저를 위한 HTTP통신 라이브러리
  • 비동기로 HTTP 통신을 가능하게 해주며 return을 promise 객체로 해주기 때문에 response 데이터를 다루기도 쉬움

📍 Axios 기능

1. promise API 지원

promise란
자바스크립트 비동기 처리에 사용되는 객체
자바스크립트의 비동기 처리란
‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’

  • axios는 비동기 통신을 지원합니다.

2. JSON 데이터로 자동변환

  • Axios는 요청을 보낼 때 자동으로 데이터를 문자열
  • Fetch()를 사용할 때는 수동으로 수행

3. 폭넓은 브라우저 호환성 보장

  • Axois는 오래된 브라우저에서 아무런 문제 없이 실행
  • Fetch()는 polyfill을 수동 설치하여 비슷한 기능을 구현

4. 응답 시간 초과 설정

Axios에서는 config 객체의 optional 속성을 사용하여 요청이 중단되기 전의 시간 (밀리 초)을 설정할 수 있습니다. Fetch()는 AbortController 인터페이스를 통해 유사한 기능을 제공합니다. 그러나 Axios만큼 간단하지는 않습니다.

5. 동시 요청

  • Axios는 axios.all() 사용하여 동시 요청을 기능을 제공

간단하게 코드를 비교해보자

  • fetch : POST
let url = 'https://seohee';
let options = {
            method: 'POST',
            mode: 'cors',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json;charset=UTF-8'
            },
            body: JSON.stringify({
                property_one: value_one,
                property_two: value_two
            })
        };
let response = await fetch(url, options);
let responseOK = response && response.ok;
if (responseOK) {
    let data = await response.json();
    // do something with data
}
  • Axios : POST
let url = 'https://seohee';
let options = {
            method: 'POST',
            url: url,
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json;charset=UTF-8'
            },
            data:{
      			id : 'seohee',
      			age: 23
            }
        };

let response = await axios(options);
let responseOK = response && response.status === 200 && response.statusText === 'OK';
if (responseOK) {
    let data = await response.data;
    // do something with data
}

📍 axios 설치

npm install -save axios

🖥 instance.interceptors

  • 📝 Axios 인터셉터 는 요청이 실행되기 전에 수정할 수있는 일종의 미들웨어이며 클라이언트 측에서 사용할 수있게되기 전에 응답하게 도와준다.
    처음에 토큰으로 Axios 인스턴스를 초기화 할 수 없기 때문에 이를 사용하여토큰검증해야 한다.
  • 📝 Axios 모듈화 시켜서 서버와 연동을 진행

📍 axios 객체 생성

  • utils/axiosInstance.js
import AsyncStorage from '@react-native-community/async-storage';
import axios from 'axios';

const USER_URL = "http://localhost:3000/api"
const axiosInstance = axios.create({
    baseURL: USER_URL,
    timeout: 1000,
});
const refreshToken = await AsyncStorage.getItem('refreshToken');

이후 interceptors.requestinterceptors.response를 진행하여 미들웨어를설정

//요청 가로채기
axiosInstance.interceptors.request.use(
    //요청 보내기전 수행
    function (config) {
        config.headers['Authorization'] = `Bearer ${refreshToken}`
        return config
    },
    //오류 요청
    function (err) {
        return Promise.reject(err)
    }
)

//응답 가로채기
axiosInstance.interceptors.response.use(
    //200대 응답 
    function (res) {
        return res
    },
    //200 이외 응답
    async function (err) {

        return Promise.reject(err);
    }
)

📍 토큰 새로고침

  • 서버에서 reqheader에 들어있는 토큰을 검증하여 해당 회원의 데이터를 가져온다
const authJWT = (req, res, next) => {
  if (req.headers.authorization) {
    const token = req.headers.authorization.split('Bearer ')[1];
    const result = verify(token);
    if (result.ok) {
      req.id = result.id;
      req.name = result.name;
      req.password=result.password;
      req.filename=result.filename;
      req.filedate=result.filedate;
      next();
    } else {
      res.status(401).send({
        ok: false,
        message: result.message,
      });
    }
  }
};

이 작업을 위해서 클라이언트는 매 요청마다 refreshToken을 보내줘야하고, 응답이 401이고 토큰 만료의 상태라면 토큰을 재발행해주어야 한다.

토큰 재발행 과정

  • 응답이 오류인 객체의 config를 가져온다
  • 오류 코드가 만료된 토큰의 응답이 401인지 확인
  • AsyncStoragerefreshToken을 가져오고, 존재하면 서버로 보낸다
  • 새로운 accessToken을 가져오기
  • AsyncStorage의 저장소를 업데이트하고 그 토큰들로 originalReq을 다시 수행

//응답 가로채기
axiosInstance.interceptors.response.use(
    //200대 응답 
    function (res) {
        return res
    },
    //200 이외 응답
    async function (err) {
        const {
            config,
            res: { status },
        } = err;

        if (status === 401) {
            //토큰 만료시
            if (!err.res.ok) {
                const originalReq = config;
                const refreshToken = await AsyncStorage.getItem('refreshToken');
		//refresh토큰 요청 
              if(refreshToken){
                  const { data } = await axios.post(
                      USER_URL + '/users/refresh',
                      { refreshToken },
                  );

                  const {
                      accessToken: newAccessToken,
                      refreshToken: newRefreshToken
                  } = data;
          //토큰 재설정
                  await AsyncStorage.multiSet([
                      ['accessToken', newAccessToken],
                      ['refreshToken', newRefreshToken]
                  ]);

                  axios.defaults.headers.common.Authorization = `Bearer ${newAccessToken}`;
                  originalReq.headers.Authorization = `Bearer ${newAccessToken}`;
                  return axios(originalReq);
              }
            }
        }
        return Promise.reject(err);
    }
)

🖥 Redux 비동기 api연결

profile
즐기면서 정확하게 나아가는 웹프론트엔드 개발자 https://happhee-dev.tistory.com/ 로 이전하였습니다

0개의 댓글