제품 품질 저하 없이 개발팀을 확장하는 방법
개발팀을 확장하고 계신가요? 제품 품질을 저하시키지 않고 성장하는 방법을 알아보세요. 이 가이드에서는 확장할 시기의 징후, 팀 구조, 채용, 리더십 및 도구와 더불어 The Codest가 어떻게...
JavaScript는 단일 스레드 언어이며 동시에 비차단, 비동기 및 동시 언어이기도 합니다. 이 글에서는 그 원리를 설명합니다.
JavaScript 는 컴파일된 언어가 아니라 해석된 언어입니다. 즉, JS를 변환하는 인터프리터가 필요하다는 뜻입니다. 코드 를 기계 코드로 변환합니다. 여러 유형의 인터프리터(엔진이라고도 함)가 있습니다. 가장 널리 사용되는 브라우저 엔진은 V8(Chrome), Quantum(Firefox), WebKit(Safari)입니다. 참고로 V8은 널리 사용되는 비브라우저 런타임에도 사용됩니다, Node.js.
각 엔진에는 메모리 힙, 호출 스택, 이벤트 루프, 콜백 대기열, HTTP 요청, 타이머, 이벤트 등이 포함된 WebAPI가 포함되어 있으며, 모두 JS 코드를 더 빠르고 안전하게 해석하기 위해 자체적인 방식으로 구현되어 있습니다.

기본 JS 런타임 아키텍처. 저자: Alex Zlatkov
단일 스레드 언어는 단일 호출 스택과 단일 메모리 힙을 가진 언어입니다. 즉, 한 번에 한 가지 작업만 실행한다는 뜻입니다.
A 스택 는 실행되는 각 함수에 로컬 컨텍스트를 할당하는 연속적인 메모리 영역입니다.
A 힙 는 훨씬 더 큰 영역으로, 동적으로 할당된 모든 것을 저장합니다.
A 호출 스택 는 기본적으로 프로그램에서 현재 위치를 기록하는 데이터 구조입니다.
간단한 코드를 작성하여 호출 스택에서 어떤 일이 일어나는지 추적해 보겠습니다.

보시다시피 함수는 스택에 추가되고 실행된 후 나중에 삭제됩니다. 이른바 LIFO 방식인 선입선출 방식입니다. 호출 스택에 있는 각 항목을 스택 프레임.
호출 스택에 대한 지식은 오류 스택 추적을 읽는 데 유용합니다. 일반적으로 오류의 정확한 원인은 첫 번째 줄의 맨 위에 있지만 코드 실행 순서는 상향식입니다.
때때로 다음과 같이 자주 발생하는 오류를 처리할 수 있습니다. 최대 호출 스택 크기 초과. 재귀를 사용하면 쉽게 얻을 수 있습니다:
함수 foo() {
foo()
}
foo()
를 누르면 브라우저나 단말기가 멈춥니다. 브라우저마다, 심지어 버전마다 호출 스택 크기 제한이 다릅니다. 대부분의 경우 이 정도면 충분하며 다른 곳에서 문제를 찾아야 합니다.
다음은 JS 스레드를 차단하는 예제입니다. 다음과 같이 foo 파일과 바 를 사용하여 노드.js 동기화 함수 readFileSync.

이것은 반복되는 GIF입니다. 보시다시피 JS 엔진은 첫 번째 호출이 들어올 때까지 기다립니다. readFileSync 가 완료되었습니다. 그러나 이 작업은 foo 파일에 저장되어 있으므로 두 번째 함수는 호출되지 않습니다.
그러나 JS는 논블로킹이 가능하며 멀티스레드처럼 동작할 수도 있습니다. 즉, API 호출, I/O 이벤트 등의 응답을 기다리지 않고 코드 실행을 계속할 수 있습니다. 이는 C++(Chrome) 또는 Rust(Firefox)와 같은 실제 멀티스레딩 언어를 사용하는(내부적으로) JS 엔진 덕분에 가능합니다. 이들은 브라우저 내부에서 웹 API를 제공하거나 ex. Node.js의 I/O API를 제공합니다.

