
동기 vs 비동기 · 콜백 · Promise · async/await · fetch · axios · 이벤트 루프
function sayHello() {
console.log('Hello World!');
}
sayHello();
console.log('end!');
// 순서대로 Hello World! → end! 출력
function sayHello() {
console.log('Hello World!');
}
// 비동기 예제
setTimeout(sayHello, 3000);
console.log('end!');
// 바로 'end!' 가 찍히고, 3초 뒤에 'Hello World!' 출력
function increase(number, callback) {
setTimeout(() => {
const result = number + 10;
if (callback) callback(result);
}, 1000);
}
increase(0, result => {
console.log(result);
});
콜백 안에서 다시 콜백을 호출하는 구조가 계속 중첩되면서
가독성이 급격히 떨어지는 현상.
increase(0, r1 => {
console.log(r1);
increase(r1, r2 => {
console.log(r2);
increase(r2, r3 => {
console.log(r3);
// 계속 중첩...
});
});
});
문제점
→ 이 문제를 해결하기 위해 Promise, async/await 사용
ES6 에서 도입된 비동기 상태 관리 객체
세 가지 상태
pending (대기)fulfilled (성공, resolve 호출)rejected (실패, reject 호출)이후에 결과를 .then() / .catch() 로 처리
function increase(number) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const result = number + 10;
if (result > 30) {
return reject(new Error('NumberTooBig'));
}
resolve(result);
}, 1000);
});
}
increase(0)
.then(n1 => {
console.log(n1);
return increase(n1);
})
.then(n2 => {
console.log(n2);
return increase(n2);
})
.then(n3 => {
console.log(n3);
return increase(n3);
})
.catch(e => {
console.log(e); // 에러는 한 곳에서 처리
});
장점
.catch() 하나로 처리 가능async 키워드가 붙은 함수는 항상 Promise 반환await 는 Promise 가 resolve 될 때까지 기다렸다가 그 값을 반환await 는 async 함수 안에서만 사용 가능function increase(number) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const result = number + 10;
if (result > 30) {
return reject(new Error('NumberTooBig'));
}
resolve(result);
}, 1000);
});
}
async function run() {
try {
let result = await increase(0);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result);
console.log(result);
result = await increase(result); // 여기서 에러
console.log(result);
} catch (e) {
console.log(e); // try/catch 로 동기 코드처럼 에러 처리
}
}
run();
장점
try / catch 로 에러 처리fetch(url) → Promise 반환response.json() / response.text() 도 Promise 반환async function callAPI() {
// HTTP 요청
const response = await fetch(
'https://jsonplaceholder.typicode.com/users'
);
console.log(response);
console.log(`bodyUsed: ${response.bodyUsed}`);
// JSON 파싱
const data = await response.json();
console.log(data);
console.log(`bodyUsed: ${response.bodyUsed}`);
}
callAPI();
흐름
fetch 로 요청 전송response 객체 반환response.json() 으로 JSON 파싱 (또 하나의 비동기 작업)같은 작업을 then 체이닝으로 작성할 수도 있다.
function callAPI() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => {
console.log(response);
console.log(`bodyUsed: ${response.bodyUsed}`);
return response.json();
})
.then(data => {
console.log(data);
});
}
callAPI();
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
axios
.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
console.log('axios response:', response);
console.log('axios data:', response.data); // 바로 data 사용
});
</script>
특징
response.data 에 바로 파싱된 데이터가 들어감이벤트 루프의 역할
스택이 비어 있고 큐에 콜백이 있다면
setTimeout 예시에서 일어나는 흐름
setTimeout(callback, 1000) 호출핵심 포인트
블로킹(blocking)
논블로킹(non-blocking)
fetch, setTimeout 콜백 등