모던 자바스크립트 Deep Dive (1)
📖 정리
- 이 글은 '모던 자바스크립트 Deep Dive'를 읽으면서 새롭게 알게된 내용을 정리하기 위해 쓴 글 입니다.
2장 자바스크립트란?
-
2015년에 공개된 ECMAScript 6에서 let/const 키워드, 화살표 함수, 클래스, 모듈 등과 같은 범용 프로그래밍 언어로서 갖춰야 할 기능들이 대거 도입되었다.
-
Node.js는 비동기 I/O를 지원하며 단일 스레드 이벤트 루프 기반으로 동작함으로써 요청처리 성능이 좋다.
- 그러면 이벤트 루프란 무엇일까?
- 자바스크립트와 이벤트 루프 글을 참고해서 확인해보았다.
- 자바스크립트는 이벤트 루프를 이용해서 비동기 방식으로 동시성을 지원한다.
- ECMAScript에는 이벤트 루프가 없다.
- 비동기 요청과 동시성에 대한 처리는 자바스크립트 엔진을 구동하는 환경 즉 브라우저나 Node.js가 담당한다.
- 출처
- 실제로 비동기 호출을 위해 사용하는 함수들은 자바스크립트 엔진이 아닌 Web API영역에 따로 정의되어 있다.
- 또한 이벤트 루프와 태스크 큐 같은 장치도 자바스크립트 엔진 외부에 구현되어 있다.
- 출처
- Node.js는 비동기 I/O를 지원하기 위해 libuv라이브러리를 사용하며, 이 libuv의 이벤트 루프를 통해 스케쥴되고 실행된다.
- 자바스크립트가 '단일 스레드'기반의 언어라는 말은 '자바스크립트 엔진이 단일 호출 스택을 사용한다'는 관점에서만 사실이다.
- 실제 자바스크립트가 구동되는 환경에서는 주로 여러개의 스레드가 사용되며, 이러한 구동 환경이 단일 호출 스택을 사용하는 자바스크립트 엔진과 상호 연동하기 위해 사용되는 장치가 '이벤트 루프'이다.
- 태스크 큐는 말 그대로 콜백 함수들이 대기하는 큐 형태의 배열이고, 이벤트 루프는 호출 스택이 비워질 때마다 큐에서 콜백 함수를 꺼내와서 실행하는 역할을 해준다.
- 비동기 요청과 동시성에 대한 처리는 자바스크립트 엔진을 구동하는 환경 즉 브라우저나 Node.js가 담당한다.
-
Node.js는 데이터를 실시간으로 처리하기 위해 I/O가 빈번하게 발생하는 SPA에 적합하다. 하지만 CPU 사용률이 높은 애플리케이션에는 권장하지 않는다.
-
ECMAScript는 자바스크립트 표준 사양인 ECMA-262를 말하며, 프로그래밍 언어의 값, 타입, 객체와 프로퍼티, 함수, 표준 빌트인 객체등 핵심 문법을 규정한다.
-
자바스크립트는 일반적으로 프로그래밍 언어로서 기본 뼈대를 이루는 ECMAScript와 브라우저가 별도 지원하는 클라이언트 사이드 Web API, 즉 DOM, BOM, Canvas, XMLHttpRequest, fetch, requestAnimationFrame, SVG, Web Storage, Web Component, Web Worker등을 아우르는 개념이다.
4장 변수
-
변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말한다.
-
메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름을 변수 이름이라 하고, 그 변수에 저장된 값을 변수 값이라고 한다.
-
변수 이름을 식별자라고도 한다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다.
-
식별자는 값이 저장되어 있는 메모리 주소와 매핑관계를 맺으며, 이 매핑 정보도 메모리에 저장되어야 한다.
-
식별자는 값이 아니라 메모리 주소를 기억하고 있다.
-
변수 선언이란 변수를 생성하는 것을 말한다. 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것이다.
-
자바스크립트 엔진은 변수 선언을 다음과 같은 2단계에 거쳐 수행한다.
- 선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화 한다.
-
var 키워드를 사용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행된다.
-
변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임이 아니라 그 이전 단계에 실행된다.
- 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평가과정을 거치면서 소스코드를 실행하기 위한 준비를 한다.
- 이 때 변수 선언을 포함한 모든 선언문(변수 선언문, 함수 선언문 등)을 소스코드에서 찾아내 먼저 실행한다.
- 이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것 처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라 한다.
-
변수 선언과 값의 할당의 실행 시점이 다르다. 변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.
- 변수에 값을 할당할 때는 이전 값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값을 새롭게 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 그곳에 할당값을 저장한다.
- 불필요한 값들은 가비지 콜렉터에 의해 메모리에서 자동 해제된다. 단 메모리에서 언제 해제될지는 예측할 수 없다.
5장 표현식과 문
-
값은 식(표현식)이 평가되어 생성된 결과를 말한다.
-
리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 말한다.
-
표현식은 값으로 평가될 수 있는 문이다. 즉 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다.
- 리터럴은 값으로 평가되기 때문에 리터럴도 표현식이다.
-
문은 프로그램을 구성하는 기본 단위이자 최소 실행 단위이다.
- 문은 여러 토큰으로 구성된다. 토큰이란 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본요소를 말한다.
- 문을 명령문이라고도 부른다. 즉, 문은 컴퓨터에게 내리는 명령이다. 문이 실행되면 명령이 실행되고 무슨 일인가가 일어나게 된다.
- 문은 선언문, 할당문, 조건문, 반복문 등으로 구분할 수 있다.
-
표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는 것이다.
6장 데이터 타입
-
자바스크립트의 모든 값은 데이터 타입을 갖는다. 자바스크립트(ES6)는 7개의 데이터 타입을 제공한다. 7개의 데이터 타입은 원시타입과 객체타입으로 분류할 수 있다.
-
원시 타입에는 숫자 타입, 문자열 타입, 불리언 타입, undefined 타입, null 타입, 심벌 타입이 있다.
- 숫자 타입
- ECMAScript 사양에 따르면 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따른다. 즉 모든 수를 실수로 처리하며, 정수를 표현하기 위한 데이터 타입이 별도로 존재하지 않는다.
- Infinity, -Infinity, NaN 같은 특별한 값도 표현할 수 있다.
- 문자열 타입
- 문자열은 원시 타입이며, 변경 불가능한 값이다. 이것은 문자열이 생성되면 그 문자열을 변경할 수 없다는 것을 의미한다.
- undefined 타입
- 참조한 변수가 선언 이후 값이 할당된 적 없는 변수라는 것을 알려준다.
- 변수를 초기화 할 때 사용하는 undefined가 유일하며, 개발자가 의도적으로 변수에 할당하는 것은 본래 취지에 어긋난다.
- null 타입
- 변수에 값이 없다는 것을 의도적인 명시할 때 사용한다.
- 변수에 null을 할당하는 것은 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미이다.
- 심벌 타입
- ES6에 추가된 타입으로 변경 불가능한 원시 타입의 값이다.
- 다른 값과 중복되지 않는 유일무이한 값을 의미하며, 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해서 사용한다.
- 숫자 타입
-
자바스크립트 엔진은 데이터 타입, 즉 값의 종류에 따라 정해진 크기의 메모리 공간을 확보한다. 즉 변수에 할당되는 값의 데이터 타입에 따라 확보해야 할 메모리 공간의 크기가 결정된다.
- ECMAScript 사양은 문자열과 숫자 타입 외에 데이터 타입의 크기를 명시적으로 규정하고 있지는 않다. 따라서 문자열과 숫자 타입을 제외하고 데이터 타입에 따라 확보되는 메모리 공간의 크기는 자바스크립트 엔진 제조사의 구현에 따라 다를 수 있다.
-
테이터 타입이 필요한 이유는 다음과 같다.
- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해
- 값을 참조할 때 한번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
-
자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론)된다. 그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다. 이러한 특징을 동적 타이핑이라 하며, 자바스크립트를 동적 타입 언어라고 한다.