상권's

TIL 54 (복습) 본문

~2022 작성 글/TIL

TIL 54 (복습)

라마치 2022. 2. 4. 22:41

* 앞 서 학습했던 내용을 복습하기 위해 질문과 답변 형태로 작성했습니다. 질문에 대해 개인적으로 이해하고 작성한 답변이기에 내용이 빈약하거나, 오류가 있을 수 있다는 점 양해 부탁드립니다.

 

Javascript와 Nodejs가 어떻게 다른 것인지 설명해주세요.

자바스크립트는 개발 언어이며, Nodejs는 자바스크립트 런타임입니다.

Nodejs는 크롬 V8엔진으로 빌드되어 자바스크립트라는 특정한 언어로 구현한 프로그램을 실행 시키는 환경입니다.

추가 : 기존에는 자바스크립트 프로그램을 웹 브라우저 위에서만 실행할 수 있었습니다. 브라우저 외의 환경에서 실행하기 위해 나온 것이 노드입니다.

 

모든 자바스크립트 파일을 브라우저에서 한 번에 로딩 할 때의 문제점을 설명해주세요.

브라우저가 HTML 파일을 파싱할 때 스크립트 파일을 마주하면 해당 파일을 동기적으로 로드합니다. 이때 한 번에 자바스크립트 파일을 로드하게 되면 HTML 파일 파싱과 화면 출력이 늦어짐으로써 나쁜 사용자 경험을 제공하고 유저 이탈로 이어질 수 있습니다.

 

추가 : 브라우저는 렌더링 엔진을 이용해 HTML, CSS 파일을 파싱해 페이지를 화면에 표시합니다. 자바스크립트는 자바스크립트 해석기를 통해 해석이 됩니다. script 태그가 HTML 중간에 위치할 경우 파싱이 부분은 표시되지만 script 이후 부분은 파싱이 되질 않아 사용자 경험을 나쁘게 만들 수 있습니다. 그래서 body 태그 마지막에 script 태그를 넣음으로써 위의 문제를 해결할 수 있지만, 이 방법은 자바스크립트 의존적인 웹일 경우, 아무런 반응이 없기 때문에 사용자 경험이 나뻐질 수 있습니다.

script 태그에 async, defer 속성을 추가하여 파싱과 script 파일 로드가 동시에 진행될 수 있습니다. async의 경우, script 파일 로드가 파싱을 차단하지 않을 뿐 script 로드가 완료하는 즉시 script가 실행되고 이 때에는 차단이 이뤄지게 됩니다. 단점으로는 script 파일이 먼저 로드되고 실행되어 DOM에 접근하려는 데, 아직 HTML 파일 파싱이 완성되지 않았다면 에러를 발생시킬 수 있습니다. 반면 defer의 경우, script파일 로드가 HTML 파싱을 차단하지 않고,  HTML 파싱이 전부 이뤄지고 난 후 script가 실행되게 됩니다.

 

출처 1

출처 2

출처 3

 

Node.js는 싱글스레드 인가요? Node.js 런타임이 동작하는 방식을 설명해주세요.

Nodejs는 엄밀히 말하자면 싱글 스레드로 동작하지 않습니다. Nodejs를 실행하면 프로세스가 생성되고, 이 프로세스가 스레드를 여러 개 생성합니다. 하지만 직접 제어할 수 있는 스레드는 하나뿐이기 때문에 싱글 스레드라도 여겨집니다.  

Nodejs는 크롬 V8 자바스크립트 엔진과 Libuv라는 라이브러리를 사용합니다. 이를 통해 이벤트 기반, 논 블로킹 I/O 모델로 동작합니다.

Nodejs는 이벤트 기반으로, 이벤트 루프를 통해 콜백 함수들이 관리됩니다.

이벤트 리스너에 콜백함수를 등록한 후 해당 이벤트가 실행되면 콜백함수가 작동합니다. 백그라운드에서 대기하고 있던 콜백함수는 태스크 큐로 이동하게 되고 호출스택이 비워진다면 이벤트 루프가 콜백함수를 호출스택으로 올리고, 콜백함수가 실행됩니다.

다음으로 논 블로킹 I/O 입니다. I/O는 입력과 출력을 의미하며 동시에 처리될 수 있는 작업으로 파일시스템 접근이나 네트워크 요청 등이 있습니다. Nodejs는 동시에 처리될 수 있는 작업은 백그라운드에 넘겨 처리를 합니다. 이를 통해 동일한 작업도 더 짧은 시간에 처리할 수 있습니다.

코드스테이츠 모의기술면접 당시 답변
노드js는 여러개의 스레드를 가지고 있지만, 
자바스크립트를 실행하는 스레드가 단 하나이므로 노드js를 싱글스레드라고 할 수 있습니다.

Node.js는 Google의 Chrome V8 자바스크립트 엔진을 기본으로 동작합니다. 
Single Thread 기반의 Event Loop (libuv)가 돌면서 요청을 처리하며, 
시스템적으로 non-blocking io를 지원하지 않는 io 호출이 있는 경우, 
이를 비동기 처리 하기 위해서 내부의 Thread pool (libio)을 별도 이용하여 처리하게 됩니다.

추가 : 노드 14버전부터 멀티 스레드를 사용 가능해졌습니다. 코딩한 자바스크립트가 차지하는 스레드가 하나 뿐입니다. 전역컨텍스트는 함수가 호출되었을 때 생성되는 환경을 의미합니다.

 

Node.js에서 비동기의 개념은 어떻게 되나요.

1. Nodejs에서 동기, 비동기는 백그라운드 작업 완료 확인 여부에 따라 구분됩니다. 이는 함수가 바로 리턴되는 지 여부를 확인하는 블로킹, 논 블로킹과 함께 사용될 수 있습니다. 비동기-논 블로킹 방식의 경우, 호출한 함수가 바로 리턴되어 다음 작업으로 넘어가며, 백그라운드 작업 완료 여부는 신경 쓰지 않고 나중에 백그라운드가 알림을 줄 때 비로소 처리가 됩니다.

 

2. Nodejs에서 비동기는 setTime 함수로 설명을 드리겠습니다. 3초 뒤에 콘솔로그가 실행되는 setTimeout 함수 앞 뒤로 콘솔로그가 작성되어 있을 때, 코드를 실행시키면 첫번째 콘솔로그, 세번째 콘솔로그, 마지막으로 setTimeout 함수의 콘솔로그가 진행됩니다. setTimeout 함수의 경우 실행이 되면 백그라운드로 이동해 3초가 지나면 콘솔로그가 테스크큐로 이동하고 호출스택이 비워진다면 그때 이벤트루프가 콘솔로그를 호출스택으로 올려 작동되게 됩니다.

이처럼 setTimeout 함수가 진행 실행되는 3초를 기다리지 않고 다음 코드 실행으로 넘어가는 것이 비동기입니다.

 

추가 : Nodejs에서 먼저, 변수가 선언한 후 ajax 요청 내부에서 변수에 값을 할당하고, 마지막에 해당 변수를 출력하는 코드를 실행시킨다면 마지막 변수 출력 시 ajax 요청이 비동기로 처리되는 동안 마지막 출력 코드가 먼저 실행되어 undefined가 출력될 수 있습니다. 

이러한 비동기방식에 의한 문제를 해결하는 방법으로 콜백함수, promise, async/await가 있습니다. 콜백함수는 매개변수로 전달된 함수인데, 이 경우 함수 내에서 또 함수가 실행되고, 또 그 내부에서 함수가 실행되며 이른바 콜백지옥을 만들어냅니다. 이러한 콜백지옥을 promise의 then과 catch를 활용하여 promise 체이닝으로 해결할 수 있으며, aysnc/await으로 동기적으로 이해할 수 있는 코드를 구현할 수 있습니다.

 

리팩토링 계획 : 프로젝트 당시 코드 구현이 급급해서 복습을 하지 않아 async/await의 경우 맨 마지막 catch문으로 에러를 해결할 수 있음에도 then 마다 catch를 작성했습니다. 남에게 말하기 부끄럽지만 이 기회를 통해 다시 한 번 더 학습하고 반영할 예정.

'~2022 작성 글 > TIL' 카테고리의 다른 글

TIL 56 (복습)  (0) 2022.02.09
TIL 55 (복습)  (0) 2022.02.06
TIL 53 (배포 자동화)(2021.12.06)  (0) 2021.12.06
TIL 52 (Docker, Docker-compose, AWS ECS)(2021.12.03)  (0) 2021.12.03
TIL 51 (HTTP/1,2,3, git branch)(2021.12.02)  (0) 2021.12.02
Comments