- Axios와 Fetch, 나의 선택은?
데이터를 API 요청으로 받을 시간이 왔다. Axios를 사용한 기억이 있는데, fetch가 있다고 한다. 둘 중에 뭐를 사용하면 좋을까? 아무래도 API 요청은 핵심적인 기능이고 자주 사용하다보니 잘 선택하고 싶다. 일단 둘을 비교해보자.
기능/특성 | fetch | axios |
설치 필요 여부 | 브라우저 내장 | 별도 설치 필요 |
기본 기능 | 네트워크 요청 기능만 제공 | JSON 파싱, 상태 코드 처리, 요청 취소 등 다양한 기능 포함 |
에러 핸들링 | 네트워크 에러만 캐치, 상태 코드 에러 직접처리 필요 | 모든 에러 자동 처리 |
요청 취소 | AbortController 사용 | 기본 제공 |
응답 데이터 변화 | 수동으로 변환(ex. response.json()) | 자동변환(JSON 데이터) |
fetch는 브라우저 내장이 가장 큰 매력일 것 같다. 프로그램의 무게를 줄이고 싶어 fetch를 선택했는데, 막상 에러처리와 같은 부분에서는 response 의 상태코드가 200이 아니더라도 반환하기 때문에, 이를 처리하는 과정도 꽤나 번거로웠다. axios는 자동으로 처리해주니 다음에는 사용을 고려해봐야 겠다.
async function createPayment(token, req){
try {
// POST 요청을 보내기 위한 설정
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(req),
};
const response = await fetch(apiUrl + 'order/v1/payments', requestOptions);
const data = await response.json();
console.log(data);
if (!response.ok) {
throw data.error_code;
}
return data;
} catch (error) {
console.error('데이터를 가져오는 중 오류 발생:', error);
throw error;
}
}
위 코드는 유저가 결제 버튼을 누를 때 payment 를 생성하는 요청하는 것이다. requestOptions에 method나 header 그리고 body를 넣는다. 그리고 fetch를 통해 request 한다. async/await를 사용하여 비동기로 처리해준다. 응답이 오면 response에 데이터가 할당되고, 이 response가 200이 아니면 error를 던지도록 한다. 그 외 제대로 왔으면 response를 json으로 바꾸어주고 이를 반환한다.
- 데이터를 받는 시간 동안 유저는 떠나.. Loading 페이지 추가
데이터를 비동기로 받을 때, 요청을 클릭하고 사용자 환경에 따라 지연이 발생한다. 이 때, 화면에 변화가 없으면 유저는 다시 버튼을 클릭한다. 사실 나는 몇 초 후에 버튼을 누를 줄 알았지만, 유저 테스트를 통해 지켜본 바, 거의 1초가 되기전 다시 누른다... 그래서 지연이 발생하는 데이터 송 수신 쪽은 Loading page가 필요했다. Loading Page를 추가함으로써 훨씬 자연스러운 UX가 완성된다.
const Login = () => {
...
const login = async () => {
if (checkInfo()) {
setIsLoading(true);
try {
setPersistence(firebaseAuth, browserLocalPersistence)
.then(() => signInWithEmailAndPassword(firebaseAuth, userEmail, userPassword))
.then(async (userCredential) => {
if (userCredential) {
try {
await generateToken(userCredential.user);
} catch (error) {
console.log(error);
throw error;
}
} else {
alert("다시 로그인을 시도해주세요.");
}
})
.then(() => {
setIsLoading(false);
})
.then(()=>{
navigate('/', { state: { snackBar: true } });
})
.catch((error) => {
console.log(error);
setIsLoading(false);
const errorCode = error.code;
switch (errorCode) {
case 'auth/user-not-found':
setErrMsg('입력한 아이디는 없는 아이디입니다.');
break;
case 'auth/wrong-password':
setErrMsg('비밀번호가 일치하지 않습니다.');
break;
case 'auth/invalid-login-credentials':
setErrMsg("아이디 혹은 비밀번호 정보를 정확하지 않습니다.");
break;
default:
setErrMsg("로그인에 실패하였습니다. 이메일 인증을 진행했는지 확인해주세요.");
}
});
} catch (err) {
console.log(err.code);
alert("로그인에 실패하였습니다.");
setUserEmail('');
setUserPassword('');
setIsLoading(false);
}
}
}
...
return(
<div id="child">
<Snackbar
open={open}
onClose={() => setOpen(false)}
message="회원가입에 성공하였습니다. 가입하신 이메일로 이동하셔서 인증을 하셔야 정상적으로 로그인 할 수 있습니다."
autoHideDuration={6000}
anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
/>
{isLoading ? <LoadingScreen></LoadingScreen> :
...
)
}
export default Login;
위 코드를 보면 로그인을 시작 할 때, isLoading이라는 값을 true로 바꾸고 화면에는 LoadingScreen 컴포넌트가 마운트 되며 보여진다. 그리고 로그인이 마무리 될 때, isLoading은 false가 되고 화면에는 LoadingScreen 컴포넌트가 언마운트 되어진다.
'개발 > STUDY' 카테고리의 다른 글
useEffect (0) | 2024.05.26 |
---|---|
React 파일 구조 (0) | 2024.05.25 |
CSR과 SSR (0) | 2024.05.23 |
브라우저 동작 방법 (0) | 2024.05.23 |
프로토타입 (0) | 2024.05.23 |