웹 애플리케이션에서 서버의 API를 사용할 때 네트워크 송수신 과정에서 시간이 걸리기 때문에 작업이 즉시 처리되는 것이 아니라, 응답을 받을 때까지 기다렸다가 전달받은 응답 데이터를 처리한다
이 과정에서 해당 작업을 비동기적으로 처리하게 된다
동기적인 처리방식과 달리 비동기적으로 처리하게되면 웹 애플리케이션이 멈추지 않기 때문에 동시에 여러 가지 요청을 처리할 수도 있고, 기다리는 과정에서 다른 함수도 호출할 수 있다
서버 API를 호출할 때 외에도 비동기적으로 처리해야하는 경우는 setTimeout 함수를 사용해 특정 작업을 예약할 때다
function printMe() {
console.log('Hello World');
}
setTimeout(printMe, 3000);
console.log('대기 중...');
실행 결과
대기 중...
Hello World
setTimeout이 사용되는 시점에서 코드가 멈추지 않고 일단 위부터 아래까지 다 호출되고 3초 뒤에 printMe가 호출되는 것을 확인할 수 있다
JS에서 비동기 작업을 할 때 가장 흔히 사용하는 방법은 콜백 함수를 사용하는 것이다
위 코드에서는 printMe 함수 자체를 setTimeout의 인자로 전달해 주었다 👉 콜백 함수라고 한다
콜백 지옥 같은 코드가 형성되지 않게 하는 방안으로 ES6에 도입된 기능
function increase(number) {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const result = number + 10;
if (result > 50) {
const e = new Error("NumberTooBig");
return reject(e);
}
resolve(result);
}, 1000);
});
return promise;
}
increase(0)
.then((number) => {
// Promise에서 resolve된 값은 .then을 통해 받아 올 수 있음
console.log(number);
return increase(number);
})
.then((number) => {
console.log(number);
return increase(number);
})
.then((number) => {
console.log(number);
return increase(number);
})
.catch((e) => console.log(e)); // 도중에 에러가 발생한다면 .catch를 통해 알 수 있음
위와 같이 여러 작업을 처리해도 함수를 여러 번 감싸는 것이 아니라 .then
을 사용하기 때문에 콜백 지옥이 형성되지 않는다
Promise를 더욱 쉽게 사용할 수 있도록 해 주는 ES2017(ES8) 문법
함수의 앞부분에 async
키워드를 추가하고 해당 함수 내부에서 Promise의 앞부분에 await
키워드를 사용한다
Promise가 끝날 때까지 기다리고, 결과 값을 특정 변수에 담을 수 있다
function increase(number) {
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const result = number + 10;
if (result > 50) {
const e = new Error("NumberTooBig");
return reject(e);
}
resolve(result);
}, 1000);
});
return promise;
}
async function runTasks() {
// try-catch 구문을 사용하여 에러 처리
try {
let result = await increase(0);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result);
console.log(result);
} catch (e) {
console.log(e);
}
}
결론만 말하자면 useEffect에 등록하는 함수에 async를 붙이면 안 되고, useEffect 내부에서 async 키워드가 붙은 함수를 만들어 사용해야 한다
그렇게 해야하는 이뉴는 useEffect에서 반환해야 하는 값은 뒷정리 함수이기 때문이다
뒷정리 함수는 컴포넌트가 언마운트되거나 useEffect가 다시 실행될 때 이전에 실행된 작업을 정리하는 함수다
ex) 이벤트 리스너를 등록했다면 뒷정리 함수에서는 해당 리스너 제거
async 함수는 기본적으로 Promise를 반환하는데 useEffect는 Promise를 뒷정리 함수로 착각하기 때문에 리액트의 동작을 방해할 수 있다
axios는 현재 가장 많이 사용되고 있는 JS HTTP 클라이언트이며, HTTP 요청을 Promise 기반으로 처리한다는 특징이 있다
axios.get
함수는 파라미터로 전달된 주소에 GET 요청을 해 주고 .then
을 통해 결과를 비동기적으로 확인할 수 있다