JavaScript는 한 번에 하나의 기능만 수행하는 싱글 스레드 기반의 언어다. 때문에 동기적으로 동작한다.
(코드가 작성된 순서대로 작업을 처리한다)
동기(Synchronous)
: 하나의 작업이 종료될 때까지 다음 동작을 기다리는 실행 방식
console.log(1)
console.log(2)
console.log(3)
// 1,2,3
비동기(Asynchronous)
: 하나의 작업이 진행됨과 동시에 또 다른 작업도 함께 진행되는 방식
비동기는 프로그램의 응답성을 높이는데 도움을 준다.
자바스크립트는 예외적으로 비동기처리방식도 존재한다
console.log(1)
setTimeout(() => {
console.log(2)
}, 2000)
console.log(3)
// 1,3,2
실생활과 연관지어 쉽게 이해해보자.
동기
: 음식점에 갔더니 직원이 한명이었다. 나는 이전사람의 메뉴가 나오고 나서야 주문할 수 있었다.
비동기
: 음식점에 가서 주문을 했다. 이전 사람의 메뉴가 나오기 전 내가 주문한 메뉴가 나와 벨이 울렸고 먼저 받을 수 있었다
JavaScript의 실행환경
Call Stack
: LIFO(Last In First Out)으로 내부 데이터가 처리된다. 먼저 들어온 함수, 데이터가 먼저 처리된다.
Callback Queue
: FIFO(First In First Out)으로 내부 데이터가 처리된다. 먼저 들어온 함수, 데이터가 먼저 처리된다.
기본적인 함수들은 모두 call stack에 쌓이고 비동기 함수(Web APIs 포함)들은 모두 callback queue에 쌓인다.
call stack에 쌓인 기본 함수들은 먼저 담긴 함수들의 종료를 기다리고, callback queue에 쌓인 비동기 함수들은 call stack이 비워져 있다면 그 때 call stack으로 하나씩 옮겨 실행된다.
아래의 코드를 실행하면 setTimeout 함수는 비동기 함수이므로 지연 시간을 지정해주지 않았음에도 불구하고 callback queue 영역으로 옮겨져 실행된다.
setTimeout(() => {
console.log("setTimeout call")
})
const func3 = function() {
console.log("func3")
}
const func2 = function() {
func3()
console.log("func2")
}
const func1 = function() {
func2()
console.log("func1")
}
func1()
// 실행순서: func3, func2, func1, setTimeout call
자바스크립트는 동기적으로 동작하는 언어라고 했다. 그러나 어떠한 코드로 인해 다음 함수의 실행이 중단되고(Blocking) 동작에 지장을 주게 된다면 해당 웹사이트의 유저 이탈로 이어질 수 있다.
자바스크립트의 한계점을 해결하기 위한 해결책
1. 콜백함수
파라미터로 함수를 전달 받아 함수의 내부에서 실행하는 함수
함수를 등록하기만 하고 어떠한 이벤트가 발생했거나 특정 시점에 도달했을 때 호출하는 함수
필요에 따라 callback 함수를 비동기적으로 실행할 수도 있다
function userID(name){
alert(`userID is ${name}`);
}
userID('syong')
function fn() {
setTimeout(() => {
console.log(1);
setTimeout(() => {
console.log(2);
setTimeout(() => {
console.log(3);
}, 0);
}, 0);
}, 0);
}
fn();
콜백 함수가 여러번 중첩되는 경우 위의 코드와 같이 콜백 지옥을 만들고, 코드의 가독성을 떨어트리는 원인이 된다.
2. Promise
비동기 처리를 위해 사용되는 객체. ES6에 도입되었다.
현재는 얻을 수 없지만, 추후 작업 완료시에 받아올 수 있는 데이터에 대한 접근 수단의 역할을 해준다
Promise는 인자로 콜백을 받는다.
함수 실행시에는 Promise 객체를 돌려 받는다.
Promise 객체 생성시에 내부에 함수를 인자로 넣어줄 수 있다. 이때 내부 함수는 resolve
와 reject
를 매개변수로 받아올 수 있다
Promise 객체 생성
const promise = new Promise(function(resolve, reject) { ….. }):
Promise 객체의 3가지 상태
- 대기(Pending) : 비동기 처리가 아직 완료되지 않은 상태
resolve
나reject
가 호출되기 전까지의 상태
- 이행(Fulfilled) : 비동기 처리가 완료되어 결과값을 반환해준 상태
- resolve 호출
- 실패(Rejected) : 비동기 처리가 실패 혹은 오류가 발생한 상태
- reject 호출
이행 상태가 되면 아래와 같이 then()메서드를 이용하여 처리 결과 값을 받을 수 있다
const sleep = function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100)
}, 2000);
});
};
sleep().then((sleepParam) => {
console.log('sleepParam')
});
실패 상태가 되면 실패한 이유(실패 처리의 결과 값)를 catch()메서드를 통하여 받을 수 있다
const sleep = function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100)
}, 2000);
});
};
sleep().catch((err) => {
console.log(err)
});
참고
본 글은 훈훈한 자바스크립트 강의의 내용과 참고글을 참고해 정리한 글입니다
'Frontend > JavaScript' 카테고리의 다른 글
[JS] 얕은 복사, 깊은 복사 (0) | 2023.04.16 |
---|---|
[JS] 구조분해할당 (destructuring assignment) (0) | 2023.04.13 |
[JS] 변수와 함수의 호이스팅(Hoisting) (0) | 2023.04.09 |
[JS] 스코프란? 전역스코프, 지역스코프, 스코프 체인 (1) | 2023.04.08 |
[JS] Event (1) - 이벤트, 이벤트 종류, 이벤트 사용방법 (0) | 2023.04.07 |