동기란
동기란 여러 작업이 있을 때 이 작업들을 순서대로 한 번에 하나씩 처리하는 방식을 말합니다.
쉽게 말해, 앞에 있는 작업이 끝나야만 다음 작업을 시작할 수 있는 구조입니다.
예를 들어, A작업, B작업, C작업이 있다고 가정해 보겠습니다. 동기 방식에서는 다음과 같은 순서로 작업이 진행됩니다:
'' A작업 시작 -> A작업 종료 -> B작업 시작 -> B작업 종료 -> C작업 시작 -> C작업 종료 ''
이 작업들을 실제로 실행하고 처리하는 역할을 하는 것이 바로 쓰레드(Thread)입니다.
장점
코드의 가독성이 높습니다. 순서대로 실행되기 때문에 로직의 흐름을 이해하기 쉽습니다.
단점
작업 중 하나라도 오래 걸리면, 전체 프로그램이 멈춘 것처럼 보일 수 있습니다.
예를 들어, A작업이 5초 걸린다면, 그 시간 동안 다른 작업은 아무것도 할 수 없습니다.
자바나 C# 같은 언어들은 멀티쓰레드 기법을 사용하여 이런 문제를 해결할 수 있습니다.
하지만 자바스크립트는 단일 쓰레드 기반 언어이기 때문에 같은 방식으로 문제를 해결하지는 않습니다.
비동기란
비동기는 동기와 반대로, 여러 작업을 순서대로 처리하지 않는 방식입니다.
앞선 작업이 끝나기를 기다리지 않고, 다른 작업을 동시에 진행할 수 있습니다.
예를 들어, A작업, B작업, C작업이 있을 때 비동기 방식에서는 A작업이 끝나지 않아도 B작업과 C작업을 동시에 처리할 수 있습니다.
특징
- 작업이 끝나면 그 결과를 받아 다음 작업을 이어서 처리할 수 있습니다.
- 자바스크립트에서는 이를 콜백 함수나 Promise, Async/Await로 구현할 수 있습니다.
자바스크립트가 비동기를 처리하는 방법
자바스크립트는 단일 쓰레드 기반 언어라서 쓰레드가 하나뿐입니다. 그럼에도 비동기를 처리할 수 있는 이유는 브라우저의 Web APIs라는 공간 덕분입니다.
Web APIs란 무엇인가요?
- Web APIs는 브라우저가 관리하는 별도의 공간으로, 비동기 작업이 실행되는 곳입니다.
- 자바스크립트 엔진이 비동기 작업을 발견하면 Web APIs에 넘겨서 실행하고, 나머지 작업은 계속 진행합니다.
- 비동기 작업이 완료되면 Web APIs가 콜백 함수를 다시 자바스크립트 엔진에 전달하여 실행하게 됩니다.
비동기 - 콜백 함수
콜백 함수는 어떤 일이 끝났을 때 "이거 해줘!"라고 지정한 다음 실행될 코드를 말합니다.
예를 들어, 친구에게 "숙제 끝나면 알려줘. 그러면 나도 게임할게!"라고 부탁하는 것과 비슷합니다.
콜백 함수가 왜 필요할까요?
자바스크립트는 한 번에 하나씩 작업을 처리하기 때문에, 오래 걸리는 작업이 있으면 다른 작업을 먼저 처리해야 효율적입니다. 이때 콜백 함수를 이용해 작업이 끝났을 때 실행할 동작을 지정할 수 있습니다.
아래 코드는 setTimeout을 사용해 특정 시간 후에 실행할 작업을 지정한 예제입니다:
console.log("A");
setTimeout(() => {
console.log("B");
}, 2000);
console.log("C");
//실행결과:
// A
// C
// B
setTimeout은 2초 후에 실행될 작업을 예약하고, 그동안 다른 작업(A와 C)을 먼저 처리하기 때문에 출력결과는 아래와 같습니다.
콜백 함수의 종류
- 타이머 관련 콜백: setTimeout, setInterval
setTimeout(() => console.log("2초 뒤 실행!"), 2000);
- 이벤트 핸들러: 클릭, 키 입력 같은 이벤트가 발생했을 때 실행
document.querySelector("button").addEventListener("click", () => { console.log("버튼 클릭됨!"); });
- 비동기 작업 콜백: 네트워크 요청 등
fetch("https://api.example.com/data") .then(response => response.json()) .then(data => console.log(data));
콜백 지옥이란?
콜백을 너무 많이 쓰면 인덴트(indent:들여 쓰기)가 점점 깊어지는 형태로 코드가 진화를 하는데 이렇게 계속 작성되면
코드가 복잡해져서 읽기 어려울 때가 있습니다. 코드가 이런 상황을 "콜백 지옥"이라고 부릅니다.
예를 들어, 이런 코드는 읽기가 매우 어렵습니다:
asyncTask1(() => {
asyncTask2(() => {
asyncTask3(() => {
console.log("끝!");
});
});
});
이런 문제를 해결하기 위해 Promise와 Async/Await가 등장했습니다.
비동기 - Promise
Promise는 자바스크립트에서 비동기 작업을 효율적으로 처리하기 위해 제공되는 내장 객체입니다.
Promise의 상태
Promise는 네 가지 상태로 나뉩니다:
- 대기(Pending): 아직 비동기 작업이 진행 중인 상태입니다.
- 해결(Resolve): 비동기 작업이 성공적으로 완료되어 성공 상태로 바뀌는 것입니다.
- 거부(Reject): 비동기 작업이 모종의 이유로 실패해서 실패 상태로 바뀌는 것입니다.
- 종료(Fulfilled): 성공 상태로 완료된 최종 상태입니다.
function delay(ms) {
return new Promise((resolve)=>{
setTimeout(()=>{
resolve(); // 비동기 작업이 끝났음을 알려야함
},ms)
})
}
async function main() {
console.log("3초 후 결과를 공개하겠습니다!");
await delay(3000);
console.log("승자는 아무개!");
}
main();
// 출력 결과 :
// 3초 후 결과를 공개하겠습니다!
// 승자는 아무개!
Promise의 메서드 사용법
then 메서드는 Promise가 성공적으로 완료되었을 때 실행되는 메서드입니다.
이 메서드를 사용하면 비동기 작업의 결과를 처리할 수 있습니다.
반대로, catch 메서드는 비동기 작업이 실패했을 때 호출됩니다.
이 두 메서드는 함께 사용하여 성공과 실패를 모두 처리할 수 있습니다.
추가로, then 메서드는 호출 결과가 해당 Promise 객체를 그대로 다시 반환합니다.
그래서 뒤에 catch 메서드를 따로 부르는 것이 아니라 연결해서 호출할 수도 있습니다.
아래는 Promise를 사용하는 간단한 예제입니다:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const num = 10;
if (typeof num === "number") {
resolve(num + 10);
} else {
reject("num이 숫자가 아닙니다");
}
}, 2000);
});
promise
.then((value) => {
console.log(value);
})
.catch((error) => {
console.log(error);
});
Promise 체이닝
then 메서드는 결과를 다음 then으로 전달할 수 있습니다.
이렇게 체인 형태로 연결하는 것을 "Promise 체이닝"이라고 합니다.
promise
.then((value) => {
console.log(value);
return value + 10;
})
.then((newValue) => {
console.log(newValue);
})
.catch((error) => {
console.log(error);
});
비동기 - Async/Await
Async란?
async는 함수 앞에 붙이는 키워드로, 해당 함수를 비동기 함수로 만들어줍니다.
비동기 함수는 항상 Promise를 반환합니다.
함수 선언문 앞에 async를 붙이면, 함수는 객체를 그대로 반환하는 대신, 그 객체를 결괏값으로 가진 Promise를 반환하게 됩니다.
Await란?
await는 비동기 함수가 완료될 때까지 기다리는 키워드입니다. 이 키워드는 async 함수 내부에서만 사용할 수 있습니다.
Async/Await 예제
async function fetchData() {
console.log("데이터를 가져오는 중입니다...");
const data = await new Promise((resolve) => {
setTimeout(() => {
resolve("가져온 데이터: 사용자 정보");
}, 3000);
});
console.log(data);
console.log("데이터 가져오기 완료!");
}
fetchData();
'DEVELOPMENT > JavaScript' 카테고리의 다른 글
[JS] 프로미스 (Promise) (1) | 2025.02.20 |
---|---|
[JS] 콜백 (Callback) (0) | 2025.02.20 |
[JS] 나를 위한 배열과 Date 메서드 컨닝페이퍼 (1) | 2025.01.22 |
[JS] 정규표현식 (RegExp) (0) | 2024.06.21 |
[JS] let,const 와 var (2) | 2024.05.22 |