Js는 왜 싱글 스레드인가

상태
시작 전
담당자
날짜
2024/06/26
숫자
0

자바스크립트는 왜 싱글스레드일까

JavaScript는 웹 개발의 중심 언어로, 특히 클라이언트 측 스크립팅에서 주요한 역할을 수행합니다.
이번 글에서는 JavaScript가 왜 싱글 스레드로 설계되었는지, 그리고 그로 인해 어떤 이점과 한계가 있는지를 분석해보겠습니다.

스레드란

간단하게 말해 CPU가 작업을 수행하는 단위 입니다. 스레드는 프로세스 내에서 실행되며, 여러 스레드가 동시에 실행될 수 있습니다. 또한 스레드는 프로세스의 자원을 공유하면서 독립적으로 실행될 수 있기 때문에, 멀티태스킹 환경에서 중요한 역할을 합니다.
싱글스레드
싱글 스레드는 한 번에 하나의 작업만을 수행하는 실행 모델입니다. 프로그램 내 모든 작업이 하나의 스레드에서 순차적으로 처리되는것 입니다.
특징
단순성: 싱글 스레드는 단일 실행 흐름을 가지기 때문에 코드 작성과 디버깅이 상대적으로 쉬움.
동기적 실행: 모든 작업이 순차적으로 실행되므로, 한 작업이 완료되기 전에 다음 작업이 시작되지 않음.
자원 관리: 스레드 간의 자원 공유 문제나 동기화 문제가 발생하지 않음.
멀티스레드
멀티 스레드는 여러 스레드를 사용하여 동시에 여러 작업을 수행하는 실행 모델입니다. 프로그램 내 여러 작업이 병렬로 처리될 수 있는것 입니다.
특징
병렬 처리: 여러 작업을 동시에 수행할 수 있어, 작업 처리 속도가 빨라짐.
효율적 자원 사용: CPU 자원을 최대한 활용할 수 있어, CPU 사용률을 높일 수 있음.
복잡성 증가: 스레드 간의 자원 공유와 동기화 문제를 관리해야 하므로 코드 작성과 디버깅이 더 복잡해짐.
특성
싱글 스레드
멀티 스레드
단순성
높음
낮음
성능
동기적 처리로 인해 병목 현상 발생 가능
병렬 처리로 높은 성능 가능
자원 관리
자원 공유 문제 없음
자원 공유 및 동기화 문제 발생 가능
응답성
한 작업이 완료될 때까지 대기 필요
동시에 여러 작업 처리 가능

JavaScript란?

JavaScript는 1995년 넷스케이프(Netscape)에서 브렌던 아이크(Brendan Eich)에 의해 개발되었습니다. 당시의 웹페이지는 주로 정적으로 구성되어 있었습니다.이는 사용자와 브라우저간의 상호작용이 매우 제한적이라는 문제점이 있었습니다. 초기 웹페이지의 상호작용성을 문제를 해결하고 브라우저에서 사용할수있는 가벼운 스크립트 언어 가 필요했고 그결과, 개발된것이 넷스케이프(Netscape) JavaScript였습니다.
당시의 웹브라우저 환경은 사용자와 상호작용을 위한 기능을 제공하는데 중점을 두었으며, 단순하고 예측가능한 방식으로 작동하는것이 중요했습니다. 웹 브라우저 환경에서의 단순성, 예측 가능성, 그리고 주어진 상황에서의 최선의 실행 속도와 안정성을 위한 선택이 JavaScript가 싱글 스레드를 사용하는 이유가 된것입니다.
하지만 위에서 비교한것처럼 단순하고,빠르다는 장점이 있지만 동기적인 실행방식 으로 인한 단점으로 한번에 한작업씩 할수있는 낮은 응답성에대한 단점이 존재합니다. 이러한 단점을 극복하기 위해 JavaScript는 비동기 처리를 통해 여러 작업을 동시에 처리할 수 있는 방법을 제공합니다.

동기(Synchronous)와 비동기(Asynchronous)

JavaScript가 싱글스레드의 단점을 보완하기위해 비동기 처리 방법을 사용하는것은 이제 알겠으나 도대체 이것이 무엇일까 싶습니다.
간단하게 말하면 프로그래밍에서 작업이 수행되는 방식입니다.
동기는 작업을 순차적으로 실행하며, 한 작업이 끝날 때까지 다음 작업을 기다립니다.
비동기는 작업을 병렬적으로 실행하며, 한 작업의 결과를 기다리지 않고 다음 작업을 실행할 수 있습니다.
그럼 싱글 스레드는 한번에 한 작업만 할수있다. 라고 했는데 어떤방법으로 여러 작업을 할수있는지가 의문입니다.

