WAS 부터 이벤트 루프 까지

2jun0·2022년 8월 26일
0
post-thumbnail

왜 node.js는 톰캣을 안쓸까?

SpringBoot를 공부하다 갑자기 이상한 의문이 들었다.

왜 java의 spring은 톰캣이 필요하고 node.js의 express는 톰캣을 안쓸까?

일단 was의 정의 부터 바로 잡아야 했다.

java에서 톰캣이 하는 역할은 서블릿 컨테이너다.
일단 요청을 받으면 서블릿을 실행하는데, 하나의 서블릿에 하나의 스레드가 할당된다.
멀티 스레드 방식이라는 것이다.
다양한 요청이 들어와도 별개의 스레드로 나눠두었기 때문에 하나의 요청이 지연 되더라도 다른 스레드는 멈추지 않는다!

그런데 이 방법에 문제가 있다.

스레드가 많으면 좋은 것 같지만, 자원의 낭비가 심해진다. 계속 컨텍스트 스위칭이 일어나기 때문이다.
그래서 스레드 풀이란 것을 만들어 두고 스레드 개수를 제한 하는데, 문제가 있다.
스레드들이 오래 걸리는 I/O 작업을 실행하면서 스레드 자원을 점령하는 일이 생긴다.

그럼 node.js는 어떻게 하길래?

node.js는 단일 스레드로 동작한다. 메인 스레드가 멈추지 않는 non-blocking 방식을 사용한다고 한다.

와 대단하다! 자바도 바꾸지 그래?

자바는 이미 오래되었고, legacy 방식이 이미 고착화 되어있어 힘들다고 한다.

그래도 Spring WebFlux 같은 기술들이 나오면서 노력중이다.
Spring WebFlux는 Netty라는 was 서버를 밀고 있다.
Netty에서 non-blocking 방식을 지원해주는 것 같다. (뇌피셜)

엥? 또 was 서버인가? express.js에 was가 있는건가?

그건 엄밀히 말하면 아니다! express.js는 그냥 편리도구일 뿐이다

그럼 node.js에 was가 내장되어 있다는 거지?

그게 아니라니까!

일단 브라우저 환경을 보자

브라우저에선 다들 알다시피 javascript를 쓴다. 이것밖에 안되고 그냥 이거 원툴이다.
근데 V8같은 javascript엔진은 단일 스택에 단일 힙을 쓴다.
다중 처리가 그냥 안된다 그런거 지원 안한다.

근데 여러 웹 서비스는 다중 처리를 지원한다. 어떻게 하는 걸까?
브라우저가 해주는 거다.

브라우저가 제공하는 Web Api가 "이벤트 루프" 방식으로 다중 처리를 지원한다.
우리가 아는 setTimeout도 브라우저 지원이고 Promise도 브라우저 지원이다.

이벤트 루프는 뭔데?

setTimeout같은 함수는 스택에 태스크들을 저장해두지 않는다.
아까 말한대로 js엔진 외부지원이라 외부로 "이거 실행 해줘" 하고 스택에서 빼버린다.

그리고 큐에 차곡차곡 쌓였다가 스택이 비면 큐에서 하나씩 꺼내서 스택에 올린다.

더 자세한 설명은 아래에 있다.

https://meetup.toast.com/posts/89
https://www.youtube.com/watch?v=6MXRNXXgP_0

아무튼 그렇게 하는 것이다.

node.js는 브라우저가 아닌데?

node.js도 브라우저 환경과 비슷하게 돌아간다고 생각하면 쉽다.
node.js에는 V8엔진과 libuv가 있다.

libuv에서 이벤트 루프를 지원한다. 게다가 I/O처리를 비동기로 지원해준다.

libuv는 멀티스레드로 동작하는건가?

libuv는 커널에서 비동기 처리를 지원하는 작업은 커널에 보내버린다.
하지만 커널에서 비동기 처리를 지원하지 않는 File I/O같은 경우는 멀티 스레드를 쓴다.
여기도 thread pool이 있다.

결론.

was는 그냥 서버고 문제는 전통적인 was에 있다.
전통적인 was는 요청이 올때마다 무작정 thread를 사용하는 문제를 기본적으로 node.js에선 최소한으로 쓴다고 결론짓겠다.

profile
끄적끄적

0개의 댓글