9월 6일 부터는 HTML&CSS 강의가 끝나고 자바스크립트 강의가 시작된다. 따라서 모던 자바스크립트 Deep Dive 책을 읽고 정리한 내용을 앞으로 적을 예정이다.
빨리 가는 유일한 방법은 제대로 가는 것이다. - 로버트 c. 마틴
자바스크립트는 웹페이지의 단순한 보조 기능을 처리하기 위한 제한적인 용도를 목적으로 태어났지만 프론트엔드와 백엔드 영역의 프로그래밍 언어로 사용할 수 있는 범용 애플리케이션 언어로 성장하였다.
이에 따라 자바스크립트를 학습하는 방식 또한 기본 개념과 동작 원리를 깊이 있게 학습해야 한다.
자신이 구현한 코드가 의도한 대로 정확히 동작해서 문제를 해결해야하기 때문!
이를 위해서 기본 개념과 동작원리를 정확하게 이해하는 것이 중요하다. 이러한 기본 개념과 동작원리의 이해는 안정적이고 효율적인 코드를 생산할 수 있는 기본기이다.
기본 개념과 동작 원리를 이해하려고 노력 --> 여러번 반복해서 학습
단순히 라이브 코딩을 감상하거나 타이핑 하는 것이 아닌 의도적인 연습을 해야한다.
프로젝트를 통해 더욱 깊이 이해하고 협업을 경험하면서 모르는 것과 아는 것을 구분하여 추가로 학습이 필요한 경우 다시 기본 개념과 동작 원리 이해로 돌아가 학습을 시작
컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션
이를 위해선 문제 해결 능력이 중요하고, 0과 1밖에 알지 못하는 기계가 실행할 수 있을 정도로 정확하고 상세하게 요구사항을 설명하는 작업이 프로그래밍이다.
컴퓨터의 관점에서 문제를 사고하려면 해결 과제를 작은 단위로 분해하고 패턴화해서 추출하며, 프로그래밍 내에서 사용될 모든 개념은 평가 가능하도록 정의해야 한다.
"걷다" 라는 기능을 구현할 때, 판단해야하는 상태(오른발이 왼발보다 앞에 있는가?)와 그 상태를 판단하는 시기, 그리고 판단 기준을 정의해야하며 이를 바탕으로 실행 여부를 결정함. 예를 들어 2족 보행 로봇의 디자인을 하면서 장애물이란 무엇(크기, 움직임 등)인지, 어떤 범위 내에 있는 것인지 명확히 수치화해서 정의해야함.(장애물을 피해야 하므로)
기계어(컴퓨터가 알아듣는 언어)는 사람이 사용하는 언어와 체계가 다르기 때문에 직접 명령을 전달하는 것은 매우 어려워서 컴파일러 혹은 인터프리터를 사용해서 컴퓨터와 대화한다.(프로그그래밍 언어를 기계어로 바꾸어줌)
이러한 프로그래밍 언어는 구문과 의미의 조합으로 표현된다.
문법을 잘 안다고 해서 외국어를 잘한다고 말할 수 없듯이, 프로그래밍도 마찬가지로 문법에 맞는 문장을 구성하는 것은 물론 의미 를 가지고 있어야 언어의 역할을 충실히 수행할 수 있다.
const number = 'string';
console.log(number * number);
위 문장은 문법적으로 전혀 문제가 없지만 의미적으로는 옳지 않다.
number라는 이름의 변수에는 숫자를 할당하는 것이 의미적으로 옳다.
프로그래밍의 목적은 문제 해결이다.
1995년, 넷스케이프 커뮤니케이션즈에서 웹페이지의 보조적인 기능을 수행하기 위해 브라우저에서 동작하는 경량 프로그래밍 언어를 도입함. 이것이 브랜던 아이크라는 사람이 만든 자바스크립트이다.
처음에는 모카 -> 라이브스크립트 -> 자바스크립트라는 이름으로 바뀜
그러나 자바스크립트의 파생버전인 JScript가 출시되어 위기를 맞음.
마이크로소프트는 자바스크립트의 파생 버전인 JScript를 인터넷 익스플로러에 탑재함.
넷스케이프와 마이크로소프트는 자사 브라우저 시장 점유율을 높이기 위해 자사 브라우저에서만 동작하는 기능을 경쟁적으로 추가! --> 크로스 브라우징 이슈 발생
이로 인해 표준화된 자바스크립트의 필요성이 대두됨 --> ECMA 인터내셔널에서 표준화된 자바스크립트인 ECMAScript가 탄생됨(상표권 문제 때문에 자바스크립트가 아닌 ECMAScript라고 불림)
2009년에 ECMAScript5가 HTML5와 함께 표준 사양이 출현하고, 2015년에 ECMAScript6가 공개되는데, 범용 프로그래밍 언어로서 갖춰야 할 기능들이 포함된다. 이 이후 버전업은 작은 기능을 추가하는 수준으로 매년 공개됨.
초창기 자바스크립트 - 웹의 보조적인 기능을 수행하기 위해 한정적인 용도로 사용.
자바스크립트를 이용해 서버와 브라우저가 비동기 방식으로 데이터를 교환할 수 있는 통신 기능
jQuery의 등장으로 DOM(Document Object Model)을 더욱 쉽게 제어하고, 크로스 브라우징 이슈도 해결함.
자바스크립트 보다 배우기 쉽고 직관적인 jQuery 더 선호하는 개발자가 늘어나기도 함.
JS로 웹 애플리케이션을 구축하려는 시도의 증가와 함께 더욱 빠르게 동작하는 자바스크립트 엔진의 필요성이 대두됨 --> V8 자바스크립트 엔진의 등장
이로 인해 웹 서버에서 수행되던 로직들이 클라이언트(브라우저)로 이동하게 됨.
자바스크립트 런타임 환경으로 자바스크립트를 브라우저 이외의 환경에서 동작할 수 있도록 자바스크립트 엔진을 브라우저에서 독립시킨 자바스크립트 실행 환경이다.
주로 서버사이드 애플리케이션 개발에 주로 사용되고, 이에 필요한 모듈 파일 시스템, HTTP 등 내장 API를 제공한다. 비동기 I/O를 지원하며 단일 스레드 이벤트 루프 기반으로 동작하여 요청 처리 성능이 좋다. --> SPA에 적합함.
이제 자바스크립트는 프론트뿐만이 아닌, 백엔드 영역가지 아우르는 웹 프로그래밍 언어의 표준으로 자리 잡음으로써 크로스 플랫폼을 위한 가장 중요한 언어로 주목 받고 있다.
이전의 개발 방식으로는 복잡해진 개발 과정을 수행하기 어려워져 이에 따라 많은 패턴과 라이브러리가 출현하였는데 이것만으론 부족하여 프레임워크가 등장하게 됨.
CBD(Component based development)방법론을 기반으로 한 SPA가 대중화 되면서 Angular, React, Vue.js, Svelte등 다양한 SPA 프레임워크/라이브러리가 등장함.
ECMAScript는 프로그래밍 언어의 핵심 문법을 규정한다. 각 브라우저 제조사는 이 사양을 준수해서 브라우저에 내장되는 자바스크립트 엔진을 구현함
자바스크립트는 일반적으로 프로그래밍 언어이면서도 클라이언트 사이드 Web API인 DOM, BOM, XMLHttpRequest, fetch등을 아우르는 개념이다.
클라이언트 사이드 Web API는 월드 와이드 웹 콘소시엄(W3C)에서 별도의 사양으로 관리하고 있다.
웹 브라우저에서 동작하는 유일한 프로그래밍 언어
인터프리터 언어이며 대부분의 모던 자바스크립트 엔진은 인터프리터와 컴파일러의 장점을 결합해 비교적 처리 속도가 느린 인터프리터의 단점을 해결함.
또한 JS는 명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어 이면서 다른 객체지향 언어와의 차이점이 있긴 하지만 클래스 기반 객체지향 언어보다 효율적이면서 강력한 프로토타입 기반의 객체지향 언어다.
인터넷 익스플로러를 제외한 모던 브라우저의 ES6 지원 비율은 96%~99%로 거의 100%에 육박함.
브라우저에서 아직 지원하지 않는 최신 기능을 사용하거나 인터넷 익스플로러나 구형 브라우저를 고려해야 하는 상황이면 바벨(Babel)과 같은 트랜스파일러를 사용
브라우저와 Node.js의 용도가 다르기 때문에 이에따라 지원하는 API들이 다르다.
구글 크롬 브라우저를 사용
자바스크립트 코드에서 에러가 발생한 경우 가장 먼저 살펴봐야할 곳
HTML파일의 script태그가 있다면 자바스크립트코드가 자동적으로 실행된다.
Source패널에서 자바스크립트 코드를 디버깅 할 수 있다.
프로젝트 규모가 커짐에 따라 프레임워크 또는 라이브러리를 도입하거나 Babel, Webpack, ESLint등 여러가지 도구를 사용하기 위해 Node.js와 npm이 필요함.
Node.js는 자바스크립트를 브라우저 이외의 환경에서 동작시킬 수 있는 자바스크립트 실행환경
npm은 자바스크립트 패키지 매니저로, Node.js에서 사용할 수 있는 모듈들을 패키지화 해서 모아둔 저장소 역할과 패키지 설치 및 관리를 위한 CLI를 제공한다.
방문해서 설치
REPL(Read Eval Print Loop)을 사용하여 JS코드를 실행해 결과를 확인해 볼 수 있다.
$ node
위 명령어를 입력하면 프롬포트가 > 로 변경되면 자바스크립트 코드 실행이 가능해진다.
위로 들어가 설치
Ctrl + ` 을 사용해 내장 터미널을 열고
node {파일명}
으로 JS파일을 실행시킬 수 있다.
이 플러그인을 설치하면 VS Code의 내장 터미널에서 단축키를 사용해 JS를 비롯한 다양한 프로그래밍 언어로 구현된 소스코드를 간단히 실행할 수 있다.
윈도우 단축키: CTRL + ALT + N
Mac os: Cotnrol + option + N
클라이언트 사이드 Web API가 포함된 자바스크립트 코드를 실행하려면 브라우저에서 실행해야 하는데 소스코드를 수정할 때마다 수정 사항을 브라우저에 자동적으로 반영해주는것이 Live Server 플러그인이다.
예를 들어 10 + 20 이라는 식이 있다고 가정해보자.
컴퓨터가 값을 계산하기 위해서는 사람과 같이 10, 20 이 무엇인지, + 가 무엇인지에 대한 의미도 알아야하며 이를 저장할 공간이 필요하다. 이 공간을 컴퓨터에선 메모리라고 하는데 메모리에 접근을 하기 위해서는 메모리 주소를 알아야한다. 메모리 주소는 0xFFFFFFFF와 같은 16진수로 되어있는데 이 부분에 직접 접근하는 것은 치명적 오류를 발생시킬 가능성이 높다.
따라서 프로그래밍 언어는 기억하고 싶은 값을 메모리에 저장하고, 저장된 값을 읽어 들여 재사용하기 위해 변수라는 매커니즘을 제공한다.
변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다. --> 값의 위치를 가리키는 상징적인 이름
변수에 값을 저장하는 것을 할당(대입, 저장) 이라 하고, 변수에 저장된 값을 읽어 들이는 것을 참조 라고 한다.
변수 이름을 식별자라 하며 어떤 값을 구별해서 식별할 수 있는 고유한 이름이다.
식별자는 값이 저장되어 있는 메모리 주소와 매핑 관계를 맺고 있고, 메모리 주소를 기억하고 있다.
변수, 함수, 클래스 등의 이름은 모두 식별자이며 선언에 의해 자바스크립트 엔진에 식별자의 존재를 알린다.
값을 저장하기 위한 메모리 공간을 확보하고, 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것
var(함수레벨 스코프), let, const같은 키워드를 사용해서 선언한다.
변수 선언 과정
변수 이름을 등록하고 값을 저장할 메모리 공간을 확보. undefined 값이 암묵적으로 할당되어 초기화된다. undefined는 js에서 제공하는 원시 타입.
변수 선언의 2단계 과정
변수의 이름을 비롯한 모든 식별자는 실행 컨텍스트 에 등록이 되는데 이는 자바스크립트 엔진이 소스 코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역.
이부분을 통해 식별자와 스코프를 관리한다.
console.log(score); // undefined
var score; // 변수 선언문
이 경우 참조에러가 발생하지 않고 undefined가 출력되는데 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문.
이렇게 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라고 함.
var score = 80; // 변수 선언과 값의 할당
한줄로 변수 선언과 값의 할당을 하여도 실제로 둘의 실행시점이 다르다.
변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행!
값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.
엄밀히 말하면 var 키워드로 선언한 변수는 선언과 동시에 undefined로 초기화 되기 때문에 변수에 처음으로 값을 할당하는 것도 재할당이다.
만약 값을 재할당 할 수 없어서 변수에 저장된 값을 변경할 수 없다면 그것은 상수(Constant) 이다. (상수는 단 한번만 할당할 수 있는 변수)
값을 재할당 할때 기존 공간에 새로운 값을 저장하는 것이 아닌 새로운 메모리 공간에 값을 저장하기 때문에 어떠한 식별자와도 연결되어 있지 않은 값들(더 이상 사용되지 않는 메모리)은 가비지 콜렉터에 의해 메모리에서 자동 해제된다.(가비지 콜렉터로 메모리 누수를 방지한다.)
언매니지드 언어 --> c와 같이 메모리 제어(malloc, free)를 개발자가 주도적으로 할 수 있는거
매니지드 언어 --> 개발자의 직접적인 메모리 제어를 허용하지 않음
그외에로도 변수 이름은 변수의 존재 목적을 쉽게 알게 하기 위해 의미를 명확히 표현해야하며 이름을 선언할 시 의미를 생각하면서 심사숙고하여 정하는 것이 좋다.
네이밍 컨벤션
가독성을 높이려면 카멜 케이스와 파스칼 케이스를 따르는 것이 유리하다.
10+20; // 30
10+20은 평가되어 숫자 값 30을 생성한다. 변수에는 10 + 20이 아닌 생성된 결과인 값인 30이 들어간다.
값이란 식이 평가되어 생성된 결과이다.
3
숫자 리터럴 3이며 자바스크립트 엔진은 이를 평가해 숫자 값 3을 생성함.
리터럴 또한값
이다.
즉 리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법이다.
표현식은 값으로 평가될 수 있는 문 으로, 표현식이 평가 되면 새로운 값을 참조하거나 기존 값을 참조한다.
표현식의 예
// 리터럴 표현식
10
'Hello'
// 식별자 표현식(선언이 이미 존재한다고 가정)
sum
person.name
arr[1]
// 연산자 표현식
10 + 20
sum = 10
sum !== 10
// 함수/메서드 호출 표현식(선언이 이미 존재한다고 가정)
square()
person.getName()
값이 위치할 수 있는 자리에는 표현식도 위치할 수 있다.
문은 프로그램을 구성하는 기본 단위이자 최소 실행 단위이다.
토큰이란 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소이다.
var sum = 1 + 2;
위 식은
문
이다.
var, sum, = , 1, +, 2, ; 은 모두토큰
이다.
문의 예
// 변수 선언문
var x;
// 할당문
x = 5;
// 함수 선언문
function foo() {}
// 조건문
if(x>1) { console.log(x); }
// 반복문
for(var i = 0; i < 2; i++) { console.log(i); }
세미 콜론은 문의 종료를 나타내며 자바스크립트에서는 세미콜론을 자동적으로 붙여주는 세미콜론 자동 삽입 기능(ASI)이 존재한다.
그러나 개발자의 예측과 일치하지 않는 경우가 있기 때문에 세미콜론 사용을 권장한다.
var x; // 변수 선언문은 값으로 평가될 수 없으므로 표현식이 아니다. (표현식이 아닌문)
x = 1 + 2; // 표현식이면서 완전한 문 (표현식인 문)
표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는것.
var foo = var x; // SyntaxError
표현식이 아닌 문은 값처럼 사용이 불가하여 SyntaxError 발생
var foo = x = 100;
표현식인 문은 값처럼 사용 가능
번외
크롬 개발자 도구에서 표현식이 아닌 문을 실행하면 언제나 undefined를 출력하는데 이를 완료값이라고 한다. 완료 값은 표현식의 평가 결과가 아니어서 다른 값과 같이 변수에 할당할 수 없고 참조할 수도 없다.
표현식인 문을 실행하면 언제나 평가된 값을 반환한다.
Var a; 이렇게 두 번 선언되면 에러를 발생 시키는 것이 아닌 암묵적으로 넘어가줌(프로그래머가 아닌 잘 모르는 사람이 다룰 것이라 예상 --> 초창기), 웬만에서는 에러 없이 실행해주기 위해
암묵적으로 처리해주는 기능(magic) --> 이 부분에 대한 이해가 없으면 코드를 잘못 읽을 가능성이 있음
string(a)
A + '';
a.toString(); --> 원래 .뒤의 메소드를 작동시키기 위해서는 a가 객체여야하는데 원시값인데도 불구하고 실행시켜줌
런타임 --> 코드가 실행되는 시점
런타임에러 --> 사용자가 실행을 시켰을 때 에러
동적 타입 언어 --> 변수 선언시 변수의 타입 정보를 알려 주지 않음
정적 타입 언어 --> 변수 선언시 변수 타입 정보를 알려줌 (c같은거 int a) --> 메모리 절약
코드 독해 시 자바스크립트는 암묵적인 처리가 많아서 더 어려움
절차형 --> 지금까지 작성한 프로그래밍 언어
선언형 --> 모던 자바스크립트 환경(리액트)
에버그린 브라우저 --> 자동적으로 브라우저가 사용자에 대한 별도의 재설치를 요구하지 않고도 업데이트가 가능한 브라우저
브라우저 대부분이 es6문법이 먹힘 그러나 100%는 아니어서 바벨을 사용해서 es5이하 버전도 지원하게 만듦.
Esnext --> ecmascript의 정식사양은 아닌데 정식으로 올라올것들.
비동기 --> 데이터를 제외한 나머지 부분을 그리고 나서 데이터가 도착하면 데이터를 그리기 시작함
데스크탑 : 업데이트 할 때 불편함 --> cd같은거 재 구매 해서 설치해야함, 시장이 받아들이기 힘듦
웹 어플리케이션: 설치할 필요 없고 사용자가 업데이트가 되었는지 안되었는지도 몰라도 됨, 불법복제 불가, 유지보수가 편함
Ajax(ms가 만듦) + v8 engine --> chrome의 구글 맵스
Cbd --> 화면을 렌더링할 때 html, css, js가 필요! --> 그냥 하나로 묶어서 관리하자 --> CBD --> 목적: 재사용성
재사용 : 변수, 함수, 객체:변수와 로직이 함께 있는거(프로퍼티와 메소드), 컴포넌트(뷰를 재사용하기 위해)
Ecmascript : ecma international에서 관리
Client-side api --> w3c에서 관리
node.js --> node.js에서 관리
선언형은 함수형보다 큰 개념
개발을 할 때 효율에 치중하지 말고 가독성을 챙겨라 가독성인 측면에선 함수형이 많이 권장됨
가독성 측면에서 for문 지양해라.
Eslint에 깔려있는 루트 폴더 아래서 작업하라!
코드 러너 --> node.js환경에서 작동하는 거
10 + 20 에서 10은 리터럴(리터럴은 값을 만들어 내는 표기법, 사람이 이해할 수 있는 표기법)
비순수함수 --> 내부의 상태에 의존함
Function add(a, b) { x=100; return a + b + x; }
메모리에서 가져온 값을 cpu 안에 캐시메모리나 레지스터에 저장해서 사용
undefined값 --> 브라우저마다 값이 다르기 때문에 몇 바이트인지 알 수 없음.
변수와 메모리주소의 매핑관계는 js엔진이 알고잇음(사실 js엔진도 모르고 기계어 단에서 처리)
함수형 언어의 특징 --> 함수가 값이고 함수 이름은 식별자이다.
식별자는 스코프 내에서 유니크 해야한다.
메모리 --> 현재 사용하고 있는 공간 lock으로 잠금
가비지 콜렉터 --> 사용하고 있지 않은 공간의 lock을 풂. 언제가 될지는 모름 (변수의 life cycle)
console.log(a)의 a는 참조하는 것
js에서 값을 할당하는 과정에서 undefined 부분을 지우고 그 위에다가 덮어쓰게 되면 var b = a라는 선언이 될때 b는 a와 같은 곳을 가리키고 있기 때문에 값을 변경하지 않아도 a가 바뀌면 b도 바뀜.
이것이 코드가 간단한 몇줄이면 찾기 쉬운데, 몇 백줄인 상태에서 찾으려면 찾을 수 없고 버그가 발생.
변수에다가 값을 처음으로 넣는 행위 --> 초기화(개발자가 명시적으로 처음으로 값을 할당하는거)
Var a; --> 초기화는 아니지만 자바스크립트 엔진이 암묵적으로 undefined로 할당함.
Var a = 1; 이 부분은 두 가지로 나뉨 var a; a = 1;로 나뉘고 var a의 경우 런타임 이전에 실행이되고 a = 1은 런타임에 실행
undefined로 초기화 하는이유 --> 다른 애플리케이션에서 사용하고 남은 값들을 쓰레기 값
Let과 const키워드는 선언하기 이전에 참조하면 에러가 발생한다.
예습 범위 --> 타입 변환과 단축 평가까지! (9장) - 내일은 러버덕을 할때 1~5까지