React 모던 딥다이브 1.6 - 이벤트 루프
이벤트 루프와 비동기 통신의 이해
JavaScript는 싱글 스레드 언어로 작동합니다. 이는 한 번에 하나의 작업만 수행할 수 있다는 의미입니다. 이 설계 선택은 처리 작업을 단순화하고 예측 가능성을 보장합니다. 그러나 시간이 더 오래 걸리거나 기본 실행 흐름과 독립적으로 발생해야 하는 작업을 관리하려면 비동기 프로그래밍 기술을 사용해야 합니다.
동기(Synchronous) 방식은 직렬 처리 방식으로, 응답을 기다려야 하므로 다른 작업은 대기해야 합니다.
비동기(Asynchronous) 방식은 병렬 처리 방식으로, 요청을 시작한 후 응답이 오건 말건 상관없이 다른 작업을 수행할 수 있습니다.
1. 싱글 스레드 JavaScript
JavaScript에서 프로세스는 프로그램을 실행하는 단위를 나타내고, 스레드는 프로세스 내의 더 작은 실행 단위를 나타냅니다. 여러 스레드가 동시에 실행될 수 있는 다중 스레드 환경과 달리 JavaScript는 단일 스레드에서 작동합니다. 즉, 주어진 시간에 하나의 코드만 실행되고 여러 스레드가 생성되지 않으며 스레드 간에 메모리가 공유되지도 않습니다.
JavaScript에서 단일 스레드를 사용하는 이유는 단순성 때문입니다. 작업을 단일 스레드로 제한함으로써 개발자는 경쟁 조건 및 교착 상태와 같은 다중 스레드 관리와 관련된 복잡성을 피할 수 있습니다. 그러나 이는 장기 실행 작업이 잠재적으로 후속 코드 실행을 차단하여 사용자 경험이 저하될 수 있음을 의미합니다.
2. 이벤트 루프
이벤트 루프는 비동기 실행을 돕기 위해 만들어진 장치입니다. 이벤트 루프는 비동기 작업의 실행을 조정하고 단일 스레드 환경에서 제어 흐름을 관리하는 역할을합니다. 정확한 역할로는 이벤트 루프는 호출 스택이 비어 있는지 확인합니다. 그리고 테스크 큐 또는 마이크로 테스크 큐에서 비동기식 작업을 진행합니다.
이벤트 루프는 웹 브라우저 및 Node.js와 같은 JavaScript 런타임 환경의 기본 구성 요소입니다. 비동기식 통신을 가능하게 하고 비차단 동작을 보장합니다.
호출 스택(Call Stack): 수행되어야 할 코드나 함수를 담아두는 스택입니다. 태스크 큐(Task Queue): 실행해야 할 태스크의 집합입니다. 선택된 큐 중에서 실행 가능한 가장 오래된 태스크를 가져옵니다. 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 여기에 들어갑니다.
예를 들어, setTimeout()
함수는 호출 스택에 들어갔다가 태스크 큐로 돌아가고 스택에서 바로 제거됩니다. 그 후 이벤트 루프가 호출 스택이 비어 있음을 확인하고 태스크 큐의 내용을 실행합니다.
마이크로 태스크 큐
마이크로 태스크 큐는 이벤트 루프가 가진 하나의 큐로, Promise 등의 비동기 함수의 콜백이 여기에 들어갑니다. 마이크로 태스크 큐는 기존 태스크 큐보다 우선권을 가집니다.
랜더링은 마이크로 태스크 큐 작업이 끝날 때마다 기회를 얻습니다. 동기 코드와 마이크로 태스크 큐는 동일하게 처리되지만, 태스크 큐는 콜백이 큐에 들어가기 전까지 대기하다가 순차적으로 콜백이 호출될 때마다 랜더링됩니다.
예시 코드:
console.log("Start");
setTimeout(() => {
console.log("Timeout"); // 비동기식 실행
}, 0);
Promise.resolve("Promise").then((value) => {
console.log(value); // 마이크로 테스크 큐에 할당
});
console.log("End");
출력 결과:
Start
End
Promise
Timeout
위 코드에서 setTimeout()
은 태스크 큐에 들어가고, Promise는 마이크로 태스크 큐에 들어갑니다. 이벤트 루프는 호출 스택이 비어 있을 때 마이크로 태스크 큐의 작업을 먼저 실행하고, 그 다음 태스크 큐의 작업을 실행합니다.
이처럼 JavaScript의 싱글 스레드 특성과 이벤트 루프, 태스크 큐, 마이크로 태스크 큐의 이해는 비동기 통신을 구현하는 데 매우 중요합니다. 리액트에서도 이러한 개념들이 적용되어 효율적인 렌더링을 가능하게 합니다.
Leave a comment