본문 바로가기
프로그래밍언어/JavaScript

[Javascript] 동기 & 비동기

by Yikanghee 2022. 4. 6.
  • 자바 스크립트가 동작하는 원리
  • 순서대로 실행하는 것과 그렇지 않는 것 들

만약 수행해야 할 작업 (함수) 3개와 작업 실행 (함수 호출) 순서를 지정했다고 갖정해보자

function taskA() {
	console.log("TASK A");
}
function taskB() {
	console.log("TASK B");
}
function taskC() {
	console.log("TASK C");
}

//수행해야 할 작업(함수) 3개

taskA();
taskB();
taskC();

// 작업 실행 (함수 호출) 순서
  • 동기적 처리방식
    • 자바스크립트는 코드가 작성된 순서대로 작업을 처리함
    • 이전 작업이 진행 중 일 때는 다음 작업을 수행하지 않고 기다림 → 블로킹 방식
    • 먼저 작성된 코드를 먼저 다 실행하고 나서 뒤에 작성된 코드를 실행한다 → 동기적 방식의 처리
  • 동기적 처리방식의 문제점
    • 동기적 처리의 단점은 하나의 작업이 너무 오래 걸리게 될 시, 모든 작업이 오래 걸리는 하나의 작업이 종료되기 전까지 올 스탑 되기 때문에, 전반적인 흐름이 느려진다
    • 웹 사이트에서 버튼 하나하나마다 30 초 씩 걸리면, 큰 문제가 발생한다
  • 멀티스레드
    • 동기적 처리방식의 문제점을 해결하기 위해서 멀티쓰레드 ‘MultiThread’ 방식을 작동시키면 Tread를 여러 개 사용하여 작업 분할이 가능하다
    • 멀티쓰레드를 사용하면 오래 걸리는 일이 있어도 다른 일꾼 Tread에게 지시하면 되므로 괜찮음
    • 하지만, 자바스크립트는 싱글 쓰레드로 동작한다
  • 비동기 작업
    • 그래서 싱글 쓰레드 방식을 이용하면서, 동기적 작업의 단점을 극복하기 위해서 여러 개의 작업을 동시에 실행시킨다
    • 즉, 먼저 작성된 코드의 결과를 기다리지 않고 다음 코드를 바로 실행함
    • 이렇게 하나의 작업을 하는동안 다른 작업을 못 하도록 블로킹 하던걸 하지 않는것을 논 블로킹 방식이라고 하고, 논 블로킹하는 방식을 비동기 작업이라고 함
  • 비동기 작업 확인하기
    • 비동기 작업을 하는 것 까지는 이해하는데 이것이 제대로 작동되는 지 확인하기 위해서 콜백 메시지를 받아야한다
    taskA(resultA) => {
    	console.log(`A 끝났습니다. 작업 결과 : ${
    resultA}`);
    }
    taskA(resultB) => {
    	console.log(`B 끝났습니다. 작업 결과 : ${
    resultB}`);
    }
    taskA(resultC) => {
    	console.log(`C 끝났습니다. 작업 결과 : ${
    resultC}`);
    }
    
    -------------------------------------
    
    function taskA() {
    	setTimeout(() => {
    		console.log("A TASK END");
    }, 2000);
    }
    
    taskA();
    console.log("코드 끝")
    // (1) 코드 끝 , (2) A TASK END
    // 이런식으로 코드 순서로는 A TASK END가 먼저 일어나고
    // 코드 끝이 두번째로 나와야하는데 
    // (1) 코드 끝 , (2) A TASK END 이러한 순서로 나오게된다
    // 이것으로 자바스크립트의 비동기 작업을 알 수 있음
    
    • 콜백함수를 사용한 비동기 처리
    function taskA(a, cb) {
    	setTimeout(() => {
    		const res = a * 2;
    		cb(res);
    }, 2000);
    }
    
    function taskB(a, cb) {
    	setTimeout(() => {
    		const res = a * -1;
    		cb(res);
    }, 1000);
    }
    taskA(7, (res) => {
    	console.log("A TASK RESUILT : ", res);
    });
    
    taskB(14, (res) => {
    	console.log("B TASK RESUILT : ", res);
    });
    
    console.log("코드 끝");
    
    // 코드 끝, B TASK RESULT : -14, A TASK RESULT : 14
    // 콜백 함수를 사용하여 비동기 통신을 사용할 수 있음
    // setTimeout 함수를 사용하여 기다리는 시간을 설정할 수 있음
    // 순서를 보면 1초 기다린 후 B, 2초 기다린 후 A를 호출함
    
  • 어떻게 자바스크립트의 엔진은 동작할까?
    • 자바스크립트에 적힌 코드는 자바스크립트 엔진을 사용하여 해석되고 사용됨
    • 자바스크립트 엔진은 Heap, Call Stack으로 구성된다
    function one() {
    	return 1;
    }
    function two() {
    	return one() + 1;
    }
    function three() {
    	return two() + 1;
    }
    
    console.log(three());
    
    • 먼저 위와 같은 코드가 실행이 되면, Call Stack으로 들어오게 되고 console.log()라는 함수를 실행한다
    • 그 안에는 three() 라는 함수가 있으므로 three() 함수를 실행한다
    • three() 안에는 two가 있어서 two( ) 함수를 실행하고 그뒤에 같은 방식으로 one() 함수를 실행한다
    • 그리고 one() 함수에서 1을 return하고 종료되어 Call Stack에서 나오게 된다
    • 그리고 two(), three() , main Context 가 순서대로 종료된다
    • 자바스크립트 엔진은 다음과 같이 실행하고 종료한다
  • 자바스크립트의 동기 & 비동기 처리방식
    • 위와 같은 코드에서 동기적으로 처리되는 함수는 asyncAdd, console.log 이다 비동기적으로 처리되는 함수는 setTimeout이다
    • 처리되는 순서는 다음과 같다
    1. Call Stack 에 Main Context, asynAdd(), setTimeout()이 순서대로 들어가게 된다
    2. 비동기 함수인 setTimeout()은 Web APIs에 들어가게되고
    3. Call Stack함수에서 asynAdd()가 처리되고, Callback Queue로 setTimeout() 함수가 들어간다
    4. 그리고 Event Loop를 통해서 Call Stack으로 들어가고
    5. 콜백 함수를 실행하고 Main Context를 실행하고 종료된다
    6. 이렇듯 비동기 처리와 동기처리를 함께 사용하면 동기 → 비동기 순서로 처리가 된다.
function asyncAdd(a, b, cb) {
	setTimeout(() => {
		const res = a + b;
		cb(res);
	}, 3000);
}

asyncAdd(1, 3, (res) => {
	console.log("결과 : ", res);
}

댓글