JavaScript 작동 원리의 핵심은 다음 두 가지이다.
싱글스레드
완전한 싱글 스레드는 아니다. 싱글스레드인 메인 스레드 이외에도 추가적으로 이벤트루프라는 싱글 스레드가 있다. 런타임인 브라우저나 Node.js(스레드 풀, 워크 스레드 같은 것들이 존재) 모두 멀티스레드로 이루어져있다. 그러나 프로그래머가 직접 제어할 수 있는 스레드가 하나뿐이어서 흔히 싱글 스레드로 여겨진다.
싱글스레드를 사용하는 이유는 무엇일까?
- 쉬워서
- 멀티 스레드 방식보다 프로그래밍이 쉬움
- 특히, 스레드 간에 자원 공유로 발생할 수 있는 교착 상태와 같은 문제들을 고려하지 않아도 됨
- 가벼워서
- 웹 브라우저에서 동작하기 위해 가벼운 언어를 도입하려고 했음
- 멀티 스레드는 많은 자원을 필요로 함
- 스레드 풀의 경우 스레드 하나당 하나의 클라이언트와 연결
- 많은 클라이언트와 연결되기 위해선 많은 수의 스레드가 필요
- 많은 CPU 코어가 필요...
- 그런데 막상 유휴 CPU가 많아진다면...
써서 안좋은 점은 무엇일까?
싱글 스레드의 단점을 생각하면 쉽다.
- 메인 스레드에서 에러 발생시 서버 전체가 먹통이 될 수 있음
- 멀티 스레드에 비해 CPU intensive한 작업에서 부적합
- 어느 한 작업에서 CPU를 많이 사용한다면, 그 후에 있는 작업들의 처리가 지연되고 응답이 늦어짐
이벤트 루프
JavaScript의 런타임 구성
- 콜스택
코드가 호출되면서, 스택으로 쌓이는 곳. LIFO 방식
- 이벤트 루프
비동기 방식의 함수들을 관리한다. 호출된 비동기 함수를 테스크 큐로 전달하고, 콜스택이 모두 비었을 때 queue에 있던 함수들을 콜스택으로 다시 전달한다.
- 백그라운드
이벤트 리스너나 타이머가 대기하는 곳. 여러 작업이 동시에 실행될 수 있음
- 테스크 큐
이벤트 발생시 백그라운드에서 태스크 큐로 타이머나 이벤트 리스너의 콜백함수를 보냄. 콜스택이 비면 FIFO으로 콜백함수를 콜스택으로 보냄.
(1) 사용자 이벤트 처리, (2) 네트워크 응답 처리, (3) I/O 작업, (4) 시간 지연 기능과 같은 기능에 대해서 비동기 방식으로 작동된다.
예시 [출처: Sunki Baek]
console.log('Hi');
setTimeout(function cb1() {
console.log('cb1');
}, 5000);
console.log('Bye');
언제 JS를 사용해야할까?
서버 개발자로서 웹 브라우저의 동적 기능을 지원하는 스크립트 언어라는 측면보단, Node.js 런타임 위에서 서버개발을 위해 사용되는 프로그래밍 언어라는 측면으로 고려해보았다.
사용해야할 때
- cpu intensive하지않은 가벼운 로직, 작은 크기의 많은 데이터를 주고 받으며 빠른 응답시간을 요구하는 애플리케이션
- 네트워크, 데이터베이스, 디스크 등의 I/O 작업이 많은 서버
- 실시간 채팅 애플리케이션, 주식 차트, JSON 데이터를 제공하는 API 서버 등
그러지 말아야할 때
- cpu intensive한 로직을 지닌 애플리케이션...
- 이런 것을 굳이 노드로 하고 싶다면 AWS 람다, 구글 클라우드 펑션스 같은 서비스에서 노드로 CPU를 많이 사용하는 작업을 지원하므로 고려해볼만 하다.
- 이미지나 비디오 처리, 대규모 데이터 처리 작업을 많이 사용하는 경우
참고자료