1. JavaScript 넌 누구니?
동적인 웹사이트를 만들기 위해서 Marc Andreessen이 고안한 DOM요소들을 조작하는 scripting 언어 입니다.
이후 Javascript를 그대로 복사한 Jscript 등 다양한 언어들이 등장하며 정규화 되지 못하고 각 브라우저에서만 호환되는 불편한 상황이 지속 됐습니다.
AJAX(Asynchronous JavaScript and XML, 비동기적으로 서버에서 데이터를 가져오고 처리하는 기술)가 등장하고, 각종 라이브러리(jQuery, dojo, mootools …)가 제공하는 APIs를 이용하여 더이상 브라우저에 의존하지 않는 개발이 가능해졌습니다.
여기서 배울 수 있는 좋은 프로그래밍 철학은, 각 layer에 종속되지 않는 interface를 만들어서 구현사항이 변경되어도 사용자의 코드는 변화하지 않도록 하는 것이 좋은 코드입니다.
이후 ECMAscript(표준사항)도 더욱 발전하여 5,6에서 많은 기능들이 추가되어 라이브러리의 도움 없이 모든 웹브라우저에서 호환이 됩니다.
각 브라우저에서 사용되는 Javascript 엔진은 모두 다릅니다. 그중에 V8엔진은 node.js나 ELECTRON에서도 많이 사용됩니다.
- BABEL 개발자는 최신버전으로 개발을 하고싶고 사용자는 항상 최신 브라우저를 사용하는 것은 아니기 때문에, 최신 ECMAscript로 개발을 하고 사용자에게 배포할 때만 ECMAscript 5,6로 변환해주는 transcompiler를 BABEL이라고 합니다.
-
SPA 최근에는 Single Page Application 이라는 하나의 페이지에서 필요한 부분만 업데이트 하는 것이 개발 경향입니다. 이런 개발동향을 위해서 제공되는 것이 React, viewjs 같은 프레임워크 입니다.
-
nodejs 강력한 V8엔진과 ECMAscript를 통해서 nodejs가 등장하게 됩니다. nodejs는 javascript 엔진을 이용하여 ServerSide 개발이 가능하게 하는 프레임워크입니다. 그외 다양한 프레임워크를 통해 모바일 웹페이지나 데스크탑 앱을 만드는 등 잠재력이 무궁무진합니다.
-
뜨고있는 기술 브라우저에서 동작할 수 있는 유일한 언어는 javacript였지만, WebAssembly의 등장으로 C++, java 등 다양한 언어를 이용하여 웹브라우저에서 동작할 수 있는 기술이 주목받고 있습니다.
-
콘솔에 출력 이제 본격적으로 콘솔에 Hello World를 출력해보고 js 강의를 시작합니다.
console.log('Hello World');
만약 nodejs가 설치되어 있다면 해당 폴더에서 node 파일명만 입력하면 Hello World의 출력을 확인할 수 있습니다.
vscode를 이용하여 index.html파일을 생성하고 script태그를 이용하여 main.js를 추가합니다.
...
<head>
...
<script src="main.js"></script>
...
vscode의 open with live server를 이용하면 브라우저에서 바로 확인가능합니다.
- 윈도우 단축키 : Ctrl Shift i
- 맥 단축키 : cmd option i
이 console API의 log라는 함수를 이용해서 우리가 원하는 메세지를 콘솔창에 출력했습니다.
또한 nodejs를 이용한 콘솔창 출력도 확인할 수 있었습니다. 이는 nodejs와 webAPI(브라우저가 제공하는 함수) 둘 다 console에 관련된 API를 갖고 있는 것입니다. mdn라이브러리에서 해당 내용을 확인할 수 있습니다.
- dev tools(개발자 도구) 브라우저의 개발자도구를 이용하면 개발에 많은 도움을 받을 수 있습니다.
- Elements 탭은 html에서 작성한 요소들을 확인할 수 있습니다.
- Console 탭에서는 단순 로그 뿐만 아니라 js를 실행할 수 있어서 다양하게 활용 할 수 있습니다.
-
Sources 탭에서는 디버깅에 유용한 탭입니다.
- js 공식 사이트
js의 공식 문서를 통해 공식문서를 확인할 수 있습니다.
mozilla-mdn사이트에서는 js 공식문서로 공부하기 좋습니다.
2. async VS defer
html에서 js를 어떻게 추가하는 것이 더 효율적인지에 대한 문제입니다.
2.1. head에 추가하는 경우
앞선 경우처럼 head에 script를 추가하는 경우, 브라우저가 한줄씩 파싱해 DOM요소로 변환시킵니다.
이후 script태그가 보이면 pasing을 멈추고 script를 fetching하고 실행 한 후 다시 parsing 합니다.
이런 방식은 js파일이 어마어마하게 큰 경우, 사용자가 페이지를 읽어오는데 많은 시간이 소요됩니다.
2.2. body 끝부분에 추가하는 경우
이때는 페이지를 모두 불러온 다음 fetching하기 때문에 js를 받기전에도 사용자가 컨텐츠를 빨리 볼 수 있습니다. 하지만 js에 의존적인 페이지라면 정상적인 페이지를 볼 수 없습니다.
2.3. head + async
head안에 script를 이용하는 것에 asyn속성을 추가하는 것입니다. 1번의 경우와 마찬가지로 parshing하다 asyn를 만나게 되면 병렬로 fetching을 진행하고 완료하면 pasing을 멈추고 executing을 하게 됩니다.
병렬 처리로 다운로드 시간을 줄일 수 있지만, js에서 queryselector를 이용하여 DOM요소를 조작하는 등의 행위를 할 때, html이 parsing되기 전에 executing 되기에 문제를 야기할 수 있습니다.
2.4. head + defer(권장)
async의 경우처럼 병렬처리를 하지만 parsing을 끝낸 다음 excuting 합니다.
2.5. async와 defer의 차이
async의 경우 스크립트에 정의된 순서에 상관 없이 먼저 fetching된 스크립트를 execuitng합니다. 순서가 중요한 script일 경우 문제가 될 수 있습니다.
defer의 경우 순서가 지켜집니다.
- use strict
'use strict';
순수언어인 바닐라자바스크립트를 사용할 때는 use strict를 선언해주는 것이 좋습니다.
js는 유연한 만큼 위험합니다. 예를들면 선언되지 않은 변수의 값을 할당하거나 기존에 선언된 프로토타입을 변경하는 등 비상식적인 행위가 가능합니다.
ECMAScirpt5에 추가된 use strict를 선언하면 이런 위험한 행위를 방지할 수 있습니다.
3. 데이터 타입
- Variable(변수)
js에서 변수를 선언할 때는 let으로 선언합니다. 이는 ES6에서 추가되었습니다.
let name = 'lala'; console.log(name); name = 'ogu'; console.log(name);
name 이라는 변수의 값이 변하여 출력되는 것을 확인할 수 있습니다.
변수를 선언하면 애플리케이션 마다 부여된 메모리에서 name이라는 변수를 저장하는 포인터가 생기게 됩니다.
-
Block scope 블록을 이용하면 일종의 지역변수처럼 사용되 해당 블록 밖에서는 변수를 사용할 수 없게됩니다.
블록 없이 선언한 변수는 global 변수로 전역에서 사용될 수 있습니다.
전역 변수는 애플리케이션이 종료될 때 까지 메모리에 남아있기 때문에 가능하면 최소한으로 클래스나 함수 등 필요한 부분에서만 선언하는 것이 좋습니다. -
var(사용 금지) ES6전에 사용하던 변수 선언으로 var를 이용하면 변수를 선언하기 전에 값을 할당 할 수 있었으므로 많은 문제를 야기합니다.
이것을 var hoisting 이라고 합니다. 정확히는 어디에 선언하든 상관없이 항상 제일 위로 선언을 끌어 올려주는 것입니다.console.log(age); age = 5; var age;
의 경우 var age; 가 제일 위로 선언되어 정의되지 않은 값이 콘솔에 출력됩니다. 또한 var는 Block scope를 무시합니다.
물론 let을 사용하려면 웹브라우저가 es6를 지원해야합니다. 메이저 브라우저중에는 익스플로러를 제외하고 지원하기 때문에 let을 사용해도 됩니다.
-
Constants(read only) const는 java의 final 키워드와 같다고 볼 수 있습니다. 한번 값이 할당되면 변하지 않는 Immutable타입입니다.
이런 상수 타입은 보안이 강하고 thread safety하며 실수를 방지 할 수 있습니다.
-
Variable types 모든 언어는 원시 타입과 객체(참조)타입으로 나뉩니다.
-
primitive type 더 이상 작은 단위로 나누어질 수 없는 한가지 아이템 입니다. number, string, boolean, null, undefined, symbol이 있습니다. 메모리에 값 자체가 저장됩니다. Immutable data타입 입니다.
-
object type(참조 타입) 아이템들을 묶어서 한 단위로 관리해주는 타입입니다. box, container 등이 있습니다.
값이 저장되는 것이 아닌 object가 담겨있는 메모리의 주소값을 참조합니다. mutable타입입니다.
const lala = { name: 'lala', age:30 };
// const로 선언된 lala포인터는 변경이 불가능하지만, lala object안의 name과 age값은 변경 가능합니다.
lala.age = 31;
-
function function도 데이터타입 중 하나로 first-class function(일급함수)를 지원한다는 의미는 다른 데이터타입처럼 변수로 선언이되고 매개변수 인자 등으로 사용할 수 있으며 function으로 return할 수 도 있다는 의미입니다.
-
C언어와의 비교 C언어나 java에서는 좀더 세세한 숫자 타입을 선언할 수 있습니다. 이런 low level 프로그래밍으로 얻는 이점은 개발자가 세세하게 메모리 최적화를 할 수 있는 것입니다.
반면 js는 number라는 키워드가 있음에도 let으로 통일하여 선언할 수 있습니다. -
특별한 숫자 키워드(에러방지)
- Infinity : 무한대
- -Infinity : -무한대
-
NaN : 숫자가 아님
- string
js의 string은 글자 수에 제약 받지 않습니다.
const brendan = 'brendan'; const greeting = 'hello' + brendan; // ''와 변수의 차이에 주목 console.log(`value: ${greeting}, type: ${typeof greeting}`); const helloBob = `hi ${brendan}!`; // template literal ''가 아닌 ``을 이용하면 + 없이 붙어 나옵니다. // 기존의 방식 : console.log('value: ' + helloBob + ' type: ' + typeof helloBob); console.log(`value: ${helloBob}, type: ${typeof helloBob}`);
-
boolean false에 할당 되는 값은 0, null, undefined, NaN, ‘‘을 포함합니다.
-
undefined null과 다르게 변수를 선언하고 어떠한 값도 정의하지 않는 값입니다.
- symbol
고유한 식별자가 필요할 때 사용합니다. 동일한 string으로 식별자를 부여했어도 다른 symbol로 구별됩니다.
동일한 식별자로 구분하고싶다면 Symbol.for메소드를 이용합니다. 출력 할때는 description 메소드를 이용하여 출력합니다.
4. Dynamic typing
js는 선언할 때 어떤 타입인지 선언하지 않고, 런타임 시에 할당된 값에 따라 타입이 변경 될 수 있음을 의미합니다.
빠르게 개발할 때는 유용하지만 규모가 있는 애플리케이션을 제작 할 때에는 위험 할 수 있습니다.
이를 위하여 typescript가 등장했습니다.
5. operator
간단히 console로 출력하는 방법만 살펴봅니다. 이때 팁은 check()함수는 그 행위가 가장 크므로 순서상 가장 뒤에 놓습니다.
== 연산자의 경우, 타입에 상관없이 값만 비교합니다. 타입을 비교하는 ===연산을 권장합니다.
참조 타입의 경우 참조하는 곳이 같을 경우만 true입니다.
6. functions
js에서 함수는 일종의 오브젝트며 일급시민으로 파라미터나 리턴 자체로도 사용될 수 있어, 콜백 함수로 많이 쓰입니다. 사용법은 아래와 같습니다.
function name(param1, param2) {body.. return ;}
파라미터와 리턴값, 함수 이름으로 어떤 기능을 하는가 예측이 가능합니다. js는 타입을 지정할 수 없으므로 타입을 지정할 필요가 있다면 typescript를 이용해야 합니다.
-
default parameters ES6에서 추가된 기능으로 파라미터가 비어진 채로 전달 됐을 떄, 기본적인 출력 값을 지정하는 것입니다.
-
rest parameters 배열 형태로 가변 파라미터를 받을 수 있습니다. ES6에서 추가되었습니다.
- early return
조건이 맞지 않을 때는 return을 줘서 빨리 함수를 종료하고 조건이 맞을 때만 필요한 로직을 실행하는 것이 좋습니다.
- function expression 함수는 일급시민 이므로 변수에 함수를 대입하면 바로 사용할 수 있습니다.
-
call back 파라미터로 함수를 받아 특정 조건일 때 해당 함수를 return 합니다.
-
arrow function 함수를 람다식으로 표현합니다.
7. class VS object
class란 관련된 속성과 행위가 묶여있는 것을 말합니다.
틀(template)로 정의만 하는것이 class 이고, object는 class를 실체화 한 것입니다. class는 ES6에 정의되었습니다.
7.1. 캡슐화
사람의 나이가 -1이 될 수 없듯이, 사용자가 입력을 잘못하는 것을 방지하기 위해 getter/setter와 접근제어자 private을 사용합니다.
class User{
constructor(...){
this.age = age;
}
get age(){return this.age;} // this._age;
set age(value){this.age = value;} // this._age;
}
게터세터 사용시 주의할 점은, 위와 같이 사용하면 call stack(overflow)가 발생합니다. 게터와 세터가 this.age(게터) = age(세터);로 무한 참조가 일어나기 때문입니다. 이를 피하기 위해서는 변수명을 조금 다르게 해줍니다.
7.2. 상속과 다형성
class 간의 공통되는 부분을 떼어내어 상속받거나 다향한 형태로 변할 수 있도록 만듭니다.
8.object
object는 { key : value } 의 쌍입니다.
선언적 오브젝트 생성
const obj1 = {}; // object literal
const obj = new Object(); // object constructor
// 바로 오브젝트를 생성하는 것도 가능하다
const lala = { name: `lala`, age:30}
js는 runtime 때 type이 결정되는 언어이므로 뒤늦게 object에 새로운 field를 추가할 수 있습니다.
8.1. computed properties
key는 항상 string 값으로 불러 올 수 있습니다. 이는 어떤 값인지 결정이 안되고 runtime에서 결정되어야 할 때 사용합니다.
예를 들어, 이런 문장에서는 undefined가 발생하는데, obj파라미터로 들어온 ellie object의 key propertiy가 존재하지 않기 떄문입니다.
console.log(lala.name);
console.log(lala.['name']); // computed properteis
// 같은 결과
8.2. constructor function
function 이름의 첫글자를 대문자로 표현해, java의 생성자처럼 동작하는 함수입니다.
8.3. for.. in
object의 모든 key(속성)들을 가져올 때 유용한 문장입니다.
for (key in lala){
console.log(key);
}
8.4. for (value of iterable)
배열의 모든 속성을 불러오는 for..of문장입니다.
8.5. Object.assign()
object를 복사하는 방법
9. 배열
배열은 안쓰이는 프로젝트가 없을 정도로 활용도가 높습니다. 배열은 동일한 타입 데이터들을 모아두는 것이지만 runtime시에 타입이 결정되는 js인 만큼 여러가지 타입의 배열이 섞일 수 있습니다.
배열의 알고리즘은 검색, 삽입(push, unshift), 정렬, 삭제(pop, shift)가 있고 그 자료구조에는 list, map, set등이 있습니다. 각각 어떤 알고리즘이 더 효율적인지 판단하여 사용하는 것이 중요합니다.
배열은 inddex를 이용하여 삽입과 삭제가 편리합니다.
1. 배열의 생성
const arr1 = new Array();
const arr2 = [1, 2];
2. index position
const furits = ['apple', 'banana'];
console.log(fruits[0]);
console.log(fruits[fruits.length -1]);
배열의 앞부터 삽입하고 삭제하는 shift는 모든 index를 변경해줘야 하므로 속도가 매우 느립니다.
splice()를 이용하면 원하는 index부터 삭제 할 수 있습니다.
10. JSON(JavaScript Object Nation)
웹브라우저에서 동작하는 client와 server간에 어떻게 통신하는지에 대해 정의한 것이 HTTP입니다.
client는 server에게 request(요청)할 수 있고, server는 client에게 response(응답)하여 데이터를 주고 받습니다.
JSON은 key와 value의 한 쌍으로 이루어져있고, byte type의 직렬화(serialize)에도 사용되며, 언어에 종속되지 않고 사용됩니다.
10.1. AJAX(Asynchronous JavaScript And XML)
AJAX는 비동기적으로 데이터를 주고받을 수 있는 방식을 말합니다. 대표적으로 XHR(XMLHttpRequest)object가 있습니다. 이 XHR오브젝트는 브라우저에서 제공하는 API입니다.
이름에는 XML이 들어가 있지만 JSON등의 데이터들도 주고받을 수 있습니다. xml은 그 수가 많아질수록 가독성이 떨어져 JSON이 많이 사용되고 있습니다.
10.2. 직렬화
JSON 데이터를 어떻게 object에서 string으로 serialization하는지 살펴봅니다. stringfy 함수의 정의를 보면, string으로 변환하고, replacer라는 옵션 파라미터를 콜백함수로 추가해 결과에 추가적인 동작이 가능한 함수임을 알 수 있습니다.
// 1. Object to JSON
let json = JSON.stringfy(rabbit);
console.log(json);
const rabbit = {
name: 'tori',
color: 'white'
size: null,
birthday: new Date(),
jump: () => {
console.log(`${name} can jump!`);
},
};
// object안의 jump 함수는 데이터가 아니므로 JSON으로 변환 되지 않습니다.
json = JSON.stringify(rabbit, (key, value) => {
console.log(`key: ${key}, value: ${value}`);
return key === 'name' ? 'lala' : value;
});
console.log(json);
// replacer 콜백 함수로 key와 value를 순서대로 추력하고, key가 name인 경우 lala를 출력하고 name이 아닌 경우에는 그대로 value를 출력하도록 했습니다.
10.3. 역직렬화
JSON의 parse API를 이용하여 JSON데이터를 object로 변환합니다. 이때, rabbit 오브젝트에서 직렬화 했을때 jump 함수가 포함되지 않았으므로 jump함수는 포함되지 않습니다. 또한 Date 타입인 birthday 역시 string타입으로 변환되었기 때문에 역직렬화시 string타입으로 변환 됩니다. 세밀화 하게 역직렬화 하여 Date타입으로 변환하려면 replacer 콜백 함수를 이용합니다.
const obj = JSON.parse(json, (key, value) => {
console.log(`key: ${key}, value: ${value}`);
return key === 'birthDate' ? new Date(value) : value;
});
console.log(obj);
console.log(obj.birthDate.getDate());
댓글남기기