이전 프로젝트에서는 서버와 통신해서 데이터를 받아오는 과정에 대해 비동기라는 인식이 부족했다. 이번에 비동기에 대한 이해를 제대로 짚고 넘어가자는 생각이 있었다.
// src/api/users/get.js
import axios from 'axios';
const url = process.env.REACT_APP_PUBLIC_API_URL;
export async function getUsersApi(payload) {
const token = localStorage.getItem('login-token');
const data = await axios.get(url + '/user', {
params: payload,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
});
return data;
}
user 페이지에서 data를 받아오는 로직을 나타내는 get.js 파일이다.
axios.get() 함수를 통해 데이터를 받아오면 원래 promise 형태로 반환된다.
async await
받아온 promise에 대해 동기적인 형태로 처리하는 다른 방식이 있는데 그것이 async await다.
getUsersApi 함수에 async를 붙이고 비동기 axios 함수에 await를 붙이면 result라는 변수에는 Promise 객체가 아닌 서버에서 보내주는 실질적인 data가 담긴다.
그러나, await를 사용안하고 바로 result에 담으면 Promise 객체가 담긴다.
이 getUsersApi()
를 다른 js 파일에서 import해서 가져오면,
// src/hooks/useFetch.js
import { getUsersApi } from 'api/user/get';
//중략
const fetchData = async (order_type, sort_type) => {
switch (page) {
case 'userinfo':
const payloadUser = {
...store.userFilter,
page: currentPage,
perPage: perPage,
pagination: 'Y',
order: order_type,
sort: sort_type,
};
const result = await getUsersApi(payloadUser);
// console.log('result', result)
try {
setBuckets(result.data.data);
setTotalPage(result.data.total);
} catch ({ response }) {
if (response.status === 401) {
logout();
}
}
똑같이 getUsersApi
함수 앞에 await를 사용해서 result에 담으면 실제 data가 담긴다.
그러나, await를 사용하지 않고 담으면 Promise 객체가 담겼다. (getUserApi 내부는 async await 형태임에도 불구하고!)
이 부분이 이해가 안되어서 console.log()를 통해 로직 순서를 확인해 봤다.
먼저 getUsersApi
앞에 await를 지우고 다음줄에 console.log로 result를 찍었다.
// src/api/users/get.js
const result = getUsersApi(payloadUser);
console.log('result', result);
그리고 getUsersApi
로직 내부에서는 axios() 이후 코드 줄에 console.log()를 추가했다.
// src/hooks/useFetch.js
import axios from 'axios';
const url = process.env.REACT_APP_PUBLIC_API_URL;
export async function getUsersApi(payload) {
console.log('비동기 시작');
const token = localStorage.getItem('login-token');
const data = await axios.get(url + '/user', {
params: payload,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
});
console.log('비동기 종료');
console.log('result', data);
return data;
}
원래 내가 이해한대로라면 getUsersApi
가 호출되었을 때, getUsersApi
내부에서 console이 차례대로 찍히고 나서, get.js에서 console.log('result', result)가 찍혀야했다고 생각했다.
그러나 결과는 다음과 같았다.
즉 getUsersApi
호출하고 내부에서 await를 기다리는 동안 바로 return이 일어났고 그 return 값에는 Promise 객체가 담긴다.
이 Promise 객체안에는 data가 담겨져 있었다.
그 후, 기다렸던 data가 담기고 getUsersApi
내부 로직이 종료되었다.
⇒ 결국, async 함수는 무조건 Promise 객체를 반환하며, axios 비동기 함수와 같은 원리로 동작한다. 그래서 반환 값이 promise 였던 것.