JavaScript는 웹 개발에서 널리 사용되는 언어로, 비동기 처리 방식이 중요한 특징 중 하나입니다. 비동기 처리는 서버 요청, 파일 읽기, 타이머와 같은 작업을 효율적으로 처리할 수 있도록 돕습니다. 이 글에서는 JavaScript의 비동기 처리 방법에 대해 살펴보겠습니다.
동기(Synchronous)와 비동기(Asynchronous)의 차이
동기 처리
동기(synchronous)는 작업이 순차적으로 진행되며, 하나의 작업이 완료되기 전까지 다음 작업이 실행되지 않는 방식입니다.
console.log('첫 번째 작업 시작');
console.log('두 번째 작업 시작');
console.log('세 번째 작업 시작');
위 코드는 순차적으로 실행되며, 출력 결과는 항상 같은 순서로 나타납니다.
비동기 처리
비동기(asynchronous)는 작업이 백그라운드에서 실행되고, 실행이 끝나면 나중에 결과를 가져오는 방식입니다. 이렇게 하면 프로그램이 특정 작업이 완료될 때까지 기다릴 필요가 없어 효율적입니다.
console.log('첫 번째 작업 시작');
setTimeout(() => {
console.log('비동기 작업 완료');
}, 1000);
console.log('세 번째 작업 시작');
위 코드의 출력은 다음과 같습니다:
첫 번째 작업 시작
세 번째 작업 시작
비동기 작업 완료
setTimeout 함수는 비동기 함수의 대표적인 예로, 1초 후 콜백 함수를 실행하지만, 그동안 다른 작업은 멈추지 않습니다.
콜백 함수
콜백 함수는 다른 함수의 인수로 전달되어 작업이 완료된 후 호출되는 함수입니다. JavaScript의 비동기 프로그래밍에서 콜백은 중요한 역할을 합니다.
콜백 함수 예제
function fetchData(callback) {
setTimeout(() => {
const data = { userId: 1, name: '홍길동' };
callback(data);
}, 1000);
}
function handleData(data) {
console.log(`사용자 ID: ${data.userId}, 이름: ${data.name}`);
}
fetchData(handleData);
위 코드는 fetchData 함수가 1초 동안 데이터를 "가져오는" 작업을 시뮬레이션하고, 완료되면 handleData 콜백 함수를 호출합니다.
콜백 지옥
콜백 함수는 간단한 비동기 작업에 적합하지만, 여러 개의 비동기 작업을 중첩하여 사용할 경우 코드가 복잡해지는 "콜백 지옥"이 발생할 수 있습니다.
getUser(userId, (user) => {
getPosts(user.id, (posts) => {
getComments(posts[0].id, (comments) => {
console.log(comments);
});
});
});
이 문제를 해결하기 위해 Promise와 async/await가 도입되었습니다.
Promise
Promise는 비동기 작업의 결과를 나타내는 객체로, 성공(resolve) 또는 실패(reject) 상태를 가질 수 있습니다. 이를 통해 콜백 지옥 문제를 해결할 수 있습니다.
Promise 생성 및 사용
const fetchUser = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const user = { id: 1, name: '홍길동' };
resolve(user); // 성공 시 호출
}, 1000);
});
};
fetchUser()
.then((user) => {
console.log(`사용자 이름: ${user.name}`);
})
.catch((error) => {
console.error(`에러 발생: ${error}`);
});
Promise 체이닝
then 메서드를 연결하여 연속적인 비동기 작업을 처리할 수 있습니다.
fetchUser()
.then((user) => {
console.log(`사용자 ID: ${user.id}`);
return fetchPosts(user.id);
})
.then((posts) => {
console.log(`포스트 제목: ${posts[0].title}`);
})
.catch((error) => {
console.error(`에러 발생: ${error}`);
});
async/await
async/await는 Promise 기반의 비동기 작업을 동기식 코드처럼 작성할 수 있게 해주는 문법입니다.
async/await 사용법
const fetchUser = async () => {
return { id: 1, name: '홍길동' };
};
const main = async () => {
try {
const user = await fetchUser();
console.log(`사용자 이름: ${user.name}`);
} catch (error) {
console.error(`에러 발생: ${error}`);
}
};
main();
여러 비동기 작업 처리
await를 사용해 순차적으로 실행하거나 Promise.all로 병렬 실행을 처리할 수 있습니다.
순차 실행
const fetchUser = () =>
new Promise((resolve) => setTimeout(() => resolve({ id: 1, name: '홍길동' }), 1000));
const fetchPosts = (userId) =>
new Promise((resolve) => setTimeout(() => resolve([{ id: 1, title: '포스트 제목' }]), 1000));
const main = async () => {
const user = await fetchUser();
console.log(`사용자 이름: ${user.name}`);
const posts = await fetchPosts(user.id);
console.log(`포스트 제목: ${posts[0].title}`);
};
main();
병렬 실행
const fetchUser = () =>
new Promise((resolve) => setTimeout(() => resolve({ id: 1, name: '홍길동' }), 1000));
const fetchPosts = () =>
new Promise((resolve) => setTimeout(() => resolve([{ id: 1, title: '포스트 제목' }]), 1000));
const main = async () => {
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
console.log(`사용자 이름: ${user.name}`);
console.log(`포스트 제목: ${posts[0].title}`);
};
main();

'Language > JavaScript' 카테고리의 다른 글
| 스코프(Scope)와 호이스팅(Hoisting) (0) | 2023.10.13 |
|---|---|
| JavaScript의 클로저(Closure) (0) | 2023.10.13 |
| JavaScript로 DOM 조작하기 (0) | 2023.10.12 |
| javascript 객체(Object)와 배열(Array) (0) | 2023.10.12 |
| Javascript의 반복문과 함수 (0) | 2023.10.12 |