- html
- AWS
- programmers
- Algorithm
- nuxt
- github
- amplify
- 프로그래머스
- SSH
- IntersectionObserverAPI
- 캐시무효화
- 백준
- 자바스크립트
- javascirpt
- Prefetch
- composition api
- fetchpriority
- preload
- JavaScript
- eslint
- CF
- S3
- TypeScript
- 모던자바스크립트DeepDive
우주선
모던 자바스크립트 Deep Dive ― (9) 본문
모던 자바스크립트 Deep Dive ― (9)
36장 디스트럭처링 할당
디스트럭처링 할당(구조 분해 할당)은 구조화된 배열과 같은 이터러블 또는 객체를 비구조화하여 1개 이상의 변수에 개별적으로 할당하는 것을 말한다.
36.1 배열 디스트럭처링 할당
배열 디스트럭처링 할당의 대상은 이터러블이어야 하며, 할당 기준은 배열의 인덱스다.
할당 연산자 왼쪽에 값을 할당받을 변수를 선언해야 한다. 이때 변수를 배열 리터럴 형태로 선언한다.
이때 변수의 개수와 이터러블의 요소 개수가 반드시 일치할 필요는 없다.
const arr = [1,2,3]
const [one, two]= arr
console.log(one, two) // 1,2
36.2 객체 디스트럭처링 할당
객체의 각 프로퍼티를 객체로부터 추출하여 1개 이상의 변수에 할당한다.
할당의 대상(할당문의 우변)은 객체여야 하며, 할당 기준은 프로퍼티 키다. 할당 연산자 왼쪽에 프로퍼티 값을 할당받을 변수를 선언한다.
할당문의 우변에 객체가 아닌 표현식을 할당하면 에러가 발생한다.
객체의 프로퍼티 키와 다른 이름으로 프로퍼티 값을 할당할 수 있다. 함수의 매개변수에도 사용할 수 있다.
const user = {firstName:'nana', lastName:'kim'}
const {firstName: fn , lastName } = user
console.log(fn, lastName) // nana Kim
function printName({firstName, lastName}){console.log(firstName, lastName)}
printName(user) // nana kim
배열의 요소가 객체인 경우 배열 디스트럭처링 할당과 객체 디스트럭처링 할당을 혼용할 수 있다.
중첩 객체의 경우에도 디스트럭처링 할당을 사용할 수 있다.
객체 디스트럭처링 할당을 위한 변수에 Rest 프로퍼티 ... 을 사용할 수 있다.(맨 마지막에 위치해야 한다)
const todos = [{id:1, content:'HTML'},{id:2, content:'CSS'},{id:3, content:'JS'}]
const [, {id}] = todos
console.log(id) // 2
const user = {name:'nana', address:{city:'seoul', zipcode:'12345'}}
const { address:{city} } = user
console.log(city) // seoul
const {x, ...rest} = { x:1, y:2, z:3 }
console.log(x, rest) // 1, {y:2, z:3}
37장 Set 과 Map
37.1 Set
Set 객체는 중복되지 않는 유일한 값들의 집합이다. Set 객체는 Set 생성자 함수로 이터러블을 인수로 전달받아 생성한다.
배열과 유사하지만 다르다. 이터러블이기 떄문에 for...of 문으로 순회할 수 있다. 스프레드 문법, 배열 디스트럭처링 가능하다.
1) 동일한 값을 중복하여 포함할 수 없다. 이 특성으로 배열에서 중복된 요소를 제거할 수 있다.
2) 요소 순서에 의미가 없다.
3) 인덱스로 요소에 접근할 수 없다.
- Set.prototype.size : 요소의 개수를 확인한다. 접근자 프로퍼티로서 개수 확인만 가능하고 개수를 변경할 수는 없다.
- Set.prototype.add : 요소를 추가하는 메서드. 연속적으로 호출할 수 있다. Set객체에 중복된 요소의 추가는 허용되지 않으며 무시된다. 자바스크립트의 모든 값을 요소로 저장할 수 있다.
- Set.prototype.has : 특정 요소가 존재하는지 확인한다. 불리언 값을 반환한다.
- Set.prototoype.delete : 요소값을 인수로 전달하여 특정 요소를 삭제한다. 존재하지 않는 요소일 시 무시된다. 삭제 성공 여부를 나타내는 불리언 값을 반환하며, 연속적으로 호출할 수 없다.
- Set.prototype.clear : 모든 요소를 일괄 삭제한다. undefined 를 반환한다.
- Set.prototype.forEach : 객체의 요소를 순회한다. 객체를 순회하는 순서는 요소가 추가된 순서다.
Set 객체는 수학적 집합을 구현하기 위한 자료구조다.
const setA = new Set([1,2,3,4])
const setB = new Set([2,4,5])
//교집합
Set.prototype.intersection = function(set){
return new Set([...this].filter(v=>set.has(v)))
}
console.log(setA.intersection(setB)) // [2,4]
//합집합
Set.prototype.union = function(set){
return new Set([...this,...set])
}
console.log(setA.union(setB)) // [1,2,3,4,5]
//차집합
Set.prototupe.difference = function(set){
return new Set([...this].filter(v=>!set.has(v)))
}
console.log(setA.difference(setB)) // [1,3]
37.2 Map
Map 객체는 키와 값의 쌍으로 이루어진컬렉션이다. Map 객체는 Map 생성자 함수로 이터러블을 인수로 전달받아 Map 객체를 생성한다. 인수로 전달되는 이터러블 또한 키-값 쌍으로 이루어져 있어야 한다. 키로 사용할 수 있는 값은 객체를 포함한 모든 값이다. 중복된 키를 갖는 요소가 존재할 수 없다. 이터러블이기 떄문에 for...of 문으로 순회할 수 있다. 스프레드 문법, 배열 디스트럭처링 가능하다.
- Map.prototype.size : 요소 개수를 확인하는 접근자 프로퍼티로서 getter함수만 존재한다.
- Map.prototype.set : 객체에 요소를 추가한다. 연속적으로 호출할 수 있으며, 중복되면 덮어씌워진다. NaN과 NaN이 같다고 평가하여 중복 추가를 허용하지 않는다.
- Map.prototype.get : 특정 요소를 취득한다.
- Map.prototype.has : 특정 요소가 존재하는지 확인한다. 불리언 값을 반환한다.
- Map.prototype.delete : Map 객체의 요소를 삭제한다. 존재하지 않는 키라면 무시되며, 연속적 호출이 불가능하다.
- Map.prototype.clear : 요소를 일괄 삭제한다.
- Map.prototype.forEach : 요소를 순회한다.
- Map.prototoype.keys , Map.prototoype.values , Map.prototoype.entries
38장 브라우저의 랜더링 과정
자바스크립트가 가장 많이 사용되는 분야는 역시 웹 브라우저 환경에서 동작하는 클라이언트 사이드다. 웹 애플리케이션의 클라이언트 사이드 자바스크립트는 브라우저에서 HTML, CSS와 함께 실행된다. 이를 위해 브라우저가 HTML,CSS, JS를 어떻게 파싱하여 랜더링하는가?
- 파싱 : 텍스트 문서의 문자열을 토큰으로 분해하고, 토큰에 문법적 의미와 구조를 반영하여 트리 구조의 자료구조인 파스 트리를 생성하는 과정.
- 랜더링 : 문서를 파싱하여 브라우저에 시각적으로 출력하는 것
브라우저는 다음과 같은 과정을 거쳐 랜더링을 수행한다.
1) 브라우저는 HTML, CSS, JS, 이미지, 폰트 등 랜더링에 필요한 리소스를 요청하고 서버로부터 응답을 받아온다.
2) 브라우저의 랜더링 엔진은 서버로부터 응답된 HTML을 파싱하여 DOM을 생성하고, CSS를 파싱하여 CSSON을 생성하고 이들을 결합하여 랜더 트리를 생성한다.
3) 브라우저의 자바스크립트 엔진은 자바스크립트를 파싱하여 AST을 생성한다. 만약 DOM API를 통해 DOM이나 CSSOM을 변경한다면 다시 렌더 트리로 결합된다.
4) 랜더 트리를 기반으로 HTMl요소를 페인팅한다.
38.1 요청과 응답
브라우저의 핵심 기능은 필요한 리소스를 서버에 요청하고 응답 받아 브라우저에 시각적으로 랜더링하는 것이다.
브라우저 주소창에 URL을 입력하고 전송하면 URL의 호스트 이름이 DNS를 통해 IP주소로 변환되고 이 IP주소를 갖는 서버에게 요청을 전송한다.
HTML을 파싱하는 도중에 외부 리소스를 로드하는 태그 (CSS파일을 로드하는 link , 이미지 파일을 로드하는 img, script ... ) 를 만나면 HTML 파싱을 일시 중단하고 해당 리소스 파일을 서버로 요청한다.
38.2 HTTP1.1 과 HTTP2.0
HTTP는 웹에서 브라우저와 서버가 통신하기 위한 프로토콜(규약)이다.
HTTP/1.1 은 기본적으로 커넥션당 하나의 요청과 응답만 처리한다. 다중 요청/응답이 불가능하다.
HTTP/2는 커넥션당 여러 개의 요청과 응답이 가능하다.
38.3 HTML파싱과 DOM생성 & 38.4 CSS 파싱과 CSSOM 생성
브라우저의 요청에 의해 응답된 HTML문서는 문자열로 이루어진 텍스트이다. 브라우저의 렌더링 엔진은 이 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성한다. DOM은 HTML문서를 파싱한 결과물이다.
1) 브라우저는 HTML문서를 바이트(2진수)형태로 응답받는다. 이를 문자열로 변환한다.
2) 문자열로 변환된 문서를 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해한다.
3) 각 토큰들을 객체로 변환하여 노드를 생성한다.
4) 노드들을 트리 자료구조로 구성한다 (DOM)
CSS는 HTML과 동일한 파싱 과정 (바이트>문자>토큰>노드>CSSOM)을 거치며 CSSOM을 생성한다.
자바스크립트 엔진은 자바스크립트를 해석하여 AST(추상적 구문 트리)를 생성한다.
38.5 렌더 트리 생성
DOM과 CSSOM은 렌더링을 위해 렌더 트리로 결합된다. 렌더 트리는 브라우저 화면에 렌더링되는 노드만으로 구성된다.
렌더 트리는 브라우저 화면에 픽셀을 렌더링하는 레이아웃 계산 및 페인팅 처리에 입력된다.
38.7 리플로우와 리페인트
만약 자바스크립트에 의한 노드 추가 또는 삭제/브라우저 창의 리사이징/스타일 변경 등을 하게 된다면 레이아웃 계산, 페인팅이 재차 실행된다(리랜더링)
DOM이나 CSSOM이 변경되면 변경된 DOM이나 CSSOM은 다시 렌더 트리로 결합되고 변경된 렌더 트리를 기반으로 레이아웃과 페인팅 과정을 거쳐 화면에 다시 렌더링한다. 이를 리플로우, 리페인트라고 한다.
리플로우 : 레이아웃 계산을 다시 함 / 리페인트 : 재결합된 랜더 트리를 기반으로 다시 페인트를 함
리플로우와 리페인트는 반드시 순차적인 것이 아니다. 레이아웃에 영향이 없으면 리플로우 없이 리페인트만 실행된다.
38.8 자바스크립트 파싱에 의한 HTML 파싱 중단
브라우저는 동기적으로 HTML,CSS,JS를 파싱하므로 script태그의 위치에 따라 HTM파싱이 블로킹되어 DOM생성이 지연될 수 있다는 것을 의미한다. JS로 DOM API를 쓰기 전에 DOM이 페인팅되지 않았다던가 하는 문제를 회피하기 위해 body 요소의 아래에 JS를 위치시키는 것이 좋다.
자바스크립트 파싱에 의해 DOM생성이 중단되는 문제를 해결하기 위해 HTML5부터 외부 스크립트를 가져오는 script 태그에 async와 defer 어트리뷰트를 제공한다. 인라인 scirpt는 지원하지 않는다.
- async : HTML파싱과 JS파일의 로드가 비동기적으로 동시에 진행된다. JS가 실행은 JS파일의 로드 완료 후 진행되며 이때 HTML파싱이 중단된다.
- defer : 외부 JS의 로드가 비동기적으로 동시에 진행한다. DOM 생성이 완료된 직후에 JS 파싱과 실행을 진행한다.
'JavaScript' 카테고리의 다른 글
모던 자바스크립트 Deep Dive ― (10) (0) | 2022.12.23 |
---|---|
eslint --fix found some errors ( Error: unreachable ) (0) | 2022.10.31 |
모던 자바스크립트 Deep Dive ― (8) (1) | 2022.10.31 |
모던 자바스크립트 Deep Dive ― (7) (0) | 2022.10.28 |
모던 자바스크립트 Deep Dive ― (6) (0) | 2022.10.21 |