비동기 처리의 필요성

비동기 처리는 긴 시간 동안 실행되는 작업이 다른 작업의 수행을 막지 않도록 합니다.
예를 들어, 서버 요청, 파일 읽기, 타이머 등의 작업은 실행 시간이 오래 걸릴 수 있습니다.
하지만 싱글 스레드의 특성상 작업시간이 아무리 길어도 해당 작업들을 완료 해야만 다른작업으로 넘어갈수 있습니다. 이러한 작업이 완료될 때까지 다른 작업을 대기시키지 않고 동시에 처리할 필요가 있기때문에 비동기처리의 필요성이 강조 되는것 입니다.

비동기 처리 방법 및 원리

JavaScript의 비동기 처리는 이벤트 루프(Event Loop)와 관련된 메커니즘을 통해 이루어집니다. 이벤트 루프는 호출 스택(Call Stack)과 작업 큐(Task Queue) 간의 상호작용을 관리하여 비동기 작업을 처리하는것 입니다.
호출 스택 (Call Stack): 현재 실행 중인 함수들의 호출 정보를 저장하는 공간
함수에 대한 정보가 스택의 맨위에 추가되며 함수가 완료되면 스택에서 제거됨.이러한 방식으로 함수 호출의 순서와 실행 상태를 추적하며, 스택이 비어 있을 때 프로그램이 종료됨
작업 큐 (Task Queue 또는 Callback Queue): 비동기 작업의 콜백 함수들이 대기하는 공간
작업 큐는 FIFO(선입선출) 방식으로 동작하며, 호출 스택이 비어 있을 때 이벤트 루프를 통해 콜백 함수를 호출 스택으로 이동시킴
이벤트 루프 (Event Loop): 호출 스택과 작업 큐를 모니터링하면서, 호출 스택이 비어 있을 때 작업 큐에서 콜백 함수를 꺼내어 호출 스택에 추가하는 역할
호출 스택이 비어 있을 때 작업 큐에서 콜백 함수를 꺼내어 호출 스택에 추가하는 역할을 함. 호출 스택이 처리할 작업이 없을 때마다 이벤트 루프가 작업 큐에서 콜백 함수를 꺼내어 실행하게 되는것
예시
1.
호출 스택이 비어있음
2.
코드가 실행되면서 함수 A가 호출되고 호출 스택에 추가
3.
함수 A에서 비동기 함수 B 호출. B 는, 호출 스택으로 올라가지 않는 대신 비동기 작업의 콜백 함수가 작업 큐에 추가
4.
함수 A가 실행을 마치고 호출 스택에서 제거
5.
호출 스택이 비어 있으므로 이벤트 루프가 작업 큐를 확인
6.
작업 큐에서 대기 중인 콜백 함수(B의 비동기함수)를 호출 스택으로 이동.
7.
콜백 함수(B의 비동기함수)가 호출 스택에 추가되고 실행

Node.js의 싱글스레드 사용이유

