개발 이야기/frontend

자바스크립트는 싱글 스레드 언어다 - 비동기 처리 방식과 Web API

thisisamrd 2024. 8. 28.

 

어제 콜스택에 대한 포스팅에 이어, 오늘은 자바스크립트가 Web Api를 처리하는 방식을 통해 왜 싱글 스레드 언어라고 불리고 자바스크립트가 비동기 작업을 어떻게 처리하는지 알아보겠습니다.

 

 

 

이에 앞서 콜스택을 시각화해서 보여주는 사이트에서 Web Api 동작 방식을 이해할 수 있는 예시 코드가 담긴 사이트를 공유드립니다. 

해당 코드는 유데미 인기강의인 The Web Developer 부트캠프 2024 를 참고했습니다.

 

 

 

 

 

 

 

 

 

 

 

위 사이트에 들어가면 간단한 코드가 있을텐데요. save+run 버튼을 누르면 자동으로 실행됩니다. 중간에 pause를 눌러 잠시 멈출 수 있고, resume을 눌러 코드를 재개할 수도 있습니다.

이 때 중요한 것은 저 setTimeOut 함수가 콜스택에 쌓이는 순간, 우측 Web Apis 코너로 들어가서 3초 동안 대기한다는 것입니다. 이후 3초가 지나면 callback queue로 옮겨졌다가 다시 콜백에 쌓이며 로그가 출력되는 순서입니다.

 

 

이것이 시사하는 방식이 무엇일까요? 이를 위해서 자바스크립트가 싱글 스레드 언어라는 점부터 짚고 넘어가야 합니다.

 

 

 

 

 

 

JavaScript는 싱글 스레드 언어다

JavaScript가 싱글 스레드라는 것은 한 번에 하나의 작업만 처리할 수 있다는 의미입니다. 즉, JavaScript 엔진은 한 번에 한 줄의 코드만 실행할 수 있으며 여러 작업을 동시에 수행하는 멀티태스킹을 할 수 없습니다. 이를 "한 트랙의 마인드를 가진다"라고 표현할 수 있습니다. 하지만 JavaScript는 코드 실행 속도가 매우 빠르기 때문에, 우리는 일반적으로 여러 작업이 동시에 이루어지는 것처럼 느끼게 됩니다.

 

 

 

 

 

싱글 스레드의 잠재적 문제점

JavaScript가 한 번에 하나의 작업만 실행할 수 있기 때문에 일어나는 문제는 무엇일까요? 예를들어 네트워크 요청(AJAX 호출)이나 타이머 설정 같은 시간이 오래 걸리는 작업이 발생할 때 JavaScript의 나머지 코드가 멈춰있는 것처럼 보일 수 있습니다. 만약 서버에 데이터를 요청하는 작업이 5초가 걸릴 경우, JavaScript가 그 5초 동안 아무 작업도 하지 않고 기다린다면 전체 코드가 멈춘 것처럼 느껴지게 됩니다. 이는 사용자 경험에 있어 매우 불편한 상황을 초래할 수 있습니다.

 

실제로 이렇게 멈춰있게 된다는 것은 아니고요. 위 예시는 자바스크립트의 싱글 스레드 특성 때문에 발생할 수 있는 잠재적인 문제 상황을 설명한 것입니다. 실제 JavaScript가 그렇게 동작한다면 매우 불편한 상황이 될거예요. 그러나 다행히 JavaScript는 비동기 처리를 통해 이런 문제를 피할 수 있습니다.

 

 

 

 

 

 

 

 

JavaScript의 비동기 처리 방식

JavaScript는 싱글 스레드 언어이기 때문에, 한 번에 하나의 작업만 수행할 수 있습니다. 그러나 비동기 작업을 처리할 때는 브라우저가 제공하는 Web API와 같은 메커니즘을 활용하여 이러한 문제를 해결합니다. JavaScript는 시간이 오래 걸리는 작업을 직접 처리하는 대신, 해당 작업을 브라우저에 위임하여 백그라운드에서 처리하도록 합니다. 이를 통해 JavaScript는 작업이 진행되는 동안에도 다른 코드들을 계속해서 실행할 수 있습니다.



예를 들어 위의 예시에서 사용했던 setTimeout은 지정된 시간이 지난 후에 특정 코드를 실행하도록 예약하는 함수인데, 실제로 이  작업은 브라우저가 처리합니다. JavaScript는 setTimeout 함수를 호출한 후, 브라우저에 이 작업을 위임하고 다음 코드들을 바로 실행할 수 있습니다. 그런 다음 지정된 시간이 지나면 브라우저는 해당 작업이 완료되었음을 JavaScript에 알려주고, JavaScript는 그때서야 해당 콜백 함수를 실행합니다.

 


이러한 방식 덕분에 JavaScript는 네트워크 요청, 타이머 설정, 파일 읽기와 같이 시간이 오래 걸릴 수 있는 작업을 비동기로 처리할 수 있습니다. JavaScript는 작업이 완료될 때까지 기다리지 않고, 다른 작업을 계속해서 수행하며 사용자 경험을 개선할 수 있지요. 비동기 작업이 완료되면, 이벤트 루프(Event Loop)가 해당 작업의 콜백을 실행하도록 해줍니다. 이벤트 루프는 추후 포스팅에서 다시 적어보겠습니다.

 

 

 

 



 

 

 

Web API의 역할

JavaScript는 비동기 작업을 처리할 때 브라우저의 도움을 받습니다. Web API는 브라우저가 제공하는 기능들로, JavaScript는 이러한 작업을 브라우저에게 "위임"하는 방식으로 비동기 작업을 처리합니다. 브라우저는 JavaScript로 작성된 것이 아니라, 보통 C++와 같은 언어로 작성되어 있어 JavaScript가 할 수 없는 여러 복잡한 작업을 백그라운드에서 처리할 수 있습니다. 

 

 

 

 

콜백 함수와 콜 스택

JavaScript의 콜 스택(call stack)은 실행할 함수들을 관리합니다. 비동기 작업이 발생하면, 해당 작업을 Web API로 넘기고 다음 작업을 계속 진행합니다. 일정 시간이 지나거나 비동기 작업이 완료되면, Web API는 해당 작업을 콜백 큐(callback queue)로 보내고, 콜 스택이 비어 있을 때 그 콜백을 실행하게 됩니다. 이렇게 해서 JavaScript는 비동기 작업이 완료될 때까지 멈추지 않고 다른 작업을 수행할 수 있게 됩니다.

 

콜 스택이 쌓이는 순서를 시각화하여 보여주는 것에 대해 다룬 포스팅이 있으니 참고하시면 좋겠습니다.

 

 

 

 

 

 

 

JavaScript의 싱글 스레드와 비동기 작업의 조화

JavaScript가 싱글 스레드라는 점 때문에 멀티태스킹이 불가능해 보일 수 있지만, 실제로는 브라우저의 Web API와 비동기 처리 메커니즘 덕분에 여러 작업을 효율적으로 처리할 수 있습니다. 이러한 개념은 Promises와 async/await 같은 비동기 패턴과 개념을 이해할 때 중요한 기반이 될 것입니다.

 

 

 

댓글