모던 자바스크립트 Deep Dive
모던 자바스크립트 Deep Dive 에 대한 개인적인 정리글입니다.
1. 프로그래밍
요구사항의 집합을 분석하여 적절한 자료구조와 함수의 집합으로 변환한 후, 그 흐름을 제어 하는 것.
1-1. 프로그래밍이란?
- 컴퓨터에게 어떻게 실행할 것인 요청하는 커뮤케이션의 일종으로 컴퓨터가 이해하고 실행할 수 있을 정도로 정확하고 상세하게 요구사항을 설명하는 작업
컴퓨터가 이해하도록 설명하기 위해서는 컴퓨터의 입장에서 문제를 봐야하며 이 때 문제 해결 능력과 컴퓨팅 사고가 필요하다.
사람의 경우 ‘조용히 말하자’ 라는 말을 인지할 수 있지만 컴퓨터의 경우는 이를 명확히 수치화하여 데시벨을 어디까지 낮춰야 하는지 입력해야 되는 것과 비슷하다.
1-2. 프로그래밍 언어
컴퓨터는 기계어를 이해할 수 있으나 사람이 직접 기계어로 명령을 전달하는 것은 어려운 일이므로 약속된 구문으로 구성된 프로그래밍 언어를 사용하여 작성된 문장을 컴파일러 혹은 인터프리터와 같은 번역기를 사용하여 기계어로 변환하여 전달한다.
1-3. 구문과 의미
한국어, 영어 등의 언어를 사용할 때는 문법에 맞게 의미를 가지게 사용하는 것 처럼 프로그래밍 언어도 마찬가지이다.
2. 자바스크립트란?
2-1. 자바스크립트 탄생
- 1995년 넷스케이프 커뮤니케이션즈에서 브랜던 아이크가 개발
2-2. 자바스크립트의 표준화
버전 | 년도 | 특징 |
---|---|---|
자바스크립트 | 1995 | 탄생 |
JScript | 1996 | MS에서 개발 완전호환X - 크로스 브라우징 이슈 |
- | 1996 | 자바스크립트 ECMA international 표준화 요청 |
ES1 | 1997 | 초판 |
ES2 | 1998 | ISO/IEC 16262 국제 표준과 동일한 규격 적용 |
ES3 | 1999 | 정규표현식, try catch |
ES5 | 2009 | JSON, strict mode, 접근자 프로퍼티 ... |
ES6(ECMAscrpit2015) | 2015 | let/const, 클래스, 화살표 함수, 프로미스 ... |
ES7(ECMAscrpit2016) | 2016 | ** 지수 연산자, includes |
ES8(ECMAscrpit2017) | 2017 | async/await, Object 정적 메소드 |
ES9(ECMAscrpit2018) | 2018 | finally, for await of |
ES10(ECMAscrpit2019) | 2019 | fromEntires, flat |
ES11(ECMAscrpit2020) | 2020 | matchAll, BigInt, ??, ?. |
2-3. 자바스크립트 성장의 역사
- 초창기 HTML, CSS 단순 렌더링
- 1999년 Ajax
- 2006년 Jquery
- 2008년 V8 자바스크립트 엔진
- 2009년 라이언 달의 Node.js
- SPA 프레임워크
2-4. 자바스크립트와 ECMAScript
- ECMAScript: 자바스크립트의 표준 사양인 ECMA-262를 말하며 핵심 문법을 규정
- 자바스크립트: Core를 이루는 ECMAScript 와 WEB API(W3C에서 관리) 를 아우르는 개념
2-5. 자바스크립트 특징
- 웹 브라우저에서 동작하는 유일한 프로그래밍 언어
- 인터프리터 언어
- 멀티 패러다임 프로그래밍 언어
- 프로토타입 기반의 객체지향 언어
3. 자바스크립트 개발 환경과 실행 방법
3-1. 자바스크립트 실행 환경
자바스크립트 엔진이 있는 환경(브라우저, Node.js)에서 실행할 수 있다. 하지만 환경에 따라 용도와 기능에 차이가 있을 수 있다.
3-2~4. 웹브라우저, Node.js, VSCode
생략
4. 변수
4-1. 변수란 무엇인가? 왜 필요한가?
하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙이는 이름.
값의 위치를 가리키는 상징적인 이름.
- 변수이름: 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름
- 변수 값: 변수에 저장된 값
- 할당: 변수에 값을 저장하는 것
- 참조: 변수에 저장된 값을 읽어 들이는 것
4-2. 식별자
변수이름을 식별자라고도 하며 값이 아닌 메모리 주소를 기억하고 있다.
메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름을 식별자라 하며, 네이밍 규칙을 준수해야 한다.
선언에 의해 자바스크립트 엔진에 식별자의 존재를 알림.
4-3. 변수 선언
변수를 사용하기 위해서는 let
, const
, var
키워드를 사용한 선언이 필요하다.
본래 var 밖에 없었으나 var 의 단점을 보완하기 위해 ES6 부터 let / const 키워드가 추가되었다.
- var: 함수레벨 스코프
- let: 블록레벨 스코프
- const: 블록레벨 스코프, 값 변경 불가능
변수 선언은 2단계에 거쳐 수행
- 선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알림.
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined 를 할당해 초기화.
💿 변수 이름은 어디에 등록되는가?
변수 이름과 변수 값은 실행 컨텍스트 내에 키/값 형식인 객체로 등록되어 관리된다.
4-4. 변수 선언의 실행 시점과 변수 호이스팅
console.log(score); // undefined
var score;
위의 예제는 score
선언 전에 해당 식별자를 호출하여 에러가 발생할 것 같지만 발생하지 않는다.
변수(식별자 또한 마차가지이다.) 선언이 런타임이 아니라 그 이전 단계(소스코드 평가 과정)에서 먼저 실행되기 때문이다. 이렇게 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 것을 변수 호이스팅이라고 한다.
4-5. 값의 할당
값의 할당은 소스코드가 순차적으로 실행되는 시점 런타임에 실행된다.
console.log(score); // undefined
score = 80;
var score;
console.log(score); // 80
4-6. 값의 재할당
값이 할당되어 있는 변수에게 새로운 값을 다시 할당하는 것. 재할당을 할 수 없다면 상수 라고 한다.
재할당의 경우 메모리의 들어있는 값을 교체하는 것이 아니라 새로운 메모리 공간을 확보하고 해당 메모리에 새로운 값을 저장한다.
💿 매니지드 언어
재할당을 하여 발생하는 사용하지 않는 값들을 저장하고 있는 메모리는 자바스크립트에 내장된 가비지콜렉터에 의해 해제되는데 이와 같이 메모리 관리를 개발자가 직접 하지 않는 것을 매니지드 언어 반대의 경우 언매니지드 언어라고 한다.
4-7 식별자 네이밍 규칙
- 특수문자를 제외한 문자, 숫자,
_
,$
를 포함할 수 있다. - 숫자로 시작할 수 없다.
- 예약어를 사용할 수 없다.
가독성을 위한 다양한 네이밍 컨벤션이 있다.
5. 표현식과 문
5-1. 값
10 + 20;
- 식이 평가되어 생성된 결과, 위의 예제는
식
이고 결과인30
이 값이다.
5-2. 리터럴
- 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법
5-3. 표현식
- 값으로 평가될 수 있는 문
5-4. 문
선언문, 할당문, 조건문, 반복문 …
- 프로그램을 구성하는 기본 단위이자 최소 실행 단위
- 여러 토큰으로 구성되어 있으며, 토큰은 문법적 의미를 가지며 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미
5-5. 세미콜론과 세미콜론 자동 삽입 기능
문의 종료를 나타내며 중괄호로 묶은 코드 블록 뒤에는 붙이지 않는다. 이는 코드 블록은 언제나 문의 종료를 의미하는 자체 종결성을 가지기 때문이다.
자동으로 붙여주는 기능(ASI)이 있어 안 붙여도 되기는 하지만 예측대로 동작하지 않는 부분이 있으며 대부분의 경우 사용을 권장하고 있다.
5-6 표현식인 문과 표현식이 아닌 문
두 가지를 구별하는 명료한 방법은 변수에 할당해 보는 것이다. 표현식인 문은 값으로 평가되므로 할당이 가능하지만 아닌 경우는 할당 할 수 없다.
let x;
x = 100;
let foo = let x; // SyntaxError
6. 데이터 타입
값의 종류를 지칭하며, 자바스크립트의 모든 값은 데이터 타입을 가진다. 자바스크립트에서는 7개의 데이터 타입이 있고 6개의 원시 타입과 1개의 객체 타입으로 분류된다.
구분 | 데이터 타입 | 설명 |
---|---|---|
원시 타입 | Number | 숫자(정수, 실수 구분 없음) |
원시 타입 | string | 문자열 |
원시 타입 | boolean | 논리적 참, 거짓 |
원시 타입 | undefined | 초기화 안된 변수에 암묵적으로 할당되는 값 |
원시 타입 | null | 값이 없음을 명시 |
원시 타입 | Symbol | ES6에서 추가 |
객체 타입 | Object | 객체, 함수, 배열 |
6-1. 숫자 타입
ECMAScript 사양에 따르면 숫자 타입의 값은 배정밀도 64비트 부동소수점 형태를 따른다.
정수와 실수 구분 없기에 아래와 같은 코드가 동작하며 다음의 특별한 값 3가지를 표현할 수 있다. 🚨 대소문자 주의필요
Infinity, -Infinity, NaN
const binary = '0b01000001;
const octal = '0o101;
const hex = '0x41';
console.log(binary);
console.log(octal);
console.log(hex);
console.log(hex === octal);
console.log(hex === binary);
console.log(1 === 1.0);
6-2. 문자열 타입
0개 이상의 16비트 유니코드 문자의 집합, '
, "
, ` 으로 감싸서 표기 가능합니다.
6-3. 템플릿 리터럴
멀티라인 문자열, 표현식 삽입, 태그드 템플릿 등의 문자열 처리기능을 사용할 수 있으며, 런타임에 일반 문자열로 변환되어 처리된다.
6-4. 불리언 타입
true
, false
6-5. undefiend 타입
암묵적으로 변수가 초기화 될 때 할당하는 값으로 undefined
가 나오는 것은 선언이후 값이 할당되지 않았음을 알 수 있게 해준다.
개발자가 undefined
값을 사용하는 것은 본래 용도와 맞지 않으며 값이 비었음을 나타내고 싶을 경우는 null
을 할당하자.
💿 선언과 정의
컴파일러에게 존재를 알리는 것이 선언, 컴파일러가 변수를 생성하여 식별자와 메모리 주소를 연결할 경우 정의로 구분하나 자바스크립트는 선언과 동시에 암묵적으로 정의를 하기 때문에 좀 모호한 부분이 있다.
하지만 ECMAScript 사양에서 변수는 ‘선언한다’, 함수는 ‘정의한다’ 라고 표현하고 있다.
6-6. null 타입
변수에 값이 없음을 의도적으로 명시할 때 사용되며, 할당되어 있던 값에 대한 참조를 명시적으로 제거함을 의미한다.
함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null
을 반환하기도 한다.
const element = document.getElementById("notExistId"); // 있지 않는 요소를 선택
console.log(element); // null
6-7. 심벌 타입
다른 값과 중복되지 않는 유니크 값이며 다른 원시값과 다르게 리터럴이 아닌 Symbol 함수를 호출하여 생성한다.
값은 키를 사용하여 생성하더라도 해당 값은 다르며 값을 확인할 수 없다.
const id1 = Symbol("id");
const id2 = Symbol("id");
console.log(id1); // Symbol(id)
console.log(id2); // Symbol(id)
console.log(id1 === id2); // false
6-8. 객체 타입
자바스크릡트를 이루고 있는 거의 모든 것이 객체. 뒤에서 다룬다.
6-9. 데이터 타입의 필요성
- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해
- 값을 참조할 때 한 번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
💿 데이터 타입에 따른 메모리공간의 크기, 심벌 테이블
ECMAScript 사양에서는 문자열과 숫자 타입 외에 데이터 타입의 크기를 명시적으로 규정하고 있지 않아 엔진의 제조사의 구현에 따라 다를 수 있다.
컴파일러 or 인터프리터는 심벌 테이블이라 불리는 자료 구조를 통해 식별자를 키로 바인딩된 값의 메모리 주소, 데이터 타입, 스코프 등을 관리한다.
6-10 동적 타이핑
변수를 선언할 때 데이터 타입을 사전에 선언하는 경우 정적 타입 언어라고 하며 이는 컴파일 시점에 타입 체크를 수행한다.
자바스크립트는 변수 선언 뒤 할당 되는 값의 타입에 따라 변경된다. 이를 동적 타이핑, 동적 타입 언어라고 한다.
💿
null
의typeof
의 값이 왜object
??
아래의 예제에서 보면 null을 할당한 뒤 타입이 object로 출력됨을 확인할 수 있는데 이는 자바스크립트 초기 버전의 버그라고 한다. 참조문서
이후 수정하려 하였으나 많은 곳에서 사용되고 하나의 자바스크립트 이념 안에서 실현이 불가능 하다는 이유로 거절되었다. 참조문서
let foo;
console.log(typeof foo); // undefined
foo = 3;
console.log(typeof foo); // number
foo = true;
console.log(typeof foo); // boolean
foo = null;
console.log(typeof foo); // object
foo = () => {};
console.log(typeof foo); // function
foo = [];
console.log(typeof foo); // object
동적 타입 언어는 유연성은 높지만 신뢰성이 떨어지며 안정적인 프로그램을 만들기 위해서는 변수를 사용할 때 주의해야 한다.
- 변수는 곡 필요한 경우에 한해 제한적으로 사용
- 변수의 유효 범위를 최대한 좁게 만들어 부작용을 억제
- 전역 변수는 최대한 사용하지 않는다.
- 변수보다는 상수를 사용해 값의 변경을 억제
- 변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍한다.
🔥 추가학습 필요
- 프로토타입 기반 프로그래밍
- 객체의 메모리 할당: 11장 참조
- var 의 단점: 변수 중복 선언, 함수 레벨의 스코프과 호이스팅, 상수 표현 불가
- 실행 콘텍스트: 23장 참조
- 헝가리안 케이스: 앞에 자료형을 붙이는 스타일, 현재는 지양되고 있다.
- 배정밀도 64비트 부동소수점: console.log(0.1 + 0.2); console.log(0.1 + 0.2 === 0.3);
- 태그드 템플릿: (text, values) => {}
- 선언 정의: ?
개인이 참고하고자 작성한 글이며, 잘못된 정보가 있을 수 있습니다. 잘못된 정보는 메일로 보내주시면 감사하겠습니다. 🙏