axios
는 npm 을 통해서 설치해야 하는 모듈로 자바스크립트 내장 fetch
와 마찬가지로 promise 객체를 기반으로 통신을 처리한다.
axios.메소드(서버 URL 주소, 요청 데이터)
의 형식으로 구성되어 axios.get
/ axios.post
와 같이 작성해서 요청을 보낼 수도 있고
axios({각종 옵션들, url 주소, 요청 데이터 등})
axios
라고만 작성하고 옵션을 모두 매개변수 인자로 넘기는 방식으로도 작성할 수 있다. 중요한 옵션은 아래와 같다.
axios({
url: "서버주소",
method: "get", // POST, PUT, DELETE 등의 요청 유형 선택
headers: {
Authorization: 인증 토큰 등
},
data: 리퀘스트 데이터 // POST, PUT 요청의 경우 전송 가능
});
axios 함수가 실행되면 해당 서버 주소로 요청을 보내고 (프로미스 객체 반환), 그 요청이 완료되면, 해당 서버의 응답을 반환한다.
이 응답에는 다음과 같은 프로퍼티가 있다.
특정한 코드의 동작이 완료될 때까지 기다렸다가 다음 작업을 진행하도록 도와주는 것이 바로 promise 객체
로, 특정한 코드의 수행이 완료되면 그 수행이 성공했는지 실패했는지에 따라서 다른 값을 반환해주는 객체이다.
promise
.then((result) => {
// 코드가 성공적으로 수행 완료될 경우 실행될 코드를 명시
// 성공한 결과값 (result = 응답, 데이터) 를 활용할 수 있음
})
.catch((error) => {
// 코드의 수행이 실패한 경우 실행될 코드를 명시
// 에러 객체 (error) 를 활용할 수 있음
});
axios.get('서버url')
.then(response => {요청 성공 시 실행할 코드})
.catch(error => {에러 핸들링})
async
/await
를 사용하는 것이 더 좋다.async
/await
문법은 promise.then / catch
를 사용하지 않고도 프로미스를 처리할 수 있게 해준다. 또한await
는 async 함수 안에서만 동작하며 사용 시 프로미스 객체가 처리될 때까지 기다렸다가 result에 결과값을 할당한다.
await 는 프로미스가 연달아 이어지는 상황에서도 코드가 깔끔하게 유지된다는 점에서 유용하다.
const getData = async () => {
const response = await axios.get("서버주소"); // 응답이 올때까지 기다렸다가 response 에 저장
// 여기서부터는 response 를 동기적으로 사용할 수 있게 됨
};
const getData = async () => {
try {
const response = await axios.get("서버주소");
// 응답과 관련한 코드
} catch (err) {
// 위에서 발생한 에러를 전부 여기서 처리
}
};
const getPosts = async () => {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
console.log(response.data); // .data 라고 해야 데이터에 접근
};
// or
const getPosts = async () => {
const response = await axios.get(`/posts`, {
params: { userId: 1 },
});
return response.data;
};
useEffect(() => {
getPosts();
}, []);
const createPost = async (post) => {
const response = await axios.post(
`https://jsonplaceholder.typicode.com/posts`,
post
);
};
useEffect(() => {
createPost({ title: "제목", body: "내용" });
}, []);
put
, patch
method 는 이미 있는 데이터를 수정하기 위해서 보내는 요청으로 post와 동일하게 작성하되 데이터 수정 시 정확히 서버에 있는 어떤 데이터를 수정하고자 하는 것인지를 명시해서 보내야 한다.
const updatePost = async (post, id) => {
const response = await axios.put(
`https://jsonplaceholder.typicode.com/posts/${id}`,
post
);
console.log(response.data);
};
useEffect(() => {
updatePost({ title: "글 수정하기", body: "수정된 내용" }, 1);
}, []);
const deletePost = async (id) => {
const response = await axios.delete(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
console.log(response.data);
};
useEffect(() => {
deletePost(1);
}, []);
config 옵션을 하나하나 명시하는 방식으로 아래와 같이 수정할 수 있다.
const createPost = async (post) => {
const response = await axios({
url: `https://jsonplaceholder.typicode.com/posts`,
method: "post", // get, put, delete 등의 method 를 명시
data: post,
});
return response.data;
};
const createPost = async (post) => {
try {
const response = await axios({
url: `https://jsonplaceholder.typicode.com/posts`,
method: "post", // get, put, delete 등의 method 를 명시
data: post,
timeout: 1, // 밀리초 단위 (명시한 시간 안에 요청이 안오면 시간초과 발생)
});
return response.data;
} catch (err) {
console.log(err);
}
};
ㅠ;
// utils/axiosConfig.js
import axios from "axios";
export const axiosSocket = axios.create({
baseURL: "또 다른 서버 주소",
});
export const axiosAPI = axios.create({
baseURL: "https://jsonplaceholder.typicode.com",
});
import { axiosAPI } from "../utils/axiosConfig";
const createPost = async (post) => {
const response = await axiosAPI.post(`/posts`, post);
return response.data;
};
//
VITE_SERVER_URL = "https://jsonplaceholder.typicode.com";
export const axiosAPI = axios.create({
baseURL: import.meta.env.VITE_SERVER_URL,
});
인터셉터는 요청 혹은 응답을 보내는 과정에서 요청 혹은 응답을 가로채고 특정한 작업을 수정하기 위한 기능으로 request
response
를 다룰 수 있다. 보통은 request 를 보낼 때에는 유저 인증 정보 존재 여부에 따라 유저 인증 정보를 요청에 포함시키기 위해 사용하고, response 를 받을 때에는 데이터 파싱 등을 처리하기 위해 사용한다.
axios.interceptors.request.use(
(request) => {
console.log(request);
return request;
},
(error) => {
console.log(error);
return Promise.reject(error);
}
);
axios.interceptors.response.use(
(response) => {
if (response.status === 200 || response.status === 201) {
return response.data;
}
return response;
},
(error) => {
console.log(error);
return Promise.reject(error);
}
);
더 많은 요청 config를 확인할 수 있다.
api 에 따라, 조건을 걸어서 데이터를 가져오는 것이 가능하다.
const getPosts = async () => {
const response = await axios.get(`/posts`, {
params: { userId: 1 },
});
return response.data;
};
qs
모듈을 사용할 수 있다.객체가 중첩되는 형태로 params를 작성하는 경우 아래처럼 설정해야 한다.
yarn add qs
// main.jsx
import qs from "qs";
axios.defaults.paramsSerializer = {
serialize: (params) => Qs.stringify(params, { arrayFormat: "brackets" }),
};
import React, { useEffect, useState } from "react";
import axios from "axios";
function Example() {
const [posts, setPosts] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const getPosts = async () => {
try {
setIsLoading(true);
const response = await axios.get(`/posts`, {
params: { userId: 1 },
});
return response.data;
} catch (err) {
setError(err);
}
};
const setPostsByResponse = async () => {
const data = await getPosts();
setPosts(data);
setIsLoading(false);
};
useEffect(() => {
setPostsByResponse();
}, []);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>{error.message}</div>;
return (
<div>
{posts.map((post) => {
return (
<div key={post.id}>
<h1>{post.title}</h1>
<p>작성자: {post.userId}</p>
<p>{post.body}</p>
</div>
);
})}
</div>
);
}
export default Example;
// hooks/useAsync.jsx
import { useEffect, useState } from "react";
function useAsync(callback, args) {
const [data, setData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const fetchData = async () => {
try {
setIsLoading(true);
const responseData = await callback(args);
setData(responseData);
} catch (err) {
setError(err);
}
setIsLoading(false);
};
useEffect(() => {
fetchData();
}, [args]);
return { data, isLoading, error };
}
export default useAsync;
// example.jsx
import React, { useEffect, useRef, useState } from "react";
import axios from "axios";
import useAsync from "../hooks/useAsync";
function Example() {
const inputRef = useRef(1);
const [postId, setPostId] = useState(1);
const getPost = async (id) => {
const response = await axios.get(`/posts/${id}`);
return response.data;
};
const { isLoading, data: post, error } = useAsync(getPost, postId);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>{error.message}</div>;
return (
<div>
<input ref={inputRef}></input>
<button onClick={() => setPostId(inputRef.current.value)}>검색</button>
<div key={post.id}>
<h1>
{post.id}번 글: {post.title}
</h1>
<p>작성자: {post.userId}</p>
<p>{post.body}</p>
</div>
</div>
);
}
export default Example;