32장 String
33장 Symbol
- 심벌이란?
- 다른 값과 중복되지 않는 유일무이한 값. → 유일한 프로퍼티 키 만드는 데 사용.
- ES6에서 도입된 7번째 데이터 타입으로, 원시값.
- 심벌 값 생성
- Symbol 함수를 호출하여 생성하는 방법밖에 없음.
- new 연산자를 사용하지 않음.
- String, Number, Boolean 등의 생성자 함수는 new 연산자와 함께 호출하여 인스턴스(객체)를 생성.
- 하지만 심벌은 객체가 아니라 원시값을 생성하는 거기 때문에 new 연산자와 함께 호출하지 않음.
- Symbol 함수를 호출할 때 괄호 안에 문자열을 인수로 전달할 수 있지만 값에는 영향이 없고, 생성될 심벌 값에 대한 설명.
- 특징
- 생성된 값은 외부로 노출되지 않기 때문에 확인할 수 없음.
- 객체처럼 접근하면, 래퍼 객체를 생성하여 Symbol.prototype의 프로퍼티를 실행할 수 있음.
- 숫자나 문자열로 암묵적 타입 변환되지는 않지만 불리언으로는 타입 변환됨. 값의 존재 여부를 확인할 때 사용할 수 있음.
38장 브라우저의 렌더링 과정
브라우저는 HTML, CSS, 자바스크립트로 작성한 텍스트 문서를 파싱(해석)하여 브라우저에 렌더링한다.
- 파싱 : 텍스트 문서(코드)를 1) 토큰으로 분해하여, 2) 문법적 의미와 구조를 반영하여, 3) 파스 트리를 생성하는 과정
- 렌더링 : 파싱하여 브라우저에 시각적으로 출력
< 브라우저의 렌더링 과정 >
- 브라우저가 렌더링에 필요한 리소스를 요청하여 서버로부터 응답 받음.
- HTML, CSS, 자바스크립트, 이미지, 폰트 파일 등
- 렌더링 엔진이 HTML과 CSS 파싱하여 DOM과 CSSOM 생성. 이 둘을 결합하여 렌더 트리 생성.
- 자바스크립트 엔진이 자바스크립트 파싱하여 AST 생성 후, 바이트코드로 변환하여 실행.
- 자바스크립트가 DOM API를 통해 DOM이나 CSSOM을 변경할 경우, 변경된 DOM과 CSSOM이 다시 렌더 트리로 결합됨.
- 렌더 트리를 기반으로 HTML 요소의 레이아웃을 계산하여 화면에 페인팅.
38.1 요청과 응답
렌더링에 필요한 리소스는 서버에 존재하므로 브라우저가 요청해야 한다. 서버에 요청하기 위해 브라우저에 주소창이 존재한다. URL을 입력하면 호스트 이름(도메인)이 DNS를 통해 IP 주소로 변환되어 해당 서버에 요청이 전송된다.
[ 662쪽 URI 예시 참고 ]
* 루트(/) 요청 : 스킴(프로토콜)과 호스트만으로 구성된 URI 요청. 일반적으로 서버는 index.html을 응답한다. 즉, https://naver.com은 https://naver.com/index.html와 같다.
서버의 루트 폴더를 기준으로 정적 파일의 경로와 파일명을 호스트(도메인) 뒤에 path로 기술하여 요청하면 서버는 해당 파일을 응답해줄 것이다.
이렇게 URI에 따라 응답 받은 html 파일을 파싱하면서, 외부 리소스를 추가로 로드하는 태그가 있을 때, HTML 파싱을 중단하고 해당 리소스 파일을 서버에 요청한다. 따라서 URI에서 명시적으로 요청하지 않은 리소스들도 응답받는다.
38.2 HTTP 1.1과 HTTP 2.0
* HTTP : 웹에서 브라우저와 서버가 통신하기 위한 프로토콜(규약). 1989년에 고안되어 1999년에 HTTP/1.1, 2015년에 HTTP/2가 발표됨.
* HTTP/1.1 : 커넥션당 하나의 요청과 응답만 처리. 즉, HTML 문서에 포함된 여러 개의 리소스 요청과 응답이 개별적으로 전송. 따라서 요청할 리소스 개수에 따라 응답 시간이 증가함.
* HTTP/2 : 커넥션당 다중 요청/응답 가능. 페이지 로드 속도가 50% 더 빠름.
==> Q. 커넥션이란 게 뭔가??
38.3 HTML 파싱과 DOM 생성
HTML 문서는 텍스트이므로 브라우저에 시각적으로 렌더링하려면, 파싱하여 브라우저가 이해할 수 있는 "객체"로 변환하여 메모리에 저장해야 한다. HTML 문서를 파싱하여 객체로 변환한 자료구조가 바로 DOM이다.
[ 666쪽 그림 38-6 참고 ]
파싱 과정 : 바이트 → 문자 → 토큰 → 노드 → CSSOM
- html 파일 전송 : 서버의 html 파일을 요청하면, 서버가 해당 파일을 읽어 메모리에 저장한 다음, 저장된 2진수 바이트를 인터넷을 통해 전송한다.
- 문자열 변환 : 브라우저는 이 2진수 바이트 형태의 html 문서를 <meta charset="UTF-8"> 태그의 charset 어트리뷰트가 지정한 인코딩 방식으로 문자열로 변환한다.
- meta 태그에서 선언된 인코딩 방식은 응답 헤더에 담겨와, 브라우저가 확인할 수 있다.
- 토큰 분해 : 문자열의 html 문서를 읽어, 토큰(문법적 의미를 갖는 코드의 최소 단위)으로 분해한다.
- 노드 생성 : 토큰을 객체로 변환하여 노드 생성. 토큰 내용에 따라 노드 종류가 달라진다. 노드는 DOM을 구성하는 기본 요소.
노드가 뭔지 궁금했는데 이렇게 생기는 거구나. html 요소(element) 같은 거라고 생각했는데 토큰이 단위인 것 같다.- ==> Q. 노드 개념
- DOM 구성 : html 요소는 중첩 관계(부모자식 관계)를 갖는다. 이 관계에 따라 노드를 트리 자료구조(DOM)로 구성한다.
38.4 CSS 파싱과 CSSOM 생성
- 렌더링 엔진이 HTML을 파싱하여 DOM을 생성해 나가다가 CSS를 로드하게 되면 DOM 생성을 중단한다.
- HTML 문서의 <link> 태그에 연결된 CSS 파일을 서버에 요청하여 받거나, <style> 태그의 CSS를 읽어 파싱한다.
- CSS를 파싱하면 HTML 파싱과 같은 과정을 거쳐 CSSOM을 생성한다.
- CSS 파싱을 마치면 다시 HTML 파싱을 이어간다.
CSS는 HTML 요소의 부모자식 관계에 따라 상속된다. 그리고 CSSOM은 CSS 상속을 반영하여 생성된다.
38.5 렌더 트리 생성
렌더링 엔진이 HTML과 CSS를 파싱하여 생성한 DOM과 CSSOM은 렌더 트리로 결합된다. 렌더 트리는 렌더링을 위한 트리구조의 자료구조로, 화면에 렌더링되지 않는 노드는 포함되지 않는다.
[ 669쪽 ]
완성된 렌더 트리로 HTML 요소의 레이아웃을 계산하여 브라우저 화면에 픽셀을 렌더링(페인팅)한다. 자바스크립트 코드 실행, 브라우저 창 크기 변경 등으로 인해 HTML 요소의 레이아웃이 변경될 경우 브라우저의 렌더링 과정이 반복(리렌더링)될 수 있다. 리렌더링은 성능에 안 좋으므로 주의하자.
38.6 자바스크립트 파싱과 실행
* DOM API : DOM이 제공하는, HTML 요소와 스타일을 변경할 수 있는 프로그래밍 인터페이스. 자바스크립트 코드에서 DOM API를 이용하여, 생성된 DOM을 동적으로 조작할 수 있음.
- 렌더링 엔진은 HTML을 파싱하다가 CSS를 만났을 때처럼, 자바스크립트 코드를 만나면 DOM 생성을 중지한다.
- 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에 제어권을 넘긴다.
- 자바스크립트 코드를 파싱하여 CPU가 이해할 수 있는 저수준 언어로 변환하고 실행.
- DOM, CSSOM 생성하는 것처럼 자바스크립트 코드를 해석하여 AST(추상적 구문 트리) 생성. AST를 기반으로 바이트코드 생성 및 실행.
- 자바스크립트 파싱 및 실행이 끝나면 렌더링 엔진이 다시 HTML 파싱을 진행한다.
[ 671쪽 ]
- 토크나이징 : 문자열인 소스코드를 어휘 분석하여 토큰으로 분해. (렉싱이라고도 부르지만 정확히 일치하는 개념은 아님.)
- 파싱 : 토큰의 집합을 구문 분석하여 AST 생성.
- AST : 토큰에 문법적 의미와 구조를 반영한 트리 구조의 자료구조. AST는 인터프리터나 컴파일러뿐 아니라, 트랜스파일러(타입스크립트, 바벨, 프리티어)도 구현할 수 있음.
- 바이트코드 : 인터프리터가 실행할 수 있는 중간 코드. AST에서 바이트코드로 변환됨.
38.7 리플로우와 리페인트
자바스크립트에서 DOM API를 사용하여 DOM, CSSOM이 변경되면, 변경된 DOM과 CSSOM이 다시 렌더 트리에 결합되고 이를 기반으로 리렌더링된다.
- 리플로우 : 레이아웃 다시 계산하는 것. 노드 추가/삭제, 요소의 크기/위치 변경, 윈도우 리사이징 등의 경우.
- 리페인트 : 재결합된 렌더 트리를 기반으로 다시 페인트 하는 것. 레이아웃에 변화 없을 땐 리페인트만 실행됨.
38.8 자바스크립트 파싱에 의한 HTML 파싱 중단
렌더링 엔진과 자바스립트 엔진은 병렬적으로(동시에) 파싱하지 않는다. 브라우저는 동기적으로, 즉 순차적으로 코드를 파싱하고 실행하기 때문이다. 따라서 1) <script> 태그의 위치에 따라 DOM 생성이 지연될 수 있다. 즉, 페이지 로딩 시간이 길어진다.
또한 <script> 태그가 불러온 자바스크립트 코드에서 2) DOM API를 사용할 경우, DOM 또는 CSSOM이 완전히 생성되지 않았을 때 문제가 될 수 있다.
==> 그러니 자바스크립트는 body 가장 아래에 위치시키자.
38.9 script 태그의 async/defer 어트리뷰트
<script>에 src 어트리뷰트를 통해 외부 자바스크립트 파일을 로드하는 경우, async와 defer 어트리뷰트를 사용해서 html과 자바스크립트 파싱을 비동기적으로 동시 진행할 수 있다. async와 defer는 자바스크립트 실행 시점이 다르다.
- async : 자바스크립트 로드 직후 파싱과 실행을 진행하며 HTML 파싱이 중단된다. 따라서 여러 <script> 태그에 적용할 경우, 태그의 순서가 아니라 자바스크립트 로드 순서대로 실행되므로 순서가 보장되어야 할 땐 사용하지 않아야 한다.
- defer : HTML 파싱 완료 직후 자바스크립트 파싱과 실행을 시작한다. 따라서 DOM 생성 후 자바스크립트가 실행되어야할 때 유용하다.
'TIL' 카테고리의 다른 글
[TIL-188] MyView 프로젝트 - MUI X DateTimePicker 사용하기 (0) | 2022.06.15 |
---|---|
[TIL-187] MyView 프로젝트 - React props로 컴포넌트 전달 & text-transform (0) | 2022.06.05 |
[TIL-185] MyView 프로젝트 - JSX와 Javascript (0) | 2022.05.31 |
노마드코더 유튜브 클론코딩 챌린지(2회차) - 5주차(DAY29~DAY33) (0) | 2022.05.31 |
[TIL-184] 모던 자바스크립트 25장 클래스 (0) | 2022.05.27 |