자바스크립트 딥다이브 1
자바스크립트의 표준화
- 2015년에 공개된 ECMAScript 6(ECMAScript 2015, ES6)는 let/const 키워드, 화살표 함수 클래스, 모듈 등과 같이 범용 프로그래밍 언어로서 갖춰야 할 기능들을 대거 도입하는 큰 변화를 주었다.
자바스크립트 성장의 역사
ES5 (2009)
HTML5와 함께 출현한 표준안, JSON, strict mode, 접근자 프로퍼티, 프로퍼티 어트리뷰트 제어, 향상된 배열 조작 기능 (forEach, map, filter, reduce, some, every)
ES6 (ECMAScript 2015)
let, const, 클래스, 화살표 함수, 템플릿 리터럴, 디스트럭처링 할당, 스프레드 문법, rest 파라미터, 심벌, 프로미스, Map/Set, 이터러블, for...of, 제너레이터, 프록시, 모듈, import/export
Ajax
- Ajax는 1999년 자바스크립트를 이용해 서버와 브라우저가 비동기 asynchronous 방식으로 데이터를 교환할 수 있는 통신기능인 Ajax Asynchronous JavaScript and XML가 XMLHttpRequest 라는 이름으로 등장했다.
jQuery
- V8 자바스크립트 엔진의 등장으로 자바스크립트는 데스크톱 애플리케이션과 유사한 사용자 경험을 제공할 수 있는 웹 애플리케이션 프로그래밍 언어로 정착했다.
NodeJS
- Node.js는 비동기 I/O를 지원하며 단일 스레드 이벤트 루프 기반으로 동작함으로써 요청 처리 성능이 좋다.
- 데이터를 실시간으로 처리하기 위해 I/O가 빈번하게 발생하는 SPA에 적합하다. 하지만 CPU 사용률이 높은 애플리케이션에는 권장하지 않는다.
자바스크립트의 특징
- 자바스크립트는 HTML, CSS와 함께 웹을 구성하는 요소 중 하나로 웹 브라우저에서 동작하는 프로그래밍 언어이다.
- 개발자가 별도의 컴파일 작업을 수행하지 않는 인터프리터 언어다.
- 인터프리터는 소스코드를 즉시 실행하고 컴파일러는 빠르게 동작하는 머신 코드를 생성하고 최적화한다. 이를 통해 컴파일 단계에서 추가적인 시간이 필요함에도 더욱 빠르게 코드를 실행할 수 있다.
인터프리터 언어 vs 컴파일러 언어
컴파일러 언어 | 인터프리터 언어 |
---|---|
코드가 실행되기 전 단계인 컴파일 타임에 소스코드 전체를 한번에 머신 코드로 변환 후 실행한다. | 코드가 실행되는 단계인 런타임에 문 단위로 한 줄씩 중간코드인 바이트코드로 변환 후 실행한다. |
실행 파일을 생성한다. | 실행 파일을 생성하지 않는다. |
컴파일 단계와 실행 단계가 분리되어 있다. 명시적인 컴파일 단계를 거치고, 명시적으로 실행 파일을 실행한다. | 인터프리트 단계와 실행단계가 분리되어 있지 않다. 인터프리터는 한 줄씩 바이트코드로 변환하고 즉시 실행한다. |
실행에 앞서 컴파일은 단 한번 수행된다. | 코드가 실행될 때마다 인터프리트 과정이 반복 수행된다. |
컴파일과 실행 단계가 분리되어 있으므로 코드 실행 속도가 빠르다. | 인터프리트 단계와 실행 단계가 분리되어 있지 않고 반복 수행되므로 코드 실행 속도가 비교적 느리다. |
- 자바스크립트는 런타임에 컴파일되며 실행 파일이 생성되지 않고 인터프리터의 도움 없이 실행할 수 없기 때문에 컴파일 언어라고 할 수는 없다.
- 자바스크립트는 명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어다.
- 강력한 객체지향 프로그래밍 능력을 지니고 있고 클래스, 상속, 정보 은닉을 위한 키워드가 없어 객체지향 언어가 아니라고 오해하는 경우도 있지만 클래스 기반 객체지향 언어보다 효율적이면서 강력한 프로토타입 기반의 객체지향 언어이다.
ES6 브라우저 지원 현황
- 인터넷 익스플로러나 구형 브라우저는 대부분 ES6를 지원하지 않는다. 만약 고려해야 하는 상황이라면 바벨과 같은 트랜스파일러를 사용해 ES6 이상의 사양으로 구현한 소스코드를 ES5 이하의 사양으로 다운그레이드 해야 한다.
자바스크립트 실행 환경
- 브라우저는 HTML, CSS, 자바스크립트를 실행해 웹페이지를 브라우저 화면에 렌더링하는 것이 주된 목적이다.
- ECMAScript와 DOM, BOM, Canvas, XMLHttpRequest, fetch, requestAnimationFrame, SVG, Web Storage, Web Component, Web Worker 같은 클라이언트 사이드 Web API를 지원한다.
- Node.js는 브라우저 외부에서 자바스크립트 실행 환경을 제공하는 것이 주된 목적이다.
- DOM API를 제공하지 않는다. 브라우저 외부 환경에서는 HTML 요소를 파싱해서 객체화한 DOM을 직접 다룰 필요가 없기 때문이다.
변수란 무엇이고 왜 필요할까?
- 사람은 계산과 기억을 모두 두뇌에서 하지만, 컴퓨터는 연산과 기억을 수행하는 부품이 나눠져 있다. 컴퓨터는 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다.
- 메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체다. 메모리 셀 하나의 크기는 1바이트(8비트)이며, 컴퓨터는 메모리 셀의 크기, 즉 1바이트 단위로 데이터를 저장하거나 읽어들인다.
- 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.
- 변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다. (값의 위치를 가리키는 상징적인 이름이다.)
변수명과 변수 값
- result는 변수 이름이다.
- 변수에 저장된 값(30)은 변수 값이다.
- 변수에 값을 저장하는 것을 할당(대입, 저장)이라 하고, 변수에 저장된 값을 읽어 들이는 것을 참조라 한다.
식별자
- 변수의 이름을 식별자라고도 한다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다.
- 식별자는 값이 저장되어 있는 메모리 주소와 매핑관계를 맺으며, 이 매핑 정보도 메모리에 저장되어야 한다.
- 식별자는 값이 아니라 메모리 주소를 기억하고 있다.
- 변수, 함수, 클래스 등의 이름과 같은 식별자는 네이밍 규칙을 준수해야 하며, 선언에 의해 자바스크립트 엔진에 식별자의 존재를 알린다.
변수 선언
- 변수 선언이란 변수를 생성하는 것을 말한다. 좀 더 자세히 말하자면 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것이다.
- 변수를 사용하려면 반드시 선언이 필요하다. 변수를 선언할 때는 var, let, const 키워드를 사용한다.
ES5 vs ES6
var 키워드는 여러 단점이 있다 가장 대표적인 것이 블록 레벨 스코프를 지원하지 않고 함수 레벨 스코프를 지원한다는 것이다. 이로 인해 의도치 않게 전역 변수가 선언되어 심각한 부작용이 발생하기도 한다.
- 변수 선언에 의해 확보된 메모리 공간은 비어 있을 것으로 생각할 수 있으나 확보된 메모리 공간에는 자바스크립트 엔진에 의해 undefined라는 값이 암묵적으로 할당되어 초기화된다. 이것은 자바스크립트의 독특한 특징이다.
- 자바스크립트 엔진은 2단계에 거쳐 변수 선언을 수행하는데 선언 단계와 초기화 단계로 나눠진다.
- 선언 단계: 변수의 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화 한다.
- 만약 선언하지 않는 식별자에 접근하면 ReferenceError(참조 에러)가 발생한다.
- ReferenceError(참조 에러)는 식별자를 통해 값을 참조하려 했지만 자바스크립트 엔진이 등록된 식별자를 찾을 수 없을 때 발생하는 에러이다.
변수의 이름은 어디에 등록될까?
변수의 이름을 비롯한 모든 식별자는 실행 컨텍스트에 등록된다. 실행 컨텍스트는 자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이고 이를 통해 식별자와 스코프를 관리한다.
변수 선언의 실행시점과 변수 호이스팅
- 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임이 아니라 그 이전 단계에서 먼저 실행된다.
- 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다. 이때 소스코드 실행을 위한 준비 단계인 소스코드의 평과 과정에서 변수 선언을 포함한 모든 선언문(변수 선언문, 함수 선언문 등)을 소스코드에서 찾아 먼저 실행한다. 이 과정이 끝나면 변수 선언을 포함한 모든 선언문을 제외하고 소스코드를 한 줄씩 순차적으로 실행한다.
- 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라 한다.
- var, let, const, function, function* class 키워드를 사용해서 선언하는 모든 식별자(변수, 함수 클래스 등)는 호이스팅된다. 모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문이다.
값의 할당
값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.
- 변수 선언은 런타임 이전에 먼저 실행되고 값의 할당은 런타임에 실행된다.
- score 변수에 값을 할당하는 시점에는 이미 변수 선언이 완료된 상태이며, 이미 undefined로 초기화 되어있다.
- score 변수에 값을 할당하면 score 변수의 값은 undefined에서 새롭게 할당한 숫자 값 80으로 변경(재할당)된다.
- 변수 선언과 값의 할당을 하나의 문장으로 단축 표현해도 선언과 값의 할당을 2개의 문으로 나누어 각각 실행한다.
변수에 값을 할당할 때는 이전 값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값을 새롭게 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 그 곳에 할당 값을 저장한다는 점에 주의하자.
값의 재할당
- 값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없다면 변수가 아니라 상수라 한다. 상수는 한번 정해지면 변하지 않는 값이다.
가비지 콜렉터
- 가비지 콜렉터는 애플리케이션이 할당한 메모리 공간을 주기적으로 검사해 더 이상 사용되지 않는 메모리를 해제하는 기능이다.
- 더 이상 사용되지 않는 메모리는 어떤 식별자도 참조하지 않는 메모리 공간이다.
- 자바스크립트는 가비지 콜렉터를 내장하고 있는 매니지드 언어로서 가비지 콜렉터를 통해 메모리 누수를 방지한다.
언매니지드 언어와 매니지드 언어
언매니지드 언어는 개발자가 명시적으로 메모리를 할당하고 하는 방식이다.
- 최적의 성능을 확보할 수 있지만 치명적 오류를 생산할 가능성도 있다.
- 자바스크립트 같은 매니지드 언어는 메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당한다.
- 개발자가 직접적으로 메모리를 제어하는걸 허용하지 않는다. ( 명시적으로 할당하고 해제하는 것을 허용하지 않는다. )
- 해제는 가비지 콜렉터가 수행하고 이 또한 개발자가 관여할 수 없다.
식별자 네이밍 규칙
- 네이밍 컨벤션은 하나 이상의 영어 단어로 구성된 식별자를 만들 떄 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 규칙이다.
표현식과 문(Statement)
값
- 값은 식이 평가되어 생성된 결과를 말한다.
- 식을 해석해서 값을 생성하거나 참조하는 것을 의미한다.
- 변수는 하나의 값을 저장하기 위해 확보한 공간 자체 또는 메모리 공간을 식별하기 위한 이름이고 값은 변수에 할당된다.
리터럴
- 리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 말한다.
- 코드가 실행되는 시점인 런타임에 리터럴을 평가해 값을 생성한다. ( 값을 생성하기 위해 미리 약속한 표기법이라고 할 수 있다. )
리터럴 | 예시 | 비고 |
---|---|---|
정수 리터럴 | 100 | |
부동소수점 리터럴 | 10.5 | |
2진수 리터럴 | 0b01000001 | 0b로 시작 |
8진수 리터럴 | 0o101 | 0o로 시작 (ES6에서 도입) |
16진수 리터럴 | 0x41 | 0x로 시작 (ES6에서 도입) |
문자열 리터럴 | "Hello" | |
불리언 리터럴 | true | |
객체 리터럴 | { name: "Lee", address: "Seoul" } | |
배열 리터럴 | [1, 2, 3] | |
함수 리터럴 | function() {} | |
정규 표현식 리터럴 | /[A-Z]+/g |
표현식
- 표현식은 값으로 평가될 수 있는 문이다. 새로운 값을 생성하거나 기존 값을 참조한다.
- 값으로 평가될 수 있는 문(Statement)은 모두 표현식이다.
문(Statement)
- 문(Statement)은 프로그램을 구성하는 기본 단위이자 최소 실행 단위다.
- 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다.
- 선언문, 할당문, 조건문, 반복문 등으로 구분할 수 있다.
- 변수 선언문을 실행하면 변수가 선언되고, 할당문을 실행하면 값이 할당된다. 조건문을 실행하면 지정한 조건에 따라 실행할 코드 블록이 결정되어 실행되고, 반복문을 실행하면 코드 블록이 반복 실행된다.
표현식인 문과 표현식이 아닌 문
표현식인 문과 표현식이 아닌 문
- 표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해보는 것이다.
- 크롬 개발자 도구에서 표현식이 아닌 문을 실행하면 언제나 undefined를 출력한다. ( 이를 완료 값이라 한다. )
- 완료 값은 표현식의 평과 결과가 아니라 다른 값과 같이 변수에 할당할 수 없고 참조할 수도 없다.
- 반대로 표현식인 문을 실행하면 언제나 평가된 값을 반환한다.
데이터 타입
- 자바스크립트는 7개의 데이터 타입을 제공한다. 7개의 데이터 타입은 원시타입과 객체타입으로 분류할 수 있다.
원시 타입 (Primitive Type)
- 숫자 타입
- 문자열 타입
- 불리언 타입
- undefined 타입
- null 타입
- symbol 타입
객체 타입 (Object Type)
- 객체
- 함수
- 배열
데이터 타입이 필요한 이유
- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해
- 값을 참조할 때 한 번에 읽어들여야 할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
Last updated on