Fetch와 Axios
📌 정의
Promise 기반의 HTTP 클라이언트
백엔드 또는 서드파티 API에 네트워크 요청이 필요한 애플리케이션을 개발할 때 사용하며, 네트워크에 요청을 전달하면 이행 혹은 거부할 수 있는 promise 가 반환된다.
📢 두 클라이언트 모두 비동기
🔍 Promise
비동기 작업을 수행한 후 미래에 받을 성공 또는 실패에 대한 결과값에 대한 처리기
비동기 작업은 실행 시점에는 그 결과를 알 수 없지만, 특정 시점에 완료 또는 실패에 대한 결과를 가져야 한다. 이를 위해 Promise 를 사용할 수 있으며, 마치 동기 메서드처럼 값을 반환할 수 있다. 다만, 최종 결과를 반환하는 것이 아니고 미래의 어떤 시점에 결과를 제공하겠다는 약속을 반환한다.
✔ Promise 상태
- 대기(pending): 이행하지도, 거부하지도 않은 초기 상태
- 이행(fulfilled): 연산이 성공적으로 완료됨
- 거부(rejected): 연산이 실패함
대기 중인 프로미스는 값과 함께 이행할 수도, 어떤 이유로 인해 거부될 수도 있다. 이행이나 거부될 때, 프로미스의 then 메서드에 의해 대기열(큐)에 추가된 처리기들이
호출된다.
📌 문법
🔍 Fetch
fetch는 두 개의 인자를 받는다. 첫 번째는 가져오고자 하는 리소스의 URL이다. 두 번째 인자는 요청의 설정 옵션을 포함하는 객체로 선택 인자다. 설정 옵션을
달아주지 않을 경우 기본적으로 GET 요청을 수행한다.
fetch(url); //기본 형태
//커스텀 형태
fetch(url, {
method: 'POST' //GET, PUT, DELETE ...
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({})
});
🔍 Axios
마찬가지로 method를 따로 지정하지 않을 경우 GET 요청을 수행한다.
//기본 형태
axios(url, {
//설정 옵션
});
//커스텀 형태 1
axios(url, {
method: 'get',
headers: {},
data: {
name: 'kim'
},
});
//커스텀 형태 2
axios({
method: 'get',
url: '',
headers: {},
data: {
name: 'kim'
},
});
✔ Axios 단축 메서드
아래와 같이 단축된 형태로 작성할 수도 있다.
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]]) axios.patch(url[, data[, config]])
📌 응답 데이터
(예제)
'localhost:8080/posts' 라는 곳에 GET 요청을 한 후, 그 결과로 받은 JSON 데이터를 posts에 저장
🔍 Fetch
fetch() 는 .then 메서드를 두 번 호출했다. .then을 할 때마다 promise 데이터가 반환되는데, 처음 반환되는 응답(res)는 JSON 형태가 아니다.
그래서 한번 변환(.json())을 이행한 JSON 데이터를 두 번째 .then에서 state에 담은 것이다.
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('http://localhost:8080/posts', {
method: 'GET',
})
.then((res) => res.json())
.then((res) => {
setPosts(res);
})
.catch((error) => {
console.log(error);
});
}, []);
🔍 Axios
axios()는 기본적으로 응답 데이터를 JSON 타입으로 사용할 수 있다. 응답 데이터는 언제나 응답 객체의 data 프로퍼티에서 사용할 수 있다.
const [posts, setPosts] = useState([]);
useEffect(() => {
async function getData() {
await axios
.get('http://localhost:8080/posts')
.then((res) => setPosts(res.data))
.catch((error) => console.log(error));
}
}, []);
(예제)
'localhost:8080/login' 라는 곳으로 data 를 담아 POST 요청
🔍 Fetch
Fetch는 데이터를 자동으로 문자열로 변환해주지 않기 때문에 JSON.stringify() 를 사용한 후에 body에 할당해야 한다.
const data = {
loginId: loginId,
password: password,
};
fetch('http://localhost:8080/login', {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((res) => res.json())
.then((data) => console.log(data))
.catch((error) => console.log(error));
🔍 Axios
POST 요청 시에도 기본적으로 'Content-Type' 을 'application/json' 으로 설정한다.
const data = {
loginId: loginId,
password: password,
};
await axios
.post('http://localhost:8080/login', data)
.then((data) => console.log(data))
.catch((error) => console.log(error));
🚖 Axios 의 params vs data
아래 코드처럼 작성할 경우 POST 요청이 성공하긴 한다. 하지만 요청 URL을 보면 쿼리 스트링 형태로 전달이 된다.
일반적으로 POST 요청은 body에 데이터를 담아 전송하므로, 위의 예제처럼 작성해야 한다.
await axios .post('http://localhost:8080/login', null, { params: { 'loginId': loginId, 'password': password, } }) .then((data) => console.log(data)) .catch((error) => console.log(error));
📌 예외처리
Fetch와 Axios 모두 이행되거나 거부된 promise 를 반환한다. Promise가 거부되면 catch()를 통해 처리할 수 있다.
Axios의 promise는 2xx번대가 아닌 응답이 내려오면 거부한다. 해당 에러에 대한 자세한 정보는 에러 객체(error)를 확인하여 알 수 있다.
Fetch는 네트워크 장애가 발생한 경우에만 promise를 거부한다.
- error.request: 요청이 수행되었지만 클라이언트가 응답을 받지 못했음을 의미
- error.response: 클라이언트가 2xx번대를 벗어나는 상태 코드를 가진 에러를 받았음을 의미
- error.response.status: 에러 상태 코드
- error.message: 에러 메시지
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://velog.io/@eunbinn/Axios-vs-Fetch#%EB%AC%B8%EB%B2%95