먼저 HTML/CSS/JS 파일이 어떻게 브라우저를 통해 화면에 보여지는지 이해하는 과정이 필요하다.
브라우저 렌더링이란, HTML/CSS/Javascript 파일 등을 브라우저 화면에 그리는 과정을 말한다.
사용자가 브라우저에 사이트를 접속하면, 브라우저는 서버로부터 HTML/CSS/Javascript 등 필요한 리소스를 다운 받는다.
브라우저의 브라우저 엔진은 HTML 문서를 파싱해 DOM(Document Object Model, 문서 객체 모델)트리를, CSS파일을 파싱해 CSSOM 트리를 형성한다.
그 후 DOM트리와 CSSOM트리를 결합해 렌더 트리를 형성한다.
렌더트리를 기반으로 각 요소를 배치하는 레이아웃 단계와, 화면에 요소를 그리는 페인팅 과정까지 완료되면 렌더링이 종료되고, 사용자는 접속한 사이트의 화면을 볼 수 있다.
이때 중요한 점은, HTML 문서 파싱 중, CSS 요소 혹은 Script 요소가 있다면, 브라우저 엔진은 그 즉시 HTML 파싱을 멈추고, 해당 요소를 먼저 읽게 된다.
👉 따라서 HTML 문서 내에 stylesheet파일 혹은 script파일이 어디에 위치하는지에 따라 브라우저 렌더링 속도 등이 달라진다.
결론부터 말하자면, 브라우저의 페이지 로딩 속도를 높이기 위해서는
stylesheet(CSS)는
head
태그에,
script(Javascript)는body
태그 최하단에 위치하는 것이 좋다.
HTML 문서는 위에서부터 코드가 실행되기 때문에 head
요소가 다 실행된 후 → body
요소가 실행된다.
CSS는 화면의 요소를 배치하고 그리는 역할을 하기 때문에, 늦게 호출될 경우 사용자는 스타일이 적용되지 않은 화면을 만날 수 있다.
따라서 가장 먼저 실행되는 head
요소 안에 두는 것이 좋다.
앞서 보았다 싶이 HTML 문서는 head의 요소가 모두 실행되어야 body가 실행된다. 만약 Script 파일이 head 요소이고 용량이 크다면 body 요소의 실행이 늦어지게 되므로, 사용자는 모든 요소가 실행될 때까지 빈 화면에서 =기다리게 된다.
이는 사용자 경험(UX, User Experience)에도 좋지 않기 때문에, script파일은 body 태그의 최하단에 두어, 화면이 다 그려진 후에 호출하는 것이 좋다.
📝 NOTE
💡 브라우저
브라우저는 여러 엔진들로 구성되어 있는데, 대표적으로 브라우저 엔진, 렌더링(레이아웃)엔진, JS 엔진 등으로 구성된다.
💡브라우저 엔진
사용자가 어떤 액션을 하는 것부터(인터페이스) ~ 화면에 결과물을 그려 보여주기까지의 과정을 담당한다. 브라우저 엔진은 화면에 결과를 보여주는 렌더링 엔진과 JS 구문을 분석하는 JS 런타임 엔진(JS 엔진)을 포함한다.
💡렌더링 엔진
사용자가 요청한 HTML문서와 CSS를 파싱하여 화면에 그리는 역할을 한다.
※렌더링 엔진은 종종 브라우저 엔진에 포함된 개념으로 불리기도 하는데, JS 엔진은 브라우저 없이 독립적인 환경에서도 실행(ex, Node.js)될 수 있지만, 렌더링 엔진은 불가능하기 때문이다.
💡 파싱(parsing, 구문분석)하나의 프로그램을 런타임 환경(ex, 브라우저 내 자바스크립트 엔진)이 실제로 행할 수 있는 내부 포맷으로 분석하고 변환하는 것을 의미한다.
자연어 처리에서 택스트 문서를 분석해 문장 구조, 어휘, 문법, 의미 등을 이해하는 과정으로, 파싱 과정을 통해 검색 엔진이 검색 쿼리를 이해하거나 기계 번연 시스템이 언어를 해석하는데 사용된다.
asnyc
와 defer
어트리뷰트를 사용하면 HTML파싱과 자바스크립트 파일의 로드를 비동기적으로 동시에 진행할 수 있다.
<script src="/app.js" async></script>
asnyc
속성은 HTML 파싱이 끝나지 않았더라도, 스크립트 코드 로드가 완료되는 즉시, 스크립트가 실행된다.
따라서 실행 순서가 보장되지 않기 때문에, HTML 문서 내에 여러 script 파일이 있고, 해당 코드의 순서 보장이 필요한 경우엔 asnyc
속성이 적합하지 않다.
💡 또한 스크립트 코드 안에 DOM API를 통해 DOM을 조작하는 코드가 있다면, 실행 시점에 DOM트리가 제대로 구성되지 않아, 기능이 제대로 작동하지 않는 문제가 발생할 수 있다.
<script src="/app.js" defer></script>
defer
속성은 스크립트 파일의 로드가 완료되어도 HTML 파싱이 끝날 때까지 실행을 지연했다가, HTML 파싱이 모두 끝나면 스크립트를 실행한다.
따라서 asnyc
속성과 달리 순서를 보장할 수 있고, 기능 이슈 문제를 해결할 수 있다.
JavaScript는 동적 타입이 있는 동적 언어이다. 따라서 JavaScript의 변수는 ① 어떤 특정 타입과 연결되지 않으며, ② 모든 타입의 값으로 할당(또는 재할당)이 가능하다.
let foo = 42; // number
foo = "bar"; // string
foo = true; // boolean
원시 자료형 타입은 변경 불가능한 값 (immutable value)이며, pass-by-value(값에 의한 전달)로 이루어진다.
텍스트 데이터를 나타내며, 각 문자마다 인덱스를 가진다.(인덱스는 0부터 시작한다)
±(2의 1074승)
범위의 값을 나타내며, 해당 범위를 넘어가면 양수값은 +Infinity
, 음수값은 -Infinity
로 변환된다.
Number 타입은 소수점이 없는 정수 타입과 소수점을 갖는 부동 소수점(float)으로 나뉜다.
Number.MAX_VALUE
보다 큰 양수 값 : +Infinity
로 변환Number.MIN_VALUE
보다 작은 양수 값 : +0
으로 변환Number.MAX_VALUE
보다 작은 음수 값 : -Infinity
로 변환Number.MIN_VALUE
보다 큰 음수 값 : -0
으로 변환논리 요소를 나타내며, true와 false 두 가지의 값을 가진다.
🚨 false로 변환되는 값
0
,null
,NaN
,undefine
,빈문자열('')
은 falsy한 값으로 간주된다.
자바스크립트에서의 undefined
와 null
은 모두 값이 비어있음을 나타대는 데이터 타입으로, 다만 차이점이 존재한다.
undefined는 기본적으로 값이 할당되지 않은 변수의 값으로 사용되며, undefined타입의 변수의 값 또한 undefined이다.
따라서 자바스크립트에서 undefined는 타입인 동시에 값을 나타내는 데이터 타입이다.
let temp;
console.log(temp); // undefined (temp에 값이 할당되지 않았음)
temp = undefined;
console.log(temp); // undefined (temp에 값으로 undefined가 할당됨)
undefined
와 마찬가지로 값이 비어있음을 의미하지만, null
타입은 명시적으로 값이 비어있음을 나타낸다.
🚨 Null 타입 사용 시 주의점
null 타입의 데이터 사용시 주의할 점은 null값을 할당한 변수의 데이터 타입은 obejct이다.
따라서 null 타입 변수는typeof 연산자
로 데이터 타입을 확인할 수 없기 때문에 일치 연산자(===)를 사용해야 한다,
let temp = null;
console.log(typeof tmp); // object
console.log(tmp === null); // true
console.log(tmp); // null
Symbol은 ECMA Script 6에서 등장한 새로운 데이터 타입으로, 충돌 위험이 없는 고유한 프로퍼티를 만들기 위한 데이터 타입이다.
let tmp = Symbol('tmp');
console.log(typeof tmp); // symbol
console.log(tmp === Symbol('tmp')); // false : 고유한 값으로 같지 않다.
javascript에서는 기본 데이터 타입(원시 자료형)을 제외한 모든 값은 객체로 취급되며, Property와 Method를 포함할 수 있는 독립적 주체이다.
객체는 참조에 의한 전달 (pass-by-reference)방식으로 전달된다.
따라서 객체 뿐만 아니라, 배열이나 함수 등도 모두 객체로 표현된다.
객체는 중괄호{}
로 표현할 수 있으며, key-value
한쌍의 객체 데이터인 속성(property)을 가진다.
let obj = {
name: 'John Doe',
age: 30,
passed: true,
getInfo: function () {
return this.name + ', ' + this.age;
},
};
console.log(typeof obj); // object
언뜻보면 비슷해보이는 4가지 데이터 타입의 차이점을 알아보자.
null
은 객체 형태의 빈 값으로, 값이 없는 것을 의도적으로 명시하기 위해 사용한다.
let name = null;
console.log(name) // null
console.log(typeof name) //object
undefined는 변수를 선언하고 값을 할당하기 이전의 값으로, 변수에 값을 할당하지 않은 상태를 말한다.
변수는 변수 선언 - 변수 초기화 - 변수 할당 3단계를 거쳐 생성되는데, 2번째 단계에서 자바스크립트 엔진이 변수를 초기화할 때 undefined를 사용한다.
let name;
console.log(name); //undefined
console.log(typeof name); //undefined
접근 가능한 스코프 내에 변수의 선언조차 하지 않은 상태로, undefined 타입을 갖는다.
console.log(name); //ReferenceError: name is not defined
console.log(typeof name); //undefined
표현할 수 없는 수치형 결과를 나타내는 타입으로, 해당 값이 유효한 숫자가 아님을 의미한다.
주의할 점은, NaN의 데이터 타입은 Number타입이지만, 컴퓨터로는 표현할 수 없는 숫자값을 의미한다.
let age = NaN;
console.log(age); //NaN
Console.log(typeof age); // number
console.log(undefined == null); //true
console.log(undefined === null); //false
동등 연산자는 피연산자를 비교할 때, JavaScript 엔진에 의해 암묵적인 타입 변환이 먼저 이뤄진다.
따라서 좌항과 우항의 데이터 타입이 다르더라도 값이 같다면 true를 반환한다.
let name = null;
console.log(typeof name) //object
let name;
console.log(typeof name); //undefined
따라서 null
(type of object)과 undefined
(type of undefined)의 데이터 타입은 다르지만, 자동형변환을 거쳐 값을 비교하면, 두 타입 모두 값이 없기 때문에 동등 연산자는 일치한다고 판단하여 true를 반환한다.
🚨
null
과undefined
의 데이터 타입 및 값
데이터 타입 값 null
object false undefined
undefined false
일치 연산자는 피연산자의 데이터 타입과 값이 모두 같을 경우에 true를 반환한다.
null
과 undefined
의 데이터 타입은 다르기 때문에 일치 연산자는 false를 반환한다.
자바스크립트는 변수 선언 시, 일반적으로 카멜 표기법(CamelCase)를 따른다.
※ CamelCase외에도 PascalCase, snake_case, kebab-case 등 다양한 표기법(naming convention)이 있다.
※ 참고문서