위의 GIF에서 첫 번째 함수가 호출 스택으로 푸시되고 있는 것을 볼 수 있습니다. 안녕하세요 은 콘솔에서 즉시 실행됩니다.
그런 다음 setTimeout 함수를 호출합니다. 호출 스택과 해당 비동기 콜백으로 이동합니다. foo 함수는 웹에이피의 대기열로 이동하여 3초 후에 호출이 발생하도록 설정된 호출을 기다립니다.
그 동안 프로그램은 코드를 계속 진행하며 다음과 같이 표시됩니다. 안녕하세요. 차단되지 않았습니다. 를 클릭합니다.
호출된 후 WebAPI 대기열의 각 함수는 호출이 완료되면 콜백 대기열. 호출 스택이 비워질 때까지 함수가 대기하는 곳입니다. 호출이 발생하면 함수가 하나씩 이곳으로 이동합니다.
따라서 setTimeout 타이머가 카운트다운을 완료하면 foo 함수는 콜백 큐로 이동하여 호출 스택을 사용할 수 있게 될 때까지 기다렸다가 그곳으로 이동하여 실행되면 다음과 같이 표시됩니다. 비동기 콜백에서 안녕하세요 를 클릭합니다.
문제는 런타임이 호출 스택이 비어 있음을 어떻게 알고 콜백 대기열의 이벤트가 어떻게 호출되는가 하는 것입니다. 이벤트 루프를 만나보세요. 이벤트 루프는 JS 엔진의 일부입니다. 이 프로세스는 호출 스택이 비어 있는지 지속적으로 확인하고, 비어 있는 경우 콜백 대기열에 호출을 기다리는 이벤트가 있는지 모니터링합니다.
이것이 바로 무대 뒤의 모든 마법입니다!
동시성 는 여러 작업을 동시에 실행하지만 동시에 실행하지 않는 것을 의미합니다. 예를 들어 두 개의 작업이 겹치는 시간대에 작동합니다.
병렬 처리 는 두 개 이상의 작업을 동시에 수행하는 것을 의미합니다(예: 여러 계산을 동시에 수행).
스레드 는 서로 독립적으로 실행할 수 있는 코드 실행 시퀀스입니다.
프로세스 는 실행 중인 프로그램의 인스턴스입니다. 프로그램에는 여러 개의 프로세스가 있을 수 있습니다.
In 동기식 프로그래밍을 사용하면 작업이 차례로 실행됩니다. 각 작업은 이전 작업이 완료될 때까지 기다렸다가 그 후에야 실행됩니다.
In 비동기 프로그래밍을 사용하면 한 작업이 실행되면 이전 작업이 완료될 때까지 기다릴 필요 없이 다른 작업으로 전환할 수 있습니다.
단일 스레드와 동기화: 작업이 차례로 실행됩니다. 각 작업은 이전 작업이 실행될 때까지 기다립니다.
여러 스레드와 동기화: 작업은 다른 스레드에서 실행되지만 다른 스레드에서 실행 중인 다른 작업을 기다립니다.
단일 스레드를 사용한 비동기: 다른 작업이 완료될 때까지 기다리지 않고 작업이 실행되기 시작합니다. 주어진 시간에는 하나의 작업만 실행할 수 있습니다.
여러 스레드를 사용한 비동기식: 작업은 다른 작업이 완료될 때까지 기다리지 않고 다른 스레드에서 실행되어 독립적으로 실행을 완료합니다.
JS 엔진의 내부 작동 방식을 고려하면 JS는 비동기식 단일 스레드 해석 언어로 분류할 수 있습니다. "해석된"이라는 단어는 매우 중요한데, 이는 이 언어가 항상 런타임에 의존적이며 멀티스레딩이 내장된 컴파일된 언어만큼 빠르지 않다는 것을 의미하기 때문입니다.
각 스레드가 별도의 프로세스로 시작되는 경우 Node.js가 실제 멀티 스레딩을 달성 할 수 있다는 점은 주목할 만합니다. 이를 위한 라이브러리가 있지만 Node.js에는 다음과 같은 기능이 내장되어 있습니다. 워커 스레드.
모든 이벤트 루프 GIF는 루페 애플리케이션에서 비동기 시나리오를 테스트할 수 있습니다.
자세히 읽어보세요:
품질을 최우선으로! JavaScript 프로젝트에서 GitHub 워크플로로 코드를 린트하는 5가지 쉬운 단계