우선 Node.js란 서버 측에서 JavaScript를 실행할 수 있도록 해주는 런타임 환경입니다.
런타임이란 언어가 구동되는 환경을 뜻하는데 이전에 JavaScript의 런타임 환경이 웹브라우저 였다면 Node.js는 클라이언트 가아닌 서버가 되는것입니다.
Node.js 는 이전에 설명드린 싱글스레드의 단점을 비동기 처리로 극복한 JavaScript 기반으로 설계 되었으며 해당 특성을 그대로 가져왔기 때문에 서버측 에서 많이 사용되는 네트워크 응답 및 파일시스템 접근 등과 같은 입출력 작업을 빠르게 처리할수가 있다는 장점이 있습니다.
서버 환경에서의 비동기 I/O 처리를 강조하여 많은 클라이언트 요청을 효율적으로 처리할 수 있게 합니다.
싱글 스레드에서 I/O처리
1.
동기적으로 I/O 작업을 처리할 경우, 해당 작업이 완료될 때까지 다음 코드 실행이 차단됩니다. 이는 다른 작업들이 대기해야 하며, 이 시간 동안 CPU 자원이 낭비될 수 있습니다.
2.
블로킹되는 동안 CPU는 대기하게 되므로, 시스템 전체적인 처리량이 감소할 수 있습니다. 특히 대규모 동시 접속 처리 시에는 성능 저하가 더욱 심각해질 수 있습니다.
3.
동기적 처리 방식은 요청마다 새로운 스레드를 생성하거나 프로세스를 추가로 할당하여 동시성을 처리하는 방법이 필요합니다. 이는 자원 소모가 크며 확장성이 제한될 수 있습니다.
그러나 Node.js에선 이러한 문제들을 JavaScript의 비동기처리 방식을 이용하여 해결한것입니다.
비동기 I/O 처리
Node.js의 비동기 I/O 처리는 Node.js의 주요 강점이자 특성이라고 할수 있습니다.이를 통해 파일 읽기, 데이터베이스 접근, 네트워크 요청 등 대부분의 I/O 작업을 비동기적으로 처리하기때문에 싱글 스레드 환경에서도 높은 성능과 확장성을 제공합니다.
이벤트 루프와 작업 큐
Node.js는 이벤트 루프와 작업 큐를 활용하여 비동기 작업을 효율적으로 관리함. 이벤트 루프는 작업 큐에 대기 중인 작업을 하나씩 처리하며, 비동기 작업이 완료되면 콜백 함수를 호출하여 결과를 처리합니다. 이는 JavaScript의 비동기 처리와 같은 방식 이기도 합니다.
JavaScript와 Node.js 두언어 모두 각각의 환경에 맞게 싱글 스레드 모델을 활용하여 효율적인 동작을 보장합니다.
JavaScript는 브라우저 환경에서의 단순성과 안정성을 위해 싱글 스레드 모델을 채택했으며
Node.js는 서버 환경에서의 비동기 I/O 처리를 통해 높은 성능을 제공하기 위해 싱글 스레드를 선택한것 입니다.

자바스크립트는 왜 싱글스레드일까

JavaScript는 웹 개발의 중심 언어로, 특히 클라이언트 측 스크립팅에서 주요한 역할을 수행합니다.
이번 글에서는 JavaScript가 왜 싱글 스레드로 설계되었는지, 그리고 그로 인해 어떤 이점과 한계가 있는지를 분석해보겠습니다. 이를 분석하기위해선 스레드가 무엇인지 알아볼 필요가 있습니다.

스레드란

간단하게 말해 CPU가 작업을 수행하는 단위 입니다. 스레드는 프로세스 내에서 실행되며, 여러 스레드가 동시에 실행될 수 있습니다. 또한 스레드는 프로세스의 자원을 공유하면서 독립적으로 실행될 수 있기 때문에, 멀티태스킹 환경에서 중요한 역할을 합니다.
싱글스레드
싱글 스레드는 한 번에 하나의 작업만을 수행하는 실행 모델입니다. 프로그램 내 모든 작업이 하나의 스레드에서 순차적으로 처리되는것 입니다.
특징
단순성: 싱글 스레드는 단일 실행 흐름을 가지기 때문에 코드 작성과 디버깅이 상대적으로 쉬움.
동기적 실행: 모든 작업이 순차적으로 실행되므로, 한 작업이 완료되기 전에 다음 작업이 시작되지 않음.
자원 관리: 스레드 간의 자원 공유 문제나 동기화 문제가 발생하지 않음.
멀티스레드
멀티 스레드는 여러 스레드를 사용하여 동시에 여러 작업을 수행하는 실행 모델입니다. 프로그램 내 여러 작업이 병렬로 처리될 수 있는것 입니다.
특징
병렬 처리: 여러 작업을 동시에 수행할 수 있어, 작업 처리 속도가 빨라짐.
효율적 자원 사용: CPU 자원을 최대한 활용할 수 있어, CPU 사용률을 높일 수 있음.
복잡성 증가: 스레드 간의 자원 공유와 동기화 문제를 관리해야 하므로 코드 작성과 디버깅이 더 복잡해짐.
특성
싱글 스레드
멀티 스레드
단순성
높음
낮음
성능
동기적 처리로 인해 병목 현상 발생 가능
병렬 처리로 높은 성능 가능
자원 관리
자원 공유 문제 없음
자원 공유 및 동기화 문제 발생 가능
응답성
한 작업이 완료될 때까지 대기 필요
동시에 여러 작업 처리 가능

