최근에 자스 비동기 관련 질문 받고 생각해보니까
브라우저가 멀티스레딩=web api이기 때문에 비동기처럼? 동작한다. 실제 자스 엔진은 싱글 스레드로 동작한다.
여기까지만 생각했는데 생각해보니? 결국 결과도 콜백큐에서 이벤트 루프가 가져와서 자스 콜스택에 쌓아준거니까 사실상 결과만 받은거라 매우 빠르게 처리되지만???
그래도 여전히 동기적으로 처리된다는 느낌은 받았다
그런데 우연히 제목글을 보고 노드…는 브라우저가 없잖아? 헐 그럼 얘는 뭐지?싶었다
브라우저와 노드
사실상 둘다 자바스크립트를 실행하기 위한 환경, 즉 런타임이다.
브라우저는 web api나 콜백큐 가지고 있는데 노드는 어떻게 하나 살펴보니
둘다 v8 엔진을 사용해서, 필요한 환경 = 멀티스레드 뭔가, 콜백큐
이렇게 가지고 있다.
브라우저와 다른 점은 web api 역항르 libuv 라이브러리가 대신해준다는 것이다.
이 안에는 스레드 풀이 기본 4개 있어서 I/O 작업 같은 것도 백그라운드 스레드에서 병렬로 처리한다고 한다
내용
핵심은 결국 노드는 싱글스레드라는 것이다.
자스를 실행할 때 하나의 메인 스레드, 콜백큐를 사용하는데
얘는 오래 걸리는 작업은 직접 처리하지 않는다.
I/O같은 파일 접근이나 디비 쿼리, http 요청같은 것들을 시간이 오래 걸릴 수 있으므로
노드는 이런 작업을 libuv에게 넘긴다.
암튼 위에서 혼자 주절거린 것과 비슷한 내용이고
작업은 병렬로 처리되지만 콜백은 순차적으로 메인 스레드에서 실행되는 구조입니다.
오
싱글스레드가 터지는 순간
- 이미지 / 비디오 인코딩, 디코딩
- 수백만 개의 JSON 문자열 파싱
- 대용량 리스트 정렬, 필터링
- 암호화, 복호화 같은 연산
이러한 작업들은 I/O가 아니라 실제로 cpu가 계산해야 하는 일이기 때문에 저 libuv 친구에게 떠넘길 수가 없다. 그렇다면? 메인스레드에서 저걸 계속 잡고 있는 상태가 된다는 것. 사고다.
이런 상황에서 자바 스프링같은 서버는 요청 하나가 무거워도, 스레드풀에서 남는 스레드가 다른 요청을 처리해준다. 싱글스레드가 아니기 때문에…
즉, Node.js는 가볍고 빠르지만, 진짜 무거운 CPU 작업이 들어오면 조용하게 멈춰버리는 구조입니다.
그리고 그 침묵은… 서버 운영자 입장에서는 꽤나 무섭습니다.
ㅎㄷㄷ
백엔드로서의 노드?
이러한 치명적인 단점이 있기 때문에 가벼운 서비스에서는 충분히 백엔드의 역할을 대체할 수 있겠지만 진짜 트래픽은 어렵다.
하지만?
노드는 컨테이너 환경에서의 가벼움, 스케일아웃에 최적화된 구조, I/O 중심 처리에 강한 런타임 특성 등 꽤 실용적인 장점들이 있다.
필요한 만큼 만들고 명확하게 쪼개어 확장하기에는 유리한 선택지.
(어렵군)
실제 사례 60억 건 마이그레이션
요약하면 카프카,몽고db로 구성된 화면에서 데이터를 더 가져와서 어떻게 리뉴얼하는 과정.
k8s 환경이라
kubectl top pods로 바로 확인할 수 있었는데, Node.js Pod가 1020~1030m 수준으로 CPU를 풀로 사용 중이었습니다.
싱글스레드가 코어 하나를 풀로 쓰면서 혼자 죽도록 파싱을 하고 있었던 거죠.
ㅎㄷㄷ;;
어떻게 해결? 스케일아웃
노드가 죽도록 일하고 있다면 여러 명이 죽도록 일하도록.
여러개를 띄우자!
노드처럼 가볍고 구조가 뚜렷하게 쪼개지는 런타임에서는 이 전략이 생각보다 훨씬 강력하게 작동합니다.
재미있는 건 이 구조가 API 서버에도 똑같이 적용된다는 겁니다.
Node.js는 싱글스레드 서버이지만, k8s에서 여러 개 띄우면 멀티스레드 서버처럼 운용할 수 있습니다.
마무리, 실러불릿은 없다
튜링상 수상자인 프레드 브룩스는 1986년 유명한 논문(No Silver Bullet)에서 이렇게 말했습니다.
“소프트웨어 개발에는 모든 문제를 단번에 해결해주는 은 탄환은 없다.”
후기
술술 잘읽히는 글이었다 노드 백엔드…생소해서 거의 복붙해버렸지만 ㅠㅠ 인사이트 미쳤다 배워나갈게많군

