본문 바로가기

React

[React] instance 와 interceptor

Interceptor의 필요성

 

axios.get("http://localhost:3001/todos");
axios.post("http://localhost:3001/todos", todo);
axios.delete(`http://localhost:3001/todos/${todoId}`);

 

이렇게 호출하는 부분이 리액트 앱에 300개 정도 있다고 가정하면, 호출 서버가 변경되었을 때 300개를 모두 변경해 주어야 한다.

이는 리소스적으로 엄청난 낭비이다.

 

axios는 이름에서 알 수 있듯이 다음과 같은 상황에서 흐름을 가로채서 코드상의 관여를 할 수 있게 한다.

(1) 요청(request) 이 처리되기 전 (= http request 가 서버에 전달되기 전)

(2) 응답(response) 의 then (= 성공) 또는 catch(= 실패)가 처리되기 전

 

- 요청 헤더 추가

- 인증 관리

- 로그 관련 로직 삽입

- 에러 핸들링

 

따라서 위 상황들을 포함하여 요청 및 응답시 필요한 작업을 한꺼번에 처리할 수 있음.

 


 

환경변수 실습

 

1. .env파일 생성하여 환경변수 설정

REACT_APP_SERVER_URL=http://localhost:4000

 

2. 위의 값 대신에 `${process.env.변수명}/path` 작성

  //const { data } = await axios.get("http://localhost:4000/todos"); // 서버로부터 값을 받을때 까지 기다림
    const { data } = await axios.get(`${process.env.REACT_APP_SERVER_URL}/todos`

이처럼 작성하면 포트번호가 바뀌어도 환경변수에서 한번만 설정하면 됨.

 


가공한 axios instance 사용

 

1. 상위폴더로 axios 만들고 그 안에 api.js 파일 생성, 이후 다음과 같이 작성

 

import axios from "axios";

const instance = axios.create({
  baseURL: process.env.REACT_APP_SERVER_URL,
});

export default instance;

 

2. 컴포넌트 파일로 돌아와서 api import

 

import api from "./axios/api";

 

3. 이후 api.메소드('/path') 형태로 작성

 

    // url 직접 입력 const { data } = await axios.get("http://localhost:4000/todos"); // 서버로부터 값을 받을때 까지 기다림
    // url 환경변수 설정 const { data } = await axios.get(
    //   `${process.env.REACT_APP_SERVER_URL}/todos`
    // ); // 서버로부터 값을 받을때 까지 기다림
    
    // instance 적용
    const { data } = await api.get(`/todos`); // 서버로부터 값을 받을때 까지 기다림

 

4. 코드 전체 리팩토링

 

// 서버로 부터 값 받아오는 함수
  const fetchTodos = async () => {
    // 서버로부터 값 요청, 비동기
    // const { data } = await axios.get("http://localhost:4000/todos"); // 서버로부터 값을 받을때 까지 기다림
    // const { data } = await axios.get(
    //   `${process.env.REACT_APP_SERVER_URL}/todos`
    // ); // 서버로부터 값을 받을때 까지 기다림
    const { data } = await api.get(`/todos`); // 서버로부터 값을 받을때 까지 기다림
    console.log("data", data);
    setTodos(data); // todos 를 이용해 값을 뿌려줄 수 있음.
  };

  // 추가, 입력함수
  const onSubmitHandler = async () => {
    // 무슨 값을 post 로 보낼 것인가에 대한 async, 여기서는 값을 따로 가져오는게 아니므로 없어도 무방
    api.post(`/todos`, inputValue);
    // setTodos([...todos, inputValue]); // 값 추가
    fetchTodos(); // 다시 값을 읽어와서 id 값을 부여함.
  };

  // 삭제함수
  const onDeleteHandler = async (id) => {
    // 무슨 값을 delete 할건지에 대한 async
    api.delete(`/todos/${id}`);
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  // 수정함수
  const onUpdateHandler = async () => {
    api.patch(`/todos/${targetId}`, {
      title: content,
    });
    setTodos(
      todos.map((todo) => {
        if (todo.id == targetId) {
          // 아이디의 형이 달라서 동등연산자로 하면 작동함.
          return { ...todo, title: content };
        } else {
          return todo;
        }
      })
    );
  };

 


api.js 에 request, response 확인하기 

 

import axios from "axios";

const instance = axios.create({
  baseURL: process.env.REACT_APP_SERVER_URL,
});

instance.interceptors.request.use(
  // 요청을 보내기 전 수행되는 함수
  function (config) {
    console.log("인터셉터 요청 성공");
    return config;
  },

  // 오류 요청을 보내기 전 수행되는 함수
  function (error) {
    console.log("인터셉터 오류 요청");
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  // 응답을 내보내기 전 수행되는 함수
  function (response) {
    console.log("인터셉터 응답 받았습니다.");
    return response;
  },
  // 오류응답을 내보내기 전 수행되는 함수
  function (error) {
    console.log("인터셉터 응답 오류발생");
    return Promise.reject(error);
  }
);

export default instance;

 

새로고침을 하면 fetchTodos 가 실행되고, axios 를 콜하면서 request를 함.

 

강제로 내용을 실패시키면?

instance 에 timeout 을 적용하여 다음과 같이 수정하고 실행시키면

const instance = axios.create({
  baseURL: process.env.REACT_APP_SERVER_URL,
  timeout: 1, // (0.001초) 언제까지 기다리고 그 이후까지 응답이 없으면 오류를 낼 것이다.
});

 

서버로부터 (0.001 초) 안으로 응답을 받지 못해 오류가 발생하였음.

'React' 카테고리의 다른 글

[React] custom hooks  (0) 2023.07.05
[React] Thunk  (0) 2023.07.04
[React] Fetch 와 Axios  (0) 2023.07.04
[React] 비동기 통신 axios(patch)  (0) 2023.07.04
[React] 비동기 통신 axios(delete)  (0) 2023.07.04