티스토리 뷰

반응형

[챗지피티와 공부를 해보자] 02. 이벤트 루프와 비동기 처리 + 가비지 컬렉션과의 연관

 

 

 

자바스크립트는 싱글 스레드 기반이다. 

싱글 스레드이기 때문에 한번에 한가지 작업만 실행할 수 있다.

하지만 그렇다고 한번에 한가지 작업만 하게되면? 문제가 많을것이다. (무한 대기가 생기겠지?)

그렇기 때문에 브라우저나 노드 환경에서 여러 작업을 동시에 처리할 수 있도록 설계되어있는데, 이 핵심이 이벤트 루프다.

 

 

이벤트 루프란?

자바스크립트의 비동기 처리를 가능하게하는 매커니즘이다. (비동기 작업은 HTTP요청이나 setTimeout 등..)

비동기 작업은 나중에 실행되도록 예약하고, 이벤트 루프는 준비된 작업을 실행할 수 있도록 한다.

이때 어떤 순서대로 실행을 시킬까?

우리가 여기서 알아야하는 개념은 '콜스택, 태스트큐, 마이크로태스크큐' 이다.

 

 

1. 콜스택 (Call Stack)

자바스크립트 엔진이 실행할 코드를 담아두는 스택 자료구조로 선입 후출 방식이다. 가장 마지막에 들어온 코드가 먼저 실행된다. 

동기적인 작업(함수 호출, 연산 등)은 콜스택에 쌓이고 선입 후출로 실행되며, 완료 시 스택에서 제거된다.

 

 

2. 태스크 큐 (Task Queue)

비동기 작업의 콜백 함수가 담기는 곳으로 큐 자료구조로 선입 선출 방식이다. 먼저 들어온 코드가 먼저 실행된다.

여기서 비동기 작업의 콜백 함수란, setTimeout, setInterval과 같이 타이머 콜백이나 DOM 이벤트의 비동기 콜백 등이 여기에 해당한다.

콜 스택이 완전히 비어있게 되면 이벤트 루프가 태스크 큐에서 작업을 가져와 콜 스택에 넣는다.

 

-> webAPI, NodeJS APIs는 타이머(setTimeout), 네트워크요청(fetch), 이벤트 리스너는 백그라운드에서 실행된다. 이 API들은 비동기 작업을 처리한 뒤, 결과를 태스크큐로 전달한다.

 

 

3. 마이크로태스크 큐 (Microtask Queue)

promise의 then이나 catch (promise의 콜백), MutationObserver의 콜백이 담기는 곳으로 큐 자료구조로 선입 선출 방식이다. 먼저 들어온 코드가 먼저 실행된다.

마이크로태스크큐의 우선순위는 태스크 큐보다 높아서, 콜 스택이 완전히 비어있게 되면 이벤트 루프가 마이크로태스크 큐를 먼저 확인해서 작업을 가져와 콜 스택에 넣는다. 

 

 

작동 원리를 정리해보면 아래와 같이 동작한다.

콜 스택 확인 > 콜 스택 처리 > 콜 스택이 완전히 비어있으면 > 이벤트 루프가 마이크로태크스 큐에 대기중인 작업을 콜 스택으로 이동, 실행 > 마이크로태크스 큐가 완전히 비어있으면 > 이벤트 루프가 태스크 큐에 대기중인 장업을 콜 스택으로 이동, 실행 > 전체가 비어있게 되면 이벤트 루프 대기

 

예제

console.log('시작');

setTimeout(() => {
	console.log('태스크 큐');
}, 0);

Promise.resolve().then(() => {
	console.log('마이크로태스크 큐');
});

console.log('끝');

 

예제를 간단히 설명하면

console.log는 콜스택에서 바로 실행된다. 즉, 출력은 '시작', '끝' 이 먼저 된다.

이후 이벤트 루프는 마이크로태스크 큐를 확인하므로 '마이크로태스크 큐'가 출력된다.

마지막으로 태스크 큐를 확인하므로 '태스크 큐'가 출력된다.

 

 

가비지 컬렉션과의 연관

이벤트 루프와 가비지 컬렉션은 서로 독립적으로 작동하지만 메모리 관리와 실행 흐름의 관점에서 간접적인 연관이 있다.

가비지 컬렉션을 간단히 말하면, 사용하지 않는 메모리를 해제하여 메모리 누수를 방지하는데 이때 메모리 해제의 기준은 도달 가능성으로 참조되지 않는 객체를 메모리에서 제거하는 역할을 한다.

 

이벤트 루프에서 처리되는 비동기 작업은 객체와 데이터(콜백함수, 타이머, 네크워크 응답 등)를 메모리에 유지해야한다.

가비지 컬렉션은 아래와 같은 상황에서 중요한 역할을 한다.

 

1. 비동기 작업 중 메모리 관리

이벤트 루프에서 비동기 작업의 콜백이 실행되기 전까지는 해당 작업과 관련된 객체가 메모리에 유지된다.

setTimeout의 콜백이 대기 상태일때, 관련 객체는 도달 가능한 상태로 판단되어 가비지 컬렉션 대상이 되지 않는다.

 

 

2. 작업 완료 후 메모리 해제

비동기 작업이 완료되고, 콜백이 실행된 후 관련 데이터가 더 이상 필요 없어졌을 경우, 가비지 컬렉션이 불필요한 객체를 제거하여 메모리를 확보한다.

 

동작 설명을 해보면

setTimeout이 실행 > 콜백이 태스크 큐에 대기 - 이때는 가비지 컬렉션 대상이 아니어서 메모리에 유지된다.

> 콜스택이 비어있어서 이벤트 루프가 마이크로 태스크 확인, 이것도 비어있어서 태크스 큐 확인 > setTimeout의 콜백이 이벤트 루프에 의해 콜스택으로 이동 > 콜백 실행 - 가비지 컬렉션 대상이 되어 메모리에서 해제된다.

 

 

3. 이벤트 루프 - 가비지 컬렉션 서로에게 미치는 영향

이벤트 루프 > 가비지 컬렉션에 미치는 영향

이벤트 루프는 콜백의 생명주기를 관리하며 작업 완료 후에는 메모리에서 해제될 수 있도록 준비한다. 만약 이벤트 루프가 차단되면 (blocking task 발생) 가비지 컬렉션이 실행되는 타이밍이 지연될 수 있다. 이는 메모리 관리 효율성을 떨어트릴수 있다.

 

가비지 컬렉션 > 이벤트 루프에 미치는 영향

가비지 컬렉션은 자주 실행되지 않고, 주로 메모리가 부족할 때 실행되는데 가비지 컬렉션이 실행 중에는 자바스크립트의 싱글 스레드 모델에 따라 실행 중인 작업이 일시적으로 중단 될 수 있다.

즉, 자바스크립트 엔진은 가비지 컬렉션 중 '일시적으로 모든 작업을 중단' (stop-the-world 문제)하게 되면 이로 인해 이벤트 루프가 잠시 멈추게 되고 성능에 영향을 줄 수 있다.

 

따라서 최적화를 잘 하기 위해서는

이벤트 루프는 불필요한 비동기작업을 줄이고 이벤트 루프가 효율적으로 동작하도록 해야하며, 가비지 컬렉션은 전역 객체나 참조 순환을 피하여 참조를 관리하는 다양한 방식(weakMap, WeakSet..)을 고려해야한다.

 

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함