구글의 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경인 Node.js의 등장
-> 자바스크립트는 웹 브라우저가 아닌 서버에서도 동작하는 범용 개발 언어
대부분의 프로그래밍 언어는 운영체제, 가상 머신 위에서 동작
<-> 웹 애플리케이션의 클라이언트 사이드 자바스크립트는 브라우저에서 HTML, CSS와 함께 실행
-> 브라우저 환경을 고려할 때 더 효율적인 클라이언트 사이드 자바스크립트 프로그래밍이 가능
파싱
프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽어 들여 실행하기 위해 텍스트 문서의 문자열을 토큰으로 분해하고 문법적 의미와 구조를 반영해 트리 구조의 자료구조인 파스 트리를 생성하는 일련의 과정
렌더링
렌더링은 HTML, CSS, 자바스크립트로 작성된 문서를 파싱해 브라우저에 시각적으로 출력하는 것을 의미
브라우저는 HTML, CSS, 자바스크립트, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받는다.
브라우저의 렌더링 엔진은 서버로부터 응답된 HTML과 CSS를 파싱해 DOM과 CSSOM을 생성하고 이들을 결합해 렌더 트리를 생성
브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱해 AST를 생성하고 바이트코드로 변환해 생성. 이때 자바스크립트는 DOM API를 통해 DOM이나 CSSOM을 변경할 수 있음. 변경된 DOM과 CSSOM은 다시 렌더트리로 결합
렌더 트리를 기반으로 HTML 요소의 레이아웃을 계산하고 브라우저 화면에 HTML 요소를 페인팅
브라우저의 핵심 기능 : 필요한 리소스를 서버에 요청하고 서버로부터 응답 받아 브라우저에 시각적으로 렌더링하는 것
서버에 요청하기 위해 브라우저는 주소창을 제공
브라우저의 주소창에 URL을 입력
-> URL의 호스트 이름이 DNS를 통해 IP 주소로 변환
-> 해당 IP 주소를 갖는 서버에게 요청을 전송
예시
주소창에 https://velog.io 입력시, https://(스킴), velog.io(호스트)로 이루어진 루트 요청이 서버로 전송.
루트 요청에는 명확한 리소스를 요청하는 내용이 없지만, 일반적으로 index.html을 응답하도록 기본 설정.
만약 index.html 이 아닌 다른 파일을 요청하는 경우, path에 작성해 해당 폴더를 요청.
브라우저의 주소창을 통해 서버에게 정적 파일만 요청할 수 있는 것이 아니라, 자바스크립트를 통해 동적으로 서버에 정적/동적 데이터 요청 가능
커넥션 하나당 하나의 요청과 응답만 처리
= 여러개의 요청과 응답을 한번에 전송할 수 없음
-> 요청할 리소스의 개수에 비례해 응답 시간이 증가
여러 리소스의 동시 전송이 가능
-> HTTP/1.1에 비해 페이지 로드 속도가 약 50% 정도 빠름
브라우저의 요청에 의해 서버가 응답한 HTML 문서는 문자열로 이루어진 순수한 텍스트
-> 응답받은 HTML 문서를 파싱해 브라우저가 이해할 수 있는 자료구조인 DOM을 생성
DOM은 HTML 문서를 파싱한 결과물
렌더링 엔진이 한 줄씩 순차적으로 DOM을 생성하다가 link태그나 style 태그를 만나면 DOM 생성을 일시 중단
서버에 css 파일 요청 후, 바이트 - 문자 - 토큰 - 노드 - CSSOM
을 거치며 해석해 CSSOM을 생성
CSSOM은 CSS의 상속을 반영해 생성되기 때문에, 상위에 지정한 스타일이 하위 요소에 전달 됨.
파싱 완료 후, 기존에 작업중이던 HTML 파싱이 중단된 지점으로 돌아가 다시 시작
렌더링 엔진이 서버로 부터 받은 HTML과 CSS를 파싱해 각각 DOM, CSSOM을 생성하고, 이는 렌더링을 위해 렌더 트리로 결합
렌더 트리는 렌더링을 위한 트리 형태의 자료 구조
= 화면에 렌터링되지 않는 노드들은 포함되지 않음
렌더 트리는 레이아웃을 계산하는데 사용되며, 페인팅 처리에 입력 됨.
브라우저 렌더링 과정은 반복해서 실행될 수 있음.
레이아웃 계산과 페인팅은 비용이 많이 드는 작업
= 성능에 악영향
-> 가급적 리렌더링이 발생하지 않도록 주의
자바스크립트 코드에서 DOM API를 사용해 이미 생성된 DOM을 동적으로 조작 가능
CSS 렌더링과정과 비슷하게 script 태그를 만나면 서버에서 파일을 받아 자바스크립트 엔진에 제어권을 넘김
자바스크립트 엔진은 CPU가 이해할 수 있는 저수준의 언어로 변환 및 실행하는 역할을 함
다양한 종류가 있으며, 모든 자바스크립트 엔진은 ECMAScript 준수
자바스크립트 엔진은 AST(추상적 구문 트리)를 생성해 이를 기반으로 인터프리터가 실행할 수 있는 중간 코드(바이트 코드)를 생성 및 실행
토크나이징
단순한 문자열인 자바스크립트 코드를 어휘 분석해 문법적 의미를 갖는 최소 단위인 토큰들로 분해
파싱
토큰들의 집합을 구문 분석해 AST를 생성
AST 사용시, 트랜스파일러를 구현할 수 있음.
바이트코드 생성과 실행
파싱의 결과물로서 생성된 AST는 인터프리터가 실행할 수 있는 바이트코드로 변환되고 인터프리터에 의해 실행
코드의 사용 빈도가 적어지면 디옵티마이징되기도 함.
DOM API에 의해 변경되는 경우, 다시 렌더 트리가 결합되는 과정을 거치면서 변경된 렌터트리를 기반으로 레이아웃과 페인트 과정을 거쳐 브라우저의 화면에 다시 렌더링
레이아웃 계산을 다시 하는 것
렌더트리를 기반으로 다시 페인트 하는 것.
리플로우와 리페인팅이 순차적으로 동시에 실행되는 것 ❌
레이아웃에 영향이 없는 경우 리페인팅만 실행되기도 함.
렌더링 엔진과 자바스크립트 엔진은 직렬적으로 파싱 수행
동기적으로 실행되기 때문에, HTML이 블로킹되어 실행이 지연될 수 있음.
그렇기 때문에 가장 아래에 자바스크립트를 위치시키는 것을 권장
자바스크립트 파싱에 의한 DOM 생성이 중단되는 문제를 근본적으로 해결하기 위해 등장
외부 자바스크립트 파일을 불러오는 경우에만 사용 가능
인라인 자바스크립트로는 사용 불가
<script async src="extern.js"/>
<script defer src="extern.js"/>
HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행
-> 자바스크립트의 실행 시점의 차이 존재
파일 로드가 동시에 진행되며, 자바스크립트 파일 로드가 끝남과 동시에 실행. 이 때 HTML 파싱 중단
여러개의 script 태그에 async를 지정하면, 태그의 순서와 상관없이 먼저 로드가 완료된 순서부터 실행
-> 순서 보장 ❌
자바스크립트의 파싱과 실행은 HTML파싱이 완료된 직후 (DOMContentLoaded 이벤트 발생)