Learn Eventloop

Junghan Lee·2023년 4월 22일
0

Learnd in Camp

목록 보기
38/48

이벤트 루프

// setInterval(() => {
//   document.getElementById("timer")?.innerText = "2:59";
// }, 1000);

export default function TastQueuePage(){

	const onClickTimer = () => {

		console.log("=======시작~~=======")

		setTimeout(() => {
			console.log("1초 뒤에 실행된답니다 😎️")
		}, 1000)

		console.log("=======끝~~=======")
	}

	return <button onClick={onClickTimer}>시작~~</button>;
}

위는 3분짜리 타이머

코드 순서대로 라면 함수의 끝 부분의 ‘끝’ 콘솔보다 setTimeout 안에 있는 콘솔이 먼저 실행되어야 할 것 같은데, 순서가 뒤집혀 있다.

검증을 위해 setTimeout을 0초로 바꾸어 다시 한 번 실행해 보자.

export default function TastQueuePage(){

	const onClickTimer = () => {

		console.log("=======시작~~=======")

		setTimeout(() => {
			console.log("0초 뒤에 실행된답니다 😎️")
		}, 0)

		console.log("=======끝~~=======")
	}

	return <button onClick={onClickTimer}>시작</button>;
}

콘솔이 찍히는 순서에는 변화가 없는데 이는 자바스크립트의 동작 원리 때문이다.

Task Queue
위의 타이머 코드는 콜스택에 이렇게 쌓이게 된다.

실행순서
1.callStack에서 onClickTimer 함수가 실행 (Stack - Last In First Out / LIFO 구조)
2.Background에 setTimeout()을 보내서 실행
3.setTimeout()이 TaskQueue로 전달되어 쌓임. (Queue - First In First Out / FIFO 구조)
4.TaskQueue에 쌓이는 함수는 CallStack이 다 비워진 다음 가장 마지막에 실행

위와 같은 순서에 따라 onClickTimer 함수 내에서 setTimeout이 가장 마지막에 실행되게 된다.

여기서 TaskQueue에 있는 함수를 CallStack으로 보내는 역할을 하는 일꾼이 있는데 그것을 **스레드(Thread)**라고 한다.

싱글 스레드
자바 스크립트는 **싱글 스레드** 방식을 가지고 있다. 조금 더 구체적으로 표현하자면 **싱글 이벤트 루프 스레드**라고도 한다.

핵심은, CallStack이 비어야만 TaskQueue에 있는 작업을 CallStack으로 가져온다는 것

CallStack이 작업 중이라면 setTimeout에 설정한 1초가 이미 지났다고 하더라도 TaskQueue 안의 작업이 CallStack으로 들어오지 못한다.

다음과 같은 코드를 입력하고 yarn dev 해보자.

export default function TastQueuePage(){

	const onClickTimer = () => {

		console.log("=======시작!!!!=======")

		setTimeout(() => {
			console.log("1초 뒤에 실행될 거예요!!!")
		}, 1000)

		for(let i=0; i<=9000000000; i+=1){
			sum = sum + 1
		}

		console.log("=======끝!!!!=======")
	}

	return <button onClick={onClickTimer}>시작!!!</button>;
}

페이지가 그려진 뒤 콘솔을 열고 시작 버튼을 눌러보면 클릭 후 1초가 훨씬 지났는데도 ‘끝’ 콘솔이 뜨지 않는 것을 확인할 수 있다.

setTimeout이 TaskQueue에 들어가서 대기하고 있지만, 반복문이 종료되어 CallStack이 비워지지 않으면 TaskQueue에 있는 setTimeout은 실행되지 못하기 때문이다.

setInterval, setTimeout처럼 CallStack에 쌓이지 않고 Background, TaskQueue로 넘겨지는 작업을 **비동기 작업**이라고 한다.

axios도 비동기 처리가 이루어지는 대표적인 라이브러리 중 하나.

프로세스와 스레드

프로세스:실행되어있는 프로그램
스레드: 프로세스 안에서 동작하는 일꾼

스레드가 하나인 언어를 싱글 스레드 언어, 여러개인 언어를 멀티 스레드 언어라고 한다.(자바스크립트 : 싱글 스레드)

멀티 스레드와 싱글 스레드

참고) 컨텍스트 스위칭 (멀티스레드에서 발생)

멀티 스레드 언어의 경우 동시에 여러가지 작업을 처리하고 있는 것처럼 보이지만,

사실은 여러 개의 스레드가 여러가지 작업을 번갈아가며 빠르게 수행하고 있는 것과 같다.

멀티 스레드의 경우에도 하나의 요청에 대한 응답을 기다렸다가 다음 작업으로 이동해야 하는 것은 동일하다. (이러한 작업을 컨텍스트 스위칭이라고 함.)

그렇기 때문에 멀티 스레드라고 해서 싱글 스레드보다 두드러지게 빠르지는 않다.

오히려 자바스크립트와 같은 **이벤트 루프 싱글 스레드**의 경우

오래 걸리는 작업을 TaskQueue로 빼서 처리하기 때문에 높은 퍼포먼스를 낼 수 있다.

블로킹 vs 논블로킹
위에서 설명한 멀티 스레드 예시처럼

하나의 요청에 대한 응답이 와야만 다음 작업을 시작할 수 있는 방식을

**블로킹(blocking) 방식**이라고 한다.

그리고 이벤트 루프 싱글 스레드처럼 하나의 작업이 진행되는 동안 시간이 오래 걸리는 작업은 따로 마련한 공간에 던져 실행하는 방식을 **논블로킹(non-blocking) 방식**이라고 한다.

자바스크립트 : 싱글 스레드 & 논블로킹

profile
Strive for greatness

0개의 댓글