공부/javascript

2022.06.20 - javascript 동기, 비동기, callback함수

기묜몬 2022. 6. 21. 15:34

1. 동기(Synchronous): 요청에 대한 결과가 동시에 일어난다.

순차적으로 동작하는 방식

function func1(){ 
  console.log("1번입니다"); 
  func2(); 
} 
function func2(){ 
  console.log("2번입니다"); 
  func3(); 
} 
function func3(){ 
	console.log("3번입니다"); 
} 

func1(); 
//1번입니다 
//2번입니다 
//3번입니다

 

 

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

요청을 보내고 응답에 관계없이 바로 다음 동작을 실행한다. 

console.log("Hello");

setTimeout(() => {
  console.log("hyo");
}, 1000);

console.log("World");

//Hello
//World
//hyo

2-1) js에서 비동기방식이 가능한 이유?

자바스크립트는 싱글스레드로 프로그램이 동작한다. ( 한 번에 한가지 일만 처리가 가능한 단일 스레드)

자바스크립트는 웹 브라우저나  Node.js의 자바스크립트 엔진에서 실행이 된다. 

이 엔진에는 자바스크립트를 돌리는 하나의 스레드가 존재한다. 

또한 이 엔진 뿐만아니라 자바스크립트 엔진은 Web API를 두었고, 비동기식 처리 모델인 Web API가 함께 동작하면서

setTimeout, Ajax등 기다리는 시간이 필요한 일들을 처리하는 것이다. 

이 Web API들이 별도로 비동기 처리를 따로 돌면서 콜백함수를 가지고 이벤트 루프에 들어가 처리되는대로 

콜백함수를 다시 자바스크립트 엔진으로 돌려보내준다. 

 

2-2) 비동기의 주요사례
1) dom element의 이벤트 핸들러
- 마우스, 키보드 입력(click, keydown 등)
- 페이지 로딩(DOMContentLoaded 등)

2) 타이머

- 타이머 API(setTimeout 등)
- 애니메이션 API(requestAnimationFrame)

3) 서버에 자원 요청 및 응답
- fetch API
- AJAX(XHR)

 

 

3. Callback(비동기 방식의 함수)

(1) 다른 함수의 인자로서 이용되는 함수 
(2) 어떠한 이벤트에 의해 호출되는 함수 

 

3-1) 콜백함수가 필요한 이유?

비동기로 함수를 실행할 경우라도 논리적으로  A동작이 완료되고 B동작이 실행되어야하는 경우가 있다. 

ex) 텍스트파일이나 서버로부터 비동기로 파일을 읽는 동작(A)과 읽은 파일을 가공하는 동작(B)가 있는 경우이다.

B를 콜백함수로 A함수의 인자로 호출하면 A가 동작을 완료하고 B를 실행할 수 있다. 

 

- 이름을 입력받으면 hi라는 메세지와 함께 이름을 출력하는 hello() 함수

const hello = (name) => {
  console.log(`hi ${name}`);
}

hello("hyoeun");

// hi hyoeun

 

- 콜백함수를 만들어 전달 

callbackFunc() 함수를 만들고 hello()함수의 파라미터로 전달한다. 

hello()함수는 내부에서 필요한 로직을 모두 실행한 후 마지막에 callback()함수를 실행한다. 

const hello = (name,callback) => {
  console.log(`hi ${name}`);
  callback();
 
}
const callbackFunc = () => {
  console.log("콜백 함수");
}


hello("hyoeun", callbackFunc);

// hi hyoeun
// 콜백 함수

 

- 콜백 함수 사용 예시

자바스크립트가 실행되고 2초후에 hi와 이름이 화면에 출력된다. 

setTimeout()함수에 콜백함수를 파라미터로 담아서 실행할 수 있다. 

 

const hello = (name) => {
  console.log(`hi ${name}`);

}

setTimeout(hello, 2000, "hyoeun");
console.log("1");

// 1
// hi hyoeun

 

3-2) 다른 예시 

< 동기 >

결제를 예시로 보는것과 같이 순차적으로 console에 찍힘 

function buy(item, price, int) {
  console.log(item+" 상품을 "+int+"개 담았습니다.");
  console.log("계산이 필요합니다.");
  let total = price*int;
  return total;
}

function pay(tot){
  console.log(tot + " 원을 지불했습니다.");
}
const tot = buy("고구마",1000,5);
pay(tot);

// 고구마 상품을 5개 담았습니다.
// 계산이 필요합니다.
// 5000원을 지불했습니다.

 

< 비동기 >

물건을 담고 계산하는 시간(1초)이 필요하다는 setTimeout 가정을 추가했다. 

1개에 1000원인 고구마를 5개 사서 총 금액을 리턴하여 tot 변수에 대입시킨다. 

그리고 동일하게 tot 를 지불함수(pay)파라미터로 넘겨주면 총액이 "undefined"원이 나온다.

 

=> setTimeout 함수는 순차적인 흐름을 보장하지 않는 비동기방식의 함수이기 때문

1초뒤에 다음 구문이 실행되는것이 아니라 호출한 직후 바로 다음구문을 실행한다.

function buy(item, price, int) {
    console.log(item + " 상품을 " + int + "개 담았습니다.");
    setTimeout(function() {
        console.log("계산이 필요합니다.");
        var total = price*int;
        return total;
    }, 1000);
}
function pay(tot) {
    console.log(tot + "원을 지불했습니다.");
}
var tot = buy("고구마", 1000, 5);
pay(tot);

// 고구마상품을 5개 담았습니다.
// undefined 원을 지불했습니다.
// 계산이 필요합니다.

 

< 콜백 함수 >

총액을 계산한 이후의 행위를 기술하기 위해 콜백함수(callback)를 인자로 받고, setTimeout 함수 내에 포함시킨다. 

계산이 필요하다는 함수(setTimeout)메세지 이후에 콜백함수를 수행하므로, 콜백함수에 지불 내용을 넣으면 원하는 순서로 진행이 된다. 

function buy(item, price, int, callback) {
    console.log(item + " 상품을 " + int + "개 담았습니다.");
    setTimeout(function() {
        console.log("계산이 필요합니다.");
        let total = price*int;
        callback(total);
    }, 1000);
}

function pay(tot) {
    console.log(tot + "원을 지불했습니다.");
}

let tot = buy("고구마", 1000,5,pay);

// 고구마 상품을 5개 담았습니다.
// 계산이 필요합니다.
// 5000원을 지불했습니다.

 

 

 

[참고]

https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/

https://sangminem.tistory.com/275

 

자바스크립트 콜백 함수 예제를 통해 개념 및 원리 쉽게 이해하기

자바스크립트를 배운 지 얼마 안 되신 분이라면 콜백 함수를 많이 헷갈려 하실 수 있는데요. 차근차근 설명을 해 보도록 하겠습니다. 목차 동기와 비동기 의미 동기는 하나의 요청이 오면 완료

sangminem.tistory.com