JavaScript란?

JavaScript는 1995년 넷스케이프(Netscape)에서 브렌던 아이크(Brendan Eich)에 의해 개발되었습니다. 당시의 웹페이지는 주로 정적으로 구성되어 있었습니다.이는 사용자와 브라우저간의 상호작용이 매우 제한적이라는 문제점이 있었습니다. 초기 웹페이지의 상호작용성을 문제를 해결하고 브라우저에서 사용할수있는 가벼운 스크립트 언어 가 필요했고 그결과, 개발된것이 넷스케이프(Netscape) JavaScript였습니다.
당시의 웹브라우저 환경은 사용자와 상호작용을 위한 기능을 제공하는데 중점을 두었으며, 단순하고 예측가능한 방식으로 작동하는것이 중요했습니다. 웹 브라우저 환경에서의 단순성, 예측 가능성, 그리고 주어진 상황에서의 최선의 실행 속도와 안정성을 위한 선택이 JavaScript가 싱글 스레드를 사용하는 이유가 된것입니다.
하지만 위에서 비교한것처럼 단순하고,빠르다는 장점이 있지만 동기적인 실행방식 으로 인한 단점으로 한번에 한작업씩 할수있는 낮은 응답성에대한 단점이 존재합니다. 이러한 단점을 극복하기 위해 JavaScript는 비동기 처리를 통해 여러 작업을 동시에 처리할 수 있는 방법을 제공합니다.

동기(Synchronous)와 비동기(Asynchronous)

JavaScript가 싱글스레드의 단점을 보완하기위해 비동기 처리 방법을 사용하는것은 이제 알겠으나 도대체 이것이 무엇일까 싶습니다.
간단하게 말하면 프로그래밍에서 작업이 수행되는 방식입니다.
동기는 작업을 순차적으로 실행하며, 한 작업이 끝날 때까지 다음 작업을 기다립니다.
비동기는 작업을 병렬적으로 실행하며, 한 작업의 결과를 기다리지 않고 다음 작업을 실행할 수 있습니다.
그럼 싱글 스레드는 한번에 한 작업만 할수있다. 라고 했는데 어떤방법으로 여러 작업을 할수있는지가 의문입니다.
자세한 과정은 이후에 설명 하겠지만 간단한 원리는 JavaScript는 의 비동기 함수들은 브라우저에서 제공하는 WebAPI 사용합니다. 이는 각 API 마다 스레드를 사용하기때문에 메인스레드가 작업을 이어가는동시에 다른작업을 이어나갈수잇는것입니다.

비동기 처리의 필요성

비동기 처리는 긴 시간 동안 실행되는 작업이 다른 작업의 수행을 막지 않도록 합니다.
예를 들어, 서버 요청, 파일 읽기, 타이머 등의 작업은 실행 시간이 오래 걸릴 수 있습니다.
하지만 싱글 스레드의 특성상 작업시간이 아무리 길어도 해당 작업들을 완료 해야만 다른작업으로 넘어갈수 있습니다. 이러한 작업이 완료될 때까지 다른 작업을 대기시키지 않고 동시에 처리할 필요가 있기때문에 비동기처리의 필요성이 강조 되는것 입니다.

비동기 처리 방법 및 원리

JavaScript의 비동기 처리는 이벤트 루프(Event Loop)와 관련된 메커니즘을 통해 이루어집니다. 이벤트 루프는 호출 스택(Call Stack)과 작업 큐(Task Queue) 간의 상호작용을 관리하여 비동기 작업을 처리하는것 입니다.
호출 스택 (Call Stack): 현재 실행 중인 함수들의 호출 정보를 저장하는 공간
함수에 대한 정보가 스택의 맨위에 추가되며 함수가 완료되면 스택에서 제거됨.이러한 방식으로 함수 호출의 순서와 실행 상태를 추적하며, 스택이 비어 있을 때 프로그램이 종료됨
작업 큐 (Task Queue 또는 Callback Queue): 비동기 작업의 콜백 함수들이 대기하는 공간
작업 큐는 FIFO(선입선출) 방식으로 동작하며, 호출 스택이 비어 있을 때 이벤트 루프를 통해 콜백 함수를 호출 스택으로 이동시킴
이벤트 루프 (Event Loop): 호출 스택과 작업 큐를 모니터링하면서, 호출 스택이 비어 있을 때 작업 큐에서 콜백 함수를 꺼내어 호출 스택에 추가하는 역할
호출 스택이 비어 있을 때 작업 큐에서 콜백 함수를 꺼내어 호출 스택에 추가하는 역할을 함. 호출 스택이 처리할 작업이 없을 때마다 이벤트 루프가 작업 큐에서 콜백 함수를 꺼내어 실행하게 되는것
예시
1.
호출 스택이 비어있음
2.
코드가 실행되면서 함수 A가 호출되고 호출 스택에 추가
3.
함수 A에서 비동기 함수 B 호출. B 는, 호출 스택으로 올라가지 않는 대신 비동기 작업의 콜백 함수가 작업 큐에 추가
4.
함수 A가 실행을 마치고 호출 스택에서 제거
5.
호출 스택이 비어 있으므로 이벤트 루프가 작업 큐를 확인
6.
작업 큐에서 대기 중인 콜백 함수(B의 비동기함수)를 호출 스택으로 이동.
7.
콜백 함수(B의 비동기함수)가 호출 스택에 추가되고 실행

