주의. 자바스크립트에 대해 잘 알지 못하는 사람이 공부하려고 작성한 글이기 때문입니다.
내용이 부실하거나 잘못된 정보가 있을 수 있음. 내가 뭘 알아?
비동기 vs 동기
동기 : 주어진 일들을 순차적으로(직렬적으로) 수행하는 방식.
동기는 한 번에 하나의 업무만 할 수 있다. 한 업무가 끝나기 전까지 다른 업무는 중단된다.
만약 은행에 갔는데 직원이 1명이다. 그러면 번호표를 뽑은 우리는 앞 사람이 끝나기 전까지 은행 일을 볼 수가 없다.
매우 슬프지 않은가?
흔히 쓰는 코드는 대부분 동기로 일을 처리한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function func1() {
console.log('1번');
}
function func2() {
console.log('2번');
}
function func3() {
console.log('3번');
}
function func4() {
func1();
func2();
func3();
}
func4();
// 1번
// 2번
// 3번
func4()에 있는 아이들은 1번이 끝나야 2번, 2번이 끝나야 3번의 console.log를 가져오게 된다.
func1000이 있다면 이 추운. 싸늘하게 발견될 수도 있다.
아마 이렇게 초등학교 때 계주를 달리던 것 처럼.. 애타게 내 뒷 사람을 기다리는 것처럼.. func2는 그렇게 func1을 기다린다.. 그런데 당신은 느려서 계주한 기억이 없기에 공감을 못할 수도 있다.. ^__^..
비동기 : 주어진 일들을 동시에(병렬적으로) 수행하는 방식.
비동기는 동기와 다르다. 수행하던 일이 끝나지 않아도 다른 일을 시작할 수 있다.
자바스크립트의 대부분의 DOM 이벤트나 Timer 함수(setTimeout, setInterval)와 같은 것들이 비동기적으로 일을 하게 된다.
비동기로 일을 하게 되면 당신은 앞 사람을 기다리지 않아도 된다.
비동기의 대표적인 함수 setTimeout으로 위의 코드를 수정해봤다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function func1(string) {
setTimeout(() => {
console.log(string);
}, Math.floor(Math.random() * 100) + 1);
}
function func2() {
func1('1번');
func1('2번');
func1('3번');
}
// 항상 다름 1번 or 2번 or 3번
// 항상 다름 1번 or 2번 or 3번
// 항상 다름 1번 or 2번 or 3번
//
위에 코드는 func1,2,3이 동시에 일을 시작한다.
그리고 시간 초는 랜덤으로 설정해서 항상 다른 결과가 나온다.
이렇게. 동기랑은 다르게 함수가 실핸된다.
이러면 당신은 움직이면서 스킬을 쓸 수 있다.
그런데 위처럼 코드를 실행하면 항상 랜덤 순서로 일의 결과가 나온다.
나는 1,2,3으로 나오게 하고 싶은데…
그래서 비동기함수들을 순차적으로 결과가 나오게 조절해주는 함수들이 있다.
바로 callback / promise / async,Await 이다.
하나씩 알아보자.
Callback
우리는 callback을 이용해서 비동기함수를 조절할 수 있다.
위의 코드에 인자로 callback을 넣어주자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function func1 (string, callback) {
setTimeout(
() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 100) +1
)
}
function func2 (){
func1("1번", () => {
func1("2번", () => {
func1("3번", () => {})
})
})
}
}
콜백을 이용하기 전에는 각자 시간에 따라 결과값이 랜덤으로 나왔다.
그러나 콜백을 이용하면 요 비동기를 조절하여 내가 원했던 1,2,3번으로 결과값이 나오도록 조정할 수 있다!
Promise
promise도 callback처럼 비동기를 조절할 수 있다. callback보다 더 유용함.
자세히 알아보자.
promise 예제
위에 있는 코드를 callback 대신 promise로 작성해 보았다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function func1(string) {
return new Promise((resolve, reject) => {
// 추가된 부분
setTimeout(() => {
console.log(string);
resolve(); // 추가된 부분
}, Math.floor(Math.random() * 100) + 1);
});
}
function func2() {
func1('1번')
.then(() => {
// 추가된 부분
return func1('2번');
})
.then(() => {
return func1('3번');
});
}
하나씩 알아보자
promise의 3가지 상태
프로미스는 다음과 같은 3가지 상태가 있다.
대기(pending): 이행하거나 거부되지 않은 초기 상태.
이행(fulfilled): 연산이 성공적으로 완료됨.
거부(rejected): 연산이 실패함.
대기
대기는 초기 상태로, 실행하기 전 상태를 뜻한다.
1
new Promise(function (resolve, reject) {});
이렇게 만들어 놓은 상태를 대기라고 한다.
이행
1
2
3
new Promise(function (resolve, reject) {
resolve();
});
이행은 resolve나 reject를 실행시키면 이행이다. resolve()안에 들어갈 값은 앞으로 우리가 정해주면 된다.
거부
1
2
3
new Promise(function (resolve, reject) {
reject(new Error('에러'));
});
이행이 성공적으로 완료되면 resovle()의 값을 나타내고, 중간에 문제가 생기면 reject()의 값을 나타내게 된다.
Promise Chaining
Promise Chaining은 여러 개의 promise 함수를 .then()으로 연결시키는 것을 말한다.
여기 각각 func1~4까지 0.5초 뒤에 1번~4번을 뱉는 함수가 있다.
얘네들을 .then()으로 이어주면 비동기 함수들의 결과를 내가 원하는 순서대로 조작할 수 있다.
함수들을 .then()으로 이어준 모습이다.then은 쉽게 말하면 “그리고 나서 이거 실행해” 정도로 나는 이해하고 있다.
.then()안에 return 을 하면 return의 값은 다음 .then(return)이렇게 인자로 들어가게 된다.
요런식으로 결과 값을 다음 .then()에 넘겨주어 +1을 계속 만들어 줄 수도 있다.