본문 바로가기
개발 공부/웹개발

자바스크립트_동기/비동기 개념정리(callback_promise_async/await)

by 크롱이크 2021. 5. 21.

오늘은 비동기에 대해서 알아보겠습니다.

 

동기(Synchronous): 요청에 대한 결과가 동시에 일어난다.
비동기(Asynchronous): 요청에 대한 결과가 동시에 일어나지 않는다.

동기는 바로 요청을 하면 시간이 얼마가 걸리던지 요청한 자리에서 결과가 주어집니다.

비동기는 요청과 결과가 동시에 일어나지 않을거란 약속입니다.

 

동기방식은 매우 간단하고 직관적이지만,

결과가 주어질 때까지 아무것도 못하고 기다려야 하기에 효율적이지 않다는 단점이 있습니다.

비동기 방식은 동기보다 복잡할 순 있지만,

결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 효율적으로 사용할 수 있습니다.

 

비동기와 동기의 일상생활의 예시를 들면,

커피를 마시고 카페에 갔는데 줄이 있습니다.

우리는 1. 커피를 주문한다.

2. 결제한다.

3. 커피를 받는다. 

이 세 과정을 거칩니다. 

 

여기서 앞에 있는 손님이 커피를 주문하고 결제하고, 커피를 받을때까지 직원이 커피 주문을 받지 않는다면,

줄은 길어지고 효율적이지 못하겠죠.

이것은 동기입니다. 하나의 한동작만 할수 있습니다.

하지만 비동기는 다릅니다.

앞에 손님이 주문을 하고 결제하고 나면, 다음사람이 주문을 하고 결제를 합니다.

그사이에 커피가 나오면 커피를 받아가고, 그 시간에 또 다른 손님은 주문하고 결제할 수 있습니다.

이렇게 사람마다 마시는 커피는 다를 수도 있고 동시에 이루어지지 않죠.

이것을 비동기라고 합니다.

 

비동기의 주요사례를 보면 다음과 같습니다.

1.dom element의 이벤트 핸들러

 -마우스, 키보드 입력(click, keydown 등)

 -페이지 로딩(DOMContentLoaded 등)

2. 타이머

 -타이머 API(setTimeout 등)

 -애니메이션 API(requestAnimationFrame)

3.서버에 자원 요청 및 응답

 -fetch API

 -AJAX(XHR)

Callback(비동기 방식의 함수)

 callback 함수는 다른 함수의 매개변수로 함수를 전달하고,

어떠한 이벤트가 발생한 후 매개변수로 전달한 함수가 다시 호출되는 것을 의미합니다.

콜백은 순차적으로 이어져서 좋지만 많아지면 코드를 읽는 가독성과 관리가 어려워집니다.

이것이 계속 이어지면 콜백헬이라고 부릅니다. (28~37)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const printString = (string) => {
    setTimeout(
        () => {
            cconsole.log(string);
        },
        Math.floor(Math.random() * 100+ 1
    )
}//이함수는 string이라는 인자를 받아서 시간을 랜덤으로 받아 스트링을 보여주는 함수이다.
 
const printAll = () => {
    printString("a");
    printString("b");
    printString("c");
}; //순서대로가 아닌 랜덤하게 재생된다.
printAll(); //
 
//callback 이라면,
const printString = (string, callback) => {
    setTimeout(
        () => {
            cconsole.log(string);
            callback();
        },
        Math.floor(Math.random() * 100+ 1
    )
}
 
const printAll = () => {
    printString("a", () => {
        printString("b", () => {
            printString("c", () => {
                printString("d", () => {
                })
            })
        })
    })
}
printAll();
cs

 

Promise(콜백을 핸들링 하기 좋다)

Promise는 비동기적으로 실행하는 작업의 결과를 나타내는 객체입니다.

비동기의 결과를 객체화 시킨다는 점이 Promise의 가장 큰 장점이자 특징이 됩니다.

콜백을 핸들링 하기 정말 좋습니다^^

 

resolve 성공시 실행 - then

reject 실패시 실행 - catch

finally - 무조건 실행

 

promise.all(배열): 여러 개의 프로미스를 동시에 실행 (하나라도 실패하면 catch로감)

promise.allSettled(배열) : 실패한 것만 추려낼 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const printString = (string) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(string)
            resolve()
        }, Math.floor(Math.random() * 100+1
        )
    })
 
const printAll = () => {
    printString("A"//먼저 한번 실행한다.
    .then(() => {                //조건에 만족한다면
        return printString("B"//두번째실행부턴 then이 들어간다.
    })
    .then(()=>{
        return printString("C"//콜백헬과 다르게 위치가 같다.
    })
}
cs

정해진 장시간의 기능을 수행하고 나서 정상적으로 기능이 수행되어졌다면 성공의 메시지와 처리된 결과값을 전달해주고요,

만약 수행하다가 예상치못한 문제를 받았다면 에러를 표시한다.

하나의 다른 예시로는 다음과 같다.

getHen, getEgg, cook이라는 promise객체가 있다. 콘솔창에 한번 쳐보시면 좋을 것 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const getHen = () => new Promise((resolve, reject) => {    
    setTimeout(() => resolve('닭'), 1000);
});
const getEgg = hen => new Promise((resolve, reject) => {
    // setTimeout(()=>resolve(`${hen} => 달걀`), 1000);
    setTimeout(() => reject(new Error(`error! ${hen} => egg`)), 1000);
});
 
const cook = egg => new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => 후라이`), 1000);
});
 
getHen()
    .then(hen => getEgg(hen)) //hen => 생략가능
    .catch(error => {
        return 'bread';
    })
    .then(cook)
    .then(meal => console.log(meal));
cs

 

 

Async/await(제일 편한거~)

지금까지 callback을 대신해서 promise를 배웠지만 사실 이게 제일 편합니다. promise를 더 간편하게 쓸 수 있습니다.

예시를 보면 4개의 함수가 있고, 밑에 result라는 변수가 있다. 함수 앞에 저렇게 'async' 를 붙여주고, 안에서 변수를 선언할 때 보면 'await' + 함수가 할당되어 있는 걸 볼 수 있다. 이렇게 사용합니다. 

기본 형태는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function delay(item) { 
    return new Promise(
        resolve => setTimeout(() => { 
            console.log(item); 
            resolve(); 
        }, 500
    ); 
 
 
async function basic() { 
        await delay(6); 
        console.log("finish"); 
        return "basic"
}
cs

또 다른 예시~콘솔창에 입력해보세요!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function goToWork() {
    return new Promise((resolve, reject)=> {
        setTimeout(()=> {
            resolve(`1. go to work`)
        }, 1000)
    });
};
 
function sitAndCode() {
    return new Promise((resolve, reject)=> {
        setTimeout(()=> {
            resolve(`2. sit and code`)
        }, 1000)
    });
};
 
function eatLunch() {
    return new Promise((resolve, reject)=> {
        setTimeout(()=> {
            resolve(`3. eat lunch`)
        }, 1000)
    });
};
 
function goHome() {
    return new Promise((resolve, reject)=> {
        setTimeout(()=> {
            resolve(`4. go home`)
        }, 1000)
    });
};
 
const result = async () => {
    const one = await goToWork();
    console.log(one);
 
    const two = await sitAndCode();
    console.log(one);
 
    const three = await eatLunch();
    console.log(one);
 
    const four = await goHome();
    console.log(one);
}
 
result();
cs

 

 

오늘은 비동기에 작업에 필요한 callback, promise, async/await를 알아보았습니다.

좀더 좋은 예시로 다시한번 정리하도록하겠습니다.

반응형

댓글