Node.js의 싱글스레드 사용이유

우선 Node.js란 서버 측에서 JavaScript를 실행할 수 있도록 해주는 런타임 환경입니다.
런타임이란 언어가 구동되는 환경을 뜻하는데 이전에 JavaScript의 런타임 환경이 웹브라우저 였다면 Node.js는 클라이언트 가아닌 서버가 되는것입니다.
Node.js 는 이전에 설명드린 싱글스레드의 단점을 비동기 처리로 극복한 JavaScript 기반으로 설계 되었으며 해당 특성을 그대로 가져왔기 때문에 서버측 에서 많이 사용되는 네트워크 응답 및 파일시스템 접근 등과 같은 입출력 작업을 빠르게 처리할수가 있다는 장점이 있습니다.
서버 환경에서의 비동기 I/O 처리를 강조하여 많은 클라이언트 요청을 효율적으로 처리할 수 있게 합니다.
싱글 스레드에서 I/O처리
1.
동기적으로 I/O 작업을 처리할 경우, 해당 작업이 완료될 때까지 다음 코드 실행이 차단됩니다. 이는 다른 작업들이 대기해야 하며, 이 시간 동안 CPU 자원이 낭비될 수 있습니다.
2.
블로킹되는 동안 CPU는 대기하게 되므로, 시스템 전체적인 처리량이 감소할 수 있습니다. 특히 대규모 동시 접속 처리 시에는 성능 저하가 더욱 심각해질 수 있습니다.
3.
동기적 처리 방식은 요청마다 새로운 스레드를 생성하거나 프로세스를 추가로 할당하여 동시성을 처리하는 방법이 필요합니다. 이는 자원 소모가 크며 확장성이 제한될 수 있습니다.
그러나 Node.js에선 이러한 문제들을 JavaScript의 비동기처리 방식을 이용하여 해결한것입니다.
비동기 I/O 처리
Node.js의 비동기 I/O 처리는 Node.js의 주요 강점이자 특성이라고 할수 있습니다.이를 통해 파일 읽기, 데이터베이스 접근, 네트워크 요청 등 대부분의 I/O 작업을 비동기적으로 처리하기때문에 싱글 스레드 환경에서도 높은 성능과 확장성을 제공합니다.
이벤트 루프와 작업 큐
Node.js는 이벤트 루프와 작업 큐를 활용하여 비동기 작업을 효율적으로 관리함. 이벤트 루프는 작업 큐에 대기 중인 작업을 하나씩 처리하며, 비동기 작업이 완료되면 콜백 함수를 호출하여 결과를 처리합니다. 이는 JavaScript의 비동기 처리와 같은 방식 이기도 합니다.
JavaScript와 Node.js 두언어 모두 각각의 환경에 맞게 싱글 스레드 모델을 활용하여 효율적인 동작을 보장합니다.
JavaScript는 브라우저 환경에서의 단순성과 안정성을 위해 싱글 스레드 모델을 채택했으며
Node.js는 서버 환경에서의 비동기 I/O 처리를 통해 높은 성능을 제공하기 위해 싱글 스레드를 선택한것 입니다.

7기 Bin (문승민)June 26, 2024 4:01 PMJune 26, 2024 4:01 PM

@void (연시완) (cc. @wayne (김례인)js는 왜 싱글스레드인가 초안