싱글 스레드인 자바스크립트가 어떻게 비동기를 구현합니까?
네, 좋은 질문입니다! JavaScript는 싱글 스레드(single-threaded) 언어입니다. 즉, 한 번에 하나의 작업만 처리할 수 있는 실행 스레드를 가지고 있습니다. 그럼에도 불구하고, 비동기 작업을 통해 마치 멀티스레드처럼 여러 작업이 동시에 실행되는 것처럼 보일 수 있습니다.
이는 JavaScript의 런타임 환경, 특히 이벤트 루프(Event Loop)와 콜백 큐(Callback Queue) 덕분입니다.
자바스크립트의 비동기 작업 처리는 자바스크립트 엔진(V8 엔진 등)과 이를 실행하는 런타임 환경(브라우저, Node.js 등)의 구조에 의해 가능해집니다.
1. 싱글 스레드와 비동기 처리
JavaScript는 기본적으로 싱글 스레드로 동작하기 때문에, 한 번에 하나의 작업만 처리합니다. 하지만 비동기 작업을 사용할 때는 브라우저나 Node.js 같은 자바스크립트 런타임 환경에서 제공하는 비동기 처리 메커니즘을 활용하여 여러 작업을 동시에 처리하는 것처럼 보일 수 있습니다.
싱글 스레드라는 것은 자바스크립트 엔진 자체가 한 번에 하나의 작업만 실행할 수 있음을 의미하지만, 자바스크립트 엔진 외부에서 비동기 작업을 처리하는 다른 시스템들이 존재하며, 이 시스템들이 멀티스레드 작업을 가능하게 해줍니다.
2. 비동기 처리의 핵심 요소: 이벤트 루프(Event Loop)
비동기 처리가 가능한 이유는 이벤트 루프(Event Loop)라는 메커니즘 덕분입니다. 이벤트 루프는 JavaScript 런타임의 중요한 부분으로, 비동기 작업을 관리하고 처리하는 역할을 합니다.
이벤트 루프 동작 과정
- 콜 스택(Call Stack):
- JavaScript 엔진은 콜 스택이라는 공간을 통해 함수를 실행합니다. 콜 스택은 현재 실행 중인 함수와 그 함수가 호출하는 다른 함수들을 순서대로 처리합니다.
- 싱글 스레드이기 때문에 한 번에 하나의 함수만 콜 스택에서 실행됩니다.
- 웹 API / Node API:
- 브라우저나 Node.js 같은 환경에서는 비동기 작업을 처리하는 API들을 제공합니다. 예를 들어,
setTimeout
, HTTP 요청, 파일 읽기/쓰기 등의 작업은 자바스크립트 엔진이 처리하지 않고 웹 API나 Node API가 처리합니다. - 이 API들은 별도의 스레드를 사용하여 비동기 작업을 처리하고, 작업이 완료되면 콜백을 큐에 넣어 이벤트 루프를 통해 다시 실행합니다.
- 브라우저나 Node.js 같은 환경에서는 비동기 작업을 처리하는 API들을 제공합니다. 예를 들어,
- 콜백 큐(Callback Queue):
- 비동기 작업이 완료되면 해당 작업에 대한 콜백 함수가 콜백 큐에 추가됩니다. 이 큐에는 실행 대기 중인 비동기 작업들이 차례로 대기하고 있습니다.
- 이벤트 루프(Event Loop):
- 이벤트 루프는 콜 스택이 비어있는지 확인하고, 콜 스택이 비어 있다면 콜백 큐에서 대기 중인 작업을 가져와 콜 스택에 추가하여 실행합니다.
3. 비동기 처리의 예: setTimeout
을 통한 비동기 실행
console.log('Start');
setTimeout(() => {
console.log('Inside setTimeout');
}, 1000);
console.log('End');
실행 과정:
console.log('Start')
는 콜 스택에서 실행되고, 즉시"Start"
가 출력됩니다.setTimeout
함수가 호출되면, 이 함수는 브라우저의 Web API(Node.js의 경우 Node API)에 의해 처리됩니다. 자바스크립트 엔진은setTimeout
의 콜백 함수는 실행하지 않고, 1000ms(1초) 타이머를 시작한 후, 이 작업을 API에게 맡기고 바로 콜 스택에서 제거됩니다.console.log('End')
가 콜 스택에서 실행되며"End"
가 출력됩니다.- 1000ms가 경과한 후,
setTimeout
의 콜백 함수가 콜백 큐로 이동합니다. - 이벤트 루프는 콜 스택이 비어 있는지 확인하고, 비어 있으면 콜백 큐에서
setTimeout
의 콜백을 가져와 실행합니다. 이때"Inside setTimeout"
이 출력됩니다.
결과:
Start
End
Inside setTimeout
4. 비동기 작업의 예: HTTP 요청
console.log('Start');
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => console.log(data));
console.log('End');
실행 과정:
console.log('Start')
는 즉시 실행되고"Start"
가 출력됩니다.fetch
함수는 브라우저의 비동기 API에 의해 처리됩니다. 네트워크 요청이 완료될 때까지 자바스크립트 엔진은 기다리지 않고,console.log('End')
를 실행하여"End"
를 출력합니다.- 네트워크 요청이 완료되면, 콜백 큐에 응답을 처리할 콜백 함수가 추가됩니다.
- 이벤트 루프가 콜 스택이 비어 있음을 확인한 후, 콜백 큐에 대기 중인 콜백 함수가 실행되고
fetch
의 응답을 처리하게 됩니다.
결과:
Start
End
[HTTP 요청의 결과 데이터]
5. 요약: 싱글 스레드 비동기 처리의 원리
- JavaScript는 싱글 스레드 언어입니다. 즉, 한 번에 하나의 작업만 처리할 수 있습니다.
- 하지만 브라우저나 Node.js 같은 런타임 환경에서 제공하는 비동기 API(Web API, Node API) 덕분에, 멀티스레드 작업을 지원하는 것처럼 비동기 작업을 처리할 수 있습니다.
- 이벤트 루프와 콜백 큐는 비동기 작업을 처리하는 중요한 메커니즘입니다. 자바스크립트 엔진이 작업을 처리하는 동안, 비동기 작업은 별도의 시스템(Web API, Node API)이 처리하고, 완료되면 콜백 큐를 통해 콜 스택으로 다시 작업을 가져와 실행합니다.
- 이러한 메커니즘 덕분에, JavaScript는 싱글 스레드 환경에서도 효율적으로 비동기 작업을 처리할 수 있으며, 네트워크 요청, 타이머, 파일 읽기/쓰기 등의 작업에서 프로그램이 멈추지 않고 다른 작업을 처리할 수 있습니다.
'TIL' 카테고리의 다른 글
[241004 TIL] supabase db 복원하기 (0) | 2024.10.04 |
---|---|
[241002 TIL] useReducer 다시 정리 (0) | 2024.10.02 |
[240929 TIL] 간단정규식으로 파일명에 특정문자열 추가하기 (0) | 2024.09.29 |
[240927 TIL] tailwind-merge, clsx 결합 사용 (1) | 2024.09.27 |
[240925 TIL] ReactNode, FC(gpt 질의) (0) | 2024.09.25 |