모던 JS 딥 다이브를 공부하며 정리해보는 글입니다.
모든 브라우저와 Node.js는 자바스크립트 엔진을 내장함.
주의 : 브라우저와 Node.js의 용도가 다름
브라우저 : HTML, CSS, JS를 실행해 웹페이지를 브라우저 화면에 렌더링
Node.js : 브라우저 외부에서 자바스크립트 실행 환경을 제공하는 것이 주된 목적.
둘 다 ECMAScript 실행 가능 but 각자 추가 기능은 호환 X
예) 브라우저는 파싱된 HTML 요소 선택, 조적하는 기능인 DOM API를 기본 제공 but 브라우저 외부에서 JS 개발 환경을 제공하는 Node.js는 DOM API 제공하지 않는다(외부에선 HTML 요소를 파싱해서 객체화한 DOM을 조작할 필요가 없기 때문)
예2) 브라우저는 파일 읽기만 가능 but Node.js는 파일 생성, 수정 가능한 파일 시스템 제공 (브라우저에서 파일 조작 가능하면 해킹에 취약해지기 때문)
결론 : 브라우저는 클라이언트 사이드 WEB API 제공
Node.js는 Node.js 고유의 API를 지원
크롬 권장 ( 점유율 가장 높고 크롬의 V8엔진은 Node.js에서도 사용함)
개발자 도구는 웹 개발에 필수
| dd | dd |
| --- | --- |
| Elements | 로딩된 웹 페이지의 DOM과 CSS를 편집하여 렌더링된 뷰를 확인해 볼 수 있다. 단, 편집한 내용이 저장되지는 않는다. 웹 페이지가 의도된 대로 렌더링되지 않았다면 이 패널을 확인하여 유용한 힌트를 얻을 수 있다. |
| Console | 로딩된 웹 페이지의 에러를 확인하거나 자바스크립트 소스코드에 포함시킨 console.log 메소드의 결과를 확인해 볼 수 있다. |
| Sources | 로딩된 웹 페이지의 자바스크립트 코드를 디버깅할 수 있다. |
| Network | 로딩된 웹 페이지에 관련한 네트워크 요청(request) 정보와 퍼포먼스를 확인할 수 있다. |
| Application | 웹 스토리지, 세션, 쿠키를 확인하고 관리할 수 있다 |
- Node.js는 V8엔진으로 빌드된 JS 런타임 환경이다.
- 브라우저 이외에서도 사용가능하게 해주는 것
- npm(node package manager)은 JS 패키지 매니저다.
- Node.js에서 사용가능한 모듈들을 패키지화 해서 모아둔 저장소역할 + 패키지 설치 및 관리를 위한 CLI(Command Line interface)를 제공
(모듈화 참고)
node -v // 버전나옴
npm -v // 버전 나옴
//터미널에서
node // 프롬프트가 > 로 변경되면 JS 코드 실행 가능
>1 + 2
3
>Math.max(1,2,3)
3
//JS 파일 실행하기
node index.js (js 생략 가능)
ctrl + c 두번 입력 종료
- 브라우저의 핵심 기능 - Critical Rendering Path(CRP)
사용자가 참조하고자 하는 웹페이지를 서버에 요청(Request)하고 서버의 응답(Response)을 받아 브라우저에 표시하는 것이다.- CRP 6단계
- DOM 트리 생성
->완전히 파싱된 HTML 트리.- CSSOM 트리 생성
->각 노드에 속성을 부여하는 트리- JS 실행
- Render 트리 생성
-> DOM과 CSSOM이 합쳐지는 단계- 레이아웃 생성
-> 뷰포트의 크기를 결정하며 의 viewport 속성을 통해 결정되는데 기본 뷰포트 너비는 980px.(일반적으로 메타태그의 뷰포트 값은 장치 너비에 맞게 설정한다.)- 페인팅
-> 페이지의 가시적 내용을 픽셀로 변환하여 화면에 표시.
- 전체적인 과정
브라우저는 서버에서 HTML, CSS, JS, 이미지파일 등을 응답받는다.
HTML, CSS는 렌더링엔진의 Parser에 의해 파싱되어 DOM, CSSOM 트리로 변환되고 렌더 트리로 결합된다.
HTML 파서는 script 태그를 만나면 JS 코드를 실행하기 위해 DOM 생성 프로세스를 중지하고 JS 엔진으로 제어 권한을 넘긴다.
(JS는 렌더링 엔진이 아닌 JS 엔진이 처리한다.)
권한을 받은 JS 엔진은 script 내의 JS 코드 또는 scr 속성에 정의된 JS 파일을 로드하여 파싱하고 실행한다.
완료되면 브라우저는 중지된 시점부터 DOM 생성을 재개한다.
DOM, CSSOM 트리 생성 완료되면 둘을 합친 렌더 트리를 생성하고 이것을 기반으로 브라우저는 웹페이지를 표시
그림출처) https://poiemaweb.com/js-browser
이처럼 브라우저는 동기적으로 HTML,CSS,JS를 처리한다.
때문에 script 태그의 위치에 따라 블로킹이 발생하여 DOM의 생성이 지연될 수 있다. 따라서 script 태그의 위치는 중요하다.
권장: body 요소의 가장 아래에 JS 위치.
이유
실행 컨텍스트에 관한 자세한 설명 링크
Stack & Queue
다른 언어들은
console.log(1 + 1);
setTimeout(() => {}, 1000);
console.log(2 + 2);
이렇게 짜면 2 -> 1초 후에 -> 4
이런 식으로 출력된다. 하지만 JS는
바로 2와 4가 출력됨. 따라서 아래처럼 넣어줘야 함.
console.log(1 + 1);
setTimeout(() => {
console.log(2 + 2);
}, 1000);
이 경우도
console.log(1 + 1);
setTimeout(() => {
console.log(2 + 2);
}, 1000);
console.log(3 + 3);
2 4 -> (1초후에) 4
왜 그런지 원리를 알아보자.
웹 브라우저 : 코드 해석해서 실행시켜주는 엔진
코드들은 Stack이라는 공간에 한줄 한줄 쌓여서 순서대로 실행된다.
JS는 Stack이 하나 밖에 없기 때문에 single threaded language라고 불림.
따라서 JS는 기본적으로 병렬처리 안되는 구조임.
console.log(1 + 1);
setTimeout(() => {
console.log(2 + 2);
}, 1000);
console.log(3 + 3);
바로 실행할 수 있는 콘솔로그를 먼저 실행하고
타임아웃은 잠시 대기실에 보낸 다음 콘솔로그가 다 실행 되면 그 때 실행시킴.
대기실로 보내는 코드 종류
Ajax(데이터 요청)
이벤트리스너
setTimeout(callback,time)
이런 시간이 걸리는 코드들은 Queue라는 대기실에서 대기가 끝난 코드들을 줄을 세움. -> 순서대로 Stack에 보내서 실행시킴.
조건 !! : Stack이 비었을 때 올려 보낸다.
작동원리 정리
예시1)
console.log(1 + 1); // 1번 실행
setTimeout(() => {
console.log(2 + 2); // 대기실로 이동
}, 1000);
console.log(3 + 3); // 2번 실행
// 2번 실행 후 setTimeout은 Queue로 보내지고
// Stack이 비었으면 stack으로 보내져서 실행 됨.
예시2)
console.log(1 + 1);
setTimeout(() => {
console.log(2 + 2);
}, 0);
console.log(3 + 3);
이 경우에도 2 6 4.
예시3)
console.log(1 + 1); // 1번
setTimeout(() => {
console.log(2 + 2); // 1초 4번
}, 1000);
setTimeout(() => {
console.log(4 + 4); // 0.5초니까 3번
}, 500);
console.log(3 + 3); // 2번
10초씩 걸리는 반복문의 경우
만약 바로 실행되는 반복문 코드가 10초가 소요된다고 가정하면.
대기실로 가는 코드들은 이 코드가 처리될 때 까지 Queue에서 Stack으로 전달되지 못하게 된다.
결과 만약 모달창 같은 것을 만들어 놨는데 10초가 지나 Stack이 비워지기 전까지는 실행되지 못하는 경우가 생김.
🧨 브라우저 프리징의 원인!!
결론
Stack을 바쁘게 ㄴㄴ
Queue도 바쁘게 ㄴㄴ
자바 스크립트는 동기적인 처리를 하지만 Ajax, 이벤트리스너 등 비동기적인 처리도 가능하게 된다.