동기와 비동기 ?
동기
자바스크립트는 싱글스레드 언어이기 때문에 한 번에 하나의 작업만 수행할 수 있다. 이전 작업이 끝나야 다음 작업을 실행 할 수 있는 방식이다. 이러한 방식은 오랜 시간이 걸리는 네트워크 요청 등을 할 때 프로그램이 멈추는 단점이 있다.
비동기
자바스크립트는 동기의 단점을 해결하기 위해 비동기를 도입했다. 비동기는 코드의 실행 순서와 관계없이 작업을 실행하고, 작업이 완료되면 그 결과를 처리하는 방식이다. 주로 네트워크 요청에 많이 사용한다
위 사진을 참고하면 동기적으로 실행할 경우 27초가 걸리는 반면에 비동기적으로 실행하면 15초가 걸린다.
비동기는 웹에서 서버에 요청했을 때 요청이 완료되기 전까지 아무것도 실행되지 않는다면 화면이 멈춘 것 처럼 보일 뿐만 아니라 하나의 프로그램을
실행하는 데 많은 시간이 소요되기 때문이다. 또한 실행 순서가 중요할 때도 있다. 예를 들면 다른서 코드가 서버에 요청한 데이터 값을
이용해야 할 때는 데이터를 받아 온 후에 코드가 실행되는게 필요하다. 이럴때 사용하는 것이 비동기 처리다.
자바스크립트에서 비동기를 다루는 방법
1. Callback 함수
콜백함수는 파라미터로 전달받은 함수를 말한다. 파라미터로 함수를 전달받고 함수 내부에서 필요할 때 호출해서 사용할 수 있다.
주로 비동기 작업에서 사용되며, 작업이 완료되었을 때 결과를 처리하거나 다음 작업을 수행하기 위해 사용한다.
function callBackFunc(callback) {
setTimeout(() => {
console.log("3초")
},3000)
console.log('Hello')
}
callBackFunc()
setTimeout() 함수는 비동기 함수다. 그렇기 때문에 console.log("Hello")가 먼저 나오고 3초 뒤에 console.log("3초")가 나온다
콜백함수의 단점 🚫
- 콜백함수를 사용하다 보면 코드의 가독성과 관리가 어려워지는 콜백지옥이 생긴다.
getData(function(data) {
process(data, function(processedData) {
save(processedData, function() {
// ...
});
});
});
- 에러처리가 어렵고 어디서 에러가 났는지 알기가 어렵다.
2. Promise
콜백의 한계점을 극복하기 위해 Promise가 나왔다 Promise는 비동기 작업의 결과나 상태를 표현하는 객체로 표현한다.
Promise를 사용하면 ?
- 코드의 유지 보수성이 증가한다.
- 에러 처리가 용이해진다.
- Promise의 상태는 3가지의 상태와 결과를 가진다
- pending(대기): 처리가 완료되지 않은 상태
- fulfilled(이행): 성공적으로 처리가 완료된 상태
- rejected(거부) : 처리가 실패로 끝난 상태
간단하게 Promise 사용 예시를 알아보자.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = { id: 1, name: 'John' };
if (data) {
resolve(data); // 성공
} else {
reject(new Error('Error')); // 실패
}
}, 1000);
});
}
fetchData()
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});
프로미스는 성공 또는 실패만 해야한다.
3. async / await
프로미스도 다음과 같은 문제가 있엇다.
- 특정 조건에 따라 분기를 나누기가 어렵다.
- 어떤 부분에서 에러가 발생했는지 파악하기가 어렵다.
- 프로미스 체이닝도 반복되면 가독성이 떨어져
.then
지옥이 발생할 가능성이 있다.
이러한 문제를 해결하기 위해 async/await이 등장했 다. async/await은 프로미스를 기반으로 동작하고 프로미스의 후속 처리 메서드인 then 없이도 비동기를 동기처럼 보이도록 구현하는 방식이다. 보다 간결한 코드 작성을 위해 등장한 문법으로 프로미스보다 가독성이 좋고 로직이 물 흐르듯이 직관적인것처럼 보인다.
async/await의 장점
- 프로미스의 단점 극복: 프로미스에서 발생한 단점 중 하나인 콜백 헬과 체이닝 구조의 복잡성을 해결해준다.
- 에러 처리: try-catch를 사용해서 error 처리를 쉽게 할 수 있다.
- 가독성: 비동기코드를 동기적으로 흐르는 것처럼 작성할 수 있다.
async와 await의 의미
- async : async 함수는 항상 Promise를 반환한다.
- await : await 키워드는 비동기 작업의 완료를 기다리고, 해당 작업의 결과를 반환한다 await는 async 함수 내에서만 사용할 수 있다.✔
간단하게 async await 사용 예시를 알아보자.
async function fetchData() {
try {
const response = await fetch('api주소');
const data = await response.json();
return data;
} catch (error) {
console.error('Error', error);
}
}
async function process() {
const result = await fetchData();
console.log(result)
}
process();