1. Overview
앵귤라(Angular) 에서는 자바스크립트(JavaScript), 다트(Dart), 타입스크립트(TypeScript)를 공식 언어로 지원하고 있습니다. 그리고 이 책에서는 마이크로스프트(Microsoft)의 타입스크립트를 사용하여 어플리케이션을 만들어갈 예정입니다. 그에 앞서, 앵귤라 어플리케이션을 만들기 위해서 기초가 되는 내용들을 한 번씩 짚어보고 가도록 하겠습니다. 기본 언어인 타입스크립트와 타입스크린트의 기반인 ECMAScript 그리고 개발하는데 있어서 도움을 주는 각종 개발 도구들에서 알아 보도록 하곘습니다.
1.1 ECMAScript
자바스크립트 는 매우 유명한 스크립트 언어입니다. 하지만 언제부터인지 ECMAScript 라는 이름이 등장하며 두 이름이 혼용되어 사용되기 시작하였습니다. 그렇다면 ECMAScript가 무엇이고, 자바스크립트와는 무엇이 다른지 알아보겠습니다.
1995년 넷스케이프(Netscape)의 개발자인 브렌단 아이크(Brendan Eich) 는 자신들의 새로운 인터넷 브라우저에 탑재 될 모카(Mocha)(이후 라이브스크립트(LiveScript))라는 스크립트 언어를 개발하였습니다. 그리고 좀 더 대중적인 이름을 원하던 넷스케이프는 자바(Java) 상표권을 갖고 있는 썬 마이크로시스템즈(Sun Microsystems)와 협의하여 스크립트 언어의 이름을 자바스크립트 로 최종 확정하고 1996년 3월 넷스케이프 네비게이터 2.0 과 함께 발표합니다.
<< 수정 전 >> 자바스크립트 는 클라이언트 기반 스크립트 언어로서 큰 성공을 거두었고 넷스케이프의 브라우저는 단숨에 인기상품이 되었습니다. 당시 인터넷 브라우저 시장의 경쟁자였던 마이크로소프트(Microsoft)는 제이스크립트(JScript) 라는 이름으로 자바스크립트와 유사하고 자바스크립트가 가지고 있던 몇 가지 문제들을 해결한 자신들 만의 스크립트 언어를 개발하기 시작합니다. 그리고 1996년 8월 인터넷 익스플로러 3.0 과 함께 발표합니다.
<< 수정 후 >> 그 당시 대부분의 웹 사이트들은 정적인 웹 페이지와 간단한 태그들로 이루어져 있었습니다. 이러한 상황에서 웹 페이지를 동적으로 조작하며 사용자의 행동에 반응할 수 있게 해주는 자바스크립트의 등장은 웹 환경에 커다란 충격을 주었습니다. 그리고 많은 웹 사이트들이 자바스크립트를 사용하기 시작했습니다. 그야말로 넷스케이프의 대성공을 이끈것 입니다. 하지만 인터넷 브라우저 시장의 경쟁자인 마이크로소프트(Microsoft)도 가만히 있지는 않았습니다. 자바스크립트가 성공하자 자바스크립트의 기능을 대부분 호환하고 자바스크립트가 가지고 있던 몇 가지 문제들을 해결한 제이스크립트(JScript) 를 개발하여 1996년 8월 인터넷 익스플로러 3.0 과 함께 발표합니다.
갑작스러운 경쟁자의 등장으로 넷스케이프는 자바스크립트를 보다 빠르게 확산시키길 원했고 다양한 방법을 구상하기 시작했습니다. 그 결과로 자바스크립트의 기술 규격을 인터넷에 공개하고 표준화하기로 합니다. 그리하여 1996년 11월 정보 통신분야 비영리 표준기구인 Ecma 인터네셔널(Ecma International, 이하 Ecma) 에 자바스크립트의 기술 규격 정의 업무를 이관 하였습니다. Ecma는 자바스크립트의 기술 규격에 ECMA-262 라는 이름 부여하고 1997년 스크립트 언어 표준의 첫 번째 버전을 공개합니다. 불과 1년 사이에 자바스크립트라는 스크립트 언어가 웹 생태계에 등장하고 표준화 작업까지 거치게 된것입니다.
<< 수정 전 >> 이듬해인 1997년부터 ECMA는 자신들이 정의한 언어 표준(스펙 정의 문서 : ECMA-262)을 공개하였습니다. 그 이후, 몇 개의 버전이 발표되었지만 한 가지 중요한 문제가 발생하게 됩니다. 바로 언어 표준의 정식 명칭을 무엇으로 하느냐 하는 문제가 발생한 것입니다. JavaScript는 넷스케이프가 썬 마이크로시스템즈에게 사용료를 지불하는 형태의 라이센스 계약으로 만들어진 이름이였기에 언어 표준의 이름으로 JavaScript를 계속 사용하려면 썬 마이크로시스템즈에 사용료를 지불해야 하는 상태가 된것입니다. 이러한 마케팅적인 이유로 인하여 언어 표준의 이름은 ECMAScript로 정해지고, ECMAScript를 구현하는 언어들이 각각의 이름을 갖는 형태로 마무리 되었습니다. 그래서 보통 우리가 얘기하는 JavaScript는 ECMAScript의 구현 언어 중 하나 이지만 ECMAScript와 혼용되어 초코파이 처럼 일반 명사로 사람들에게 널리 사용되고 있습니다.
<< 수정 후 >> 이처럼 표준화 작업이 순탄하게 진행되던 중에 중요한 문제가 발생하게 됩니다. 바로 '표준화된 스크립트 언어의 이름을 무엇으로 할 것인가?' 입니다. 넷스케이프는 자바스크립트 라는 이름을 사용하고 있었고, 마이크로소프트는 제이스크립트 라는 이름을 사용하고 있었습니다. 더군다나 자바스크립트 는 넷스케이프와 썬 마이크로시스템즈의 계약으로 탄생한 이름이였고, 넷스케이프가 이름 사용료를 지불하는 형태의 계약이였습니다. 사용료 문제, 넷스케이프와 마이크로소프트의 힘 싸움 등이 겹치게 되면서 Ecma는 언어의 이름을 기존에 사용되던 이름이 아닌 새로운 것으로 정할 수 밖에 없었고, 결국 ECMAScript 로 정해졌습니다.
이것이 자바스크립트가 ECMAScript로 이름이 바뀌었다는 것을 의미하지는 않습니다. ECMAScript는 언어 표준의 이름이고 기술 규격(ECMA-262)을 준수한 스크립트 언어들은 각각의 이름을 갖는 것입니다. 간단하게 정리 해보면 표준 기술 규격의 이름은 ECMA-262, 기술 규격을 준수한 표준 언어의 이름은 ECMAScript, 표준 기술 규격에 명시된 기능들을 모두 제공하고 추가적으로 부가적인 기능등을 갖고 있는 스크립트 언어는 자바스크립트 나 제이스크립트 와 같은 이름을 갖는것 입니다. 다음 장에서 살펴 볼 타입스크립트 도 ECMAScript의 기능을 포함하고 interface
와 같은 고유의 기능들을 제공하는 스크립트 언어인것 입니다. 이처럼 자바스크립트가 표준 스크립트 언어의 이름은 아니지만 대표적으로 널리 사용되는 스크립트 언어 이기 때문에 많은 곳에서 일반명사 처럼 사용되고 있습니다.
<< 이 표는 없어도 될듯???? >>
버전 | 발표일 | 설명 |
---|---|---|
1 | 1997년 6월 | 초판 |
2 | 1998년 6월 | ISO/IEC 16262 국제 표준과 완전히 동일한 규격을 적용하기 위한 변경. |
3 | 1999년 12월 | 강력한 정규 표현식, 향상된 문자열 처리, 새로운 제어문 , try/catch 예외 처리, 엄격한 오류 정의, 수치형 출력의 포매팅 등. |
4 | 버려짐 | 4번째 판은 언어에 얽힌 정치적 차이로 인해 버려졌다. 이 판을 작업 가운데 일부는 5번째 판을 이루는 기본이 되고 다른 일부는 ECMA스크립트의 기본을 이루고 있다. |
5 | 2009년 12월 | 더 철저한 오류 검사를 제공하고 오류 경향이 있는 구조를 피하는 하부집합인 "strict mode"를 추가한다. 3번째 판의 규격에 있던 수많은 애매한 부분을 명확히 한다.[1] |
5.1 | 2011년 6월 | ECMA스크립트 표준의 제 5.1판은 ISO/IEC 16262:2011 국제 표준 제3판과 함께 한다. |
6 | 2015년 6월 | 6판에는 클래스와 모듈 같은 복잡한 응용 프로그램을 작성하기 위한 새로운 문법이 추가되었다. 하지만 이러한 문법의 의미는 5판의 strict mode와 같은 방법으로 정의된다. 이 판은 "ECMAScript Harmony" 혹은 "ES6 Harmony" 등으로 불리기도 한다. |
<< 수정 전 >> ECMAScript는 1997년 처음 발표된 이후로 여러 버전이 출시 되었습니다. 2015년 6월에 ECMAScript의 6번째 버전인 ECMAScript 6를 발표 하였습니다. 이와 함께 표준 갱신 주기를 1년 단위로 정례화 하였고, 표준 명칭 뒤에 붙이는 숫자를 '버전' 대신에 '발표 연도'를 사용한다고 발표하였습니다. 이전과 많이 달라진 웹 생태계에서의 확고한 위치를 유지하기 위한 변화로 보입니다.
<< 수정 후 >> ECMAScript는 1997년 첫 번째 버전이 발표 된 이후로 비 정기적으로 여러 버전이 발표 되었습니다. 하지만, 언어가 발표되고 사용된 기간에 비해서 언어적인 발전은 매우 느리게 이루어졌습니다. 특히, 1999년 발표된 '버전 3' 이후에 여러가지 이유로 인하여 '버전 4'가 폐기되면서 10년 가까이 버전이 정체되는 등 침체기를 겪기도 했습니다. 이러한 상황은 2009년 '버전 5'가 발표되면서 해소되기 시작하였고, 이전보다는 짧은 주기로 새로운 버전들을이 발표되었습니다. 그리고 2015년 6월, Ecma는 ECMAScript의 6번째 버전인 ECMAScript 6를 발표하면서 표준 갱신 주기를 1년 단위로 정례화 하고, 표준 명칭 뒤에 붙이는 숫자를 '버전' 대신에 '발표 연도'를 사용한다고 발표하였습니다. 이러한 변화는 이전과 많이 달라진 웹 생태계에서의 확고환 위치를 유지하기 위한 변화로 인식되고 있습니다.
참고로 ECMAScript의 최신 버전은 2016년에 발표된 ECMAScript 2016(버전 7) 입니다. 하지만 현재 많은 사람들이 사용하고 있는 브라우저들은 ECMAScript 5(혹은 5.1)을 구현한 스크립트 엔진을 탑재하고 있습니다. 즉, 기본적으로는 ECMAScript 2015, 2016의 기능들을 사용할 수 없다는 것 입니다. 그렇기 때문에 ECMAScript 2015, 2016의 기능들을 사용하기 위해서는 최신 버전으로 작성된 내용들을 브라우저에서 지원하는 버전으로 변환해주는 컴파일러 혹은 트랜스파일러를 함께 사용해야 합니다.
1.1.1 ECMAScript 2015
<< 수정 전 >> ECMAScript 6(혹은 ESMAScript 2015, 이하 ES6)은 ECMAScript의 6번째 버전이며, 이전 버전에 비교하여 다른 언어들이 제공하는 쉬운 문법, 강력한 기능들이 많이 추가되었습니다. 그러므로 ES6는 프로그래밍 세계에서는 새로운 것이 아니지만, ECMAScript에 있어서는 새로운 것들이라고 볼수 있습니다.
<< 수정 후 >> 2015년 발표된 ECMAScript 2015는 ECMAScript의 6번째 버전이며, 이전 버전과 비교하여 다른 언어들이 제공하는 쉬운 문법, 강력한 기능들이 많이 추가 되었습니다. 이러한 추가 기능들은 프로그래밍 세계에서는 새로운 내용들이 아닐 수 있지만 ECMAScript에 있어서는 매우 새로운 기능들입니다.
앵귤라에서 지원하는 기본 언어 중에 하나이고, 이 책에서 기본 언어로 사용 할 타입스크립트 가 ECMAScript 2015의 기능들을 제공하기 때문에 타입스크립트에 대해서 알아보기 전에 ECMAScript 2015의 기능들 중에서 많이 사용되는 주요 기능들을 먼저 살펴보도록 하겠습니다.
1.1.1.1 화살표 함수(Arrow Function)
화살표 함수는 =>
로 표현한 함수의 약칭이라고 할 수 있습니다. C#, Java8, CoffeeScript의 화살표 함수와 문법적으로 유사합니다. 화살표 함수는 기본 함수와 비교해서 간단하지만 기본 함수가 제공하던 this, arguments, super, new.target을 할당 하지 않습니다. 또한, 화살표 함수는 항상 익명 함수이고, 메소드가 아닌 일반 함수를 표현하는데 적합합니다. 그리고 클래스의 생성자 함수로 사용 될 수 없습니다. 예제를 통해서 자세히 살표보도록 하겠습니다.
// 기본 형태
(param1, param2, ..., paramN) => { statement }
(param1, param2, ..., paramN) => expression
// { return expression; } 과 동일하게 동작합니다.
// 파라미터가 1개인 경우
(param) => { statements }
param => { statements }
// 파라미터가 없는 경우
() => { statements }
() => expression // { return expression; } 과 동일하게 동작합니다.
// 사용 예제
var evens = [2, 4, 6, 8, 10];
var odds = evens.map(n => n + 1);
var nums = evens.map((n, i) => n + 1);
var pairs = evens.map(n => ({even : v, odd : v + 1}));
evens.forEach(v => {
if (v % 4 == 0) {
console.log('4의 배수 : ', v);
}
});
// Lexical this
var person = {
name : 'Bob',
friends : [],
printFriends() {
this.friends.forEach(f => {
// 일반 함수와는 다르게 this를 할당하지 않는다.
// this 사용 시, 함수 선언부의 영역(this)가 참조된다.
console.log(this.name + "은 " + f + "와 친구이다.")
});
}
}
1.1.1.2 클래스(Classes)
<< 수정 전 >> ES6에서 추가된 클래스는 JavaScript에서 존재하는 프로토타입 기반 상속의 문법 설탕?(sugar)입니다. 따라서, 클래스 문법이 새로운 객체지향 기반의 상속 모델을 제공하는 것은 아닙니다.
클래스 문법은 객체를 만들고 상속하는 과정을 좀 더 간단하고 명확하게 해줍니다. 그리고 프로토타입 기반으로 상속, 부모 클래스 호출, 전역 메소드, 생성자를 지원합니다. (vs 다른 객체지향 기반 언어의 클래스 처럼 constructor, super, static, extends 키워드 등을 사용 할 수 있습니다.)
<< 수정 후 >> ECMAScript 2015에서 추가된 클래스 문법은 프로토타입 기반의 객체 상속 패턴입니다. 클래스 문법은 편리한 선언적 형식을 사용해서 객체를 만들고 상속하는 과정을 좀 더 간단하고 명확하게 해줍니다. 그리고 다른 객체지향 언어들의 클래스 문법처럼 생성자(constructor), 상속(extends), 상위 객체(super) 호출, 정적(static) 메소드 등을 제공합니다. 하지만, 이전 처럼 프로토타입에 기반을 두고 있기 때문에 완전히 새로운 객체지향 기반의 상속 모델을 제공하는 것은 아닙니다.
// 클래스 선언
class Point {
// 생성자
constructor(x, y) {
this.x = x;
this.y = y;
}
// 일반 메소드
print() {
console.log("x 좌표 : " + this.x + " , y 좌표 : " + this.y);
}
// 정적 메소드
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt(dx*dx + dy*dy);
}
}
// 상속 클래스 선언
class 3DPoint extends Point {
constructor(x, y, z) {
// super로 부모 클래스 호출
super(x, y);
this.z = z;
}
// 메소드 오버라이딩
print () {
super.print();
console.log("z 좌표 : " + z);
}
}
// 사용 예제
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.distance(p1, p2));
const p3 = new 3DPoint(5, 5, 10);
p3.print();
단, 클래스 선언은 함수 선언과는 달리 호이스팅(끌어 올리기)는 지원하지 않기 때문에, 클래스 선언과 사용 순서를 잘 지켜주어야 합니다.
1.1.1.3 강화된 객체 리터럴(Enhanced Object Literals)
객체 리터럴을 이용한 객체 선언시 사용자 편의를 위한 기능들이 많이 추가 되었습니다.
- 프토토타입 지정
- 변수 선인 및 할당, 메소드 선언 간소화
- 상위 객체(super) 호출 가능
- 표현식을 이용한 동적 변수명 지정
// 객체 리터럴
var obj = {
// 프로토타입 지정
__proto__ : theProtoObj,
// 변수 선언 및 할당 간소화
handler : handler,
// 메소드 선언 간소화
toString() {
// 상위 객체(super) 호출 가능
return "안녕하세요. " + super.toString();
},
// 표현식을 이용한 동적 변수명 지정
['prop_' + (() => 42)() ] : 42 // 'prop_42' : 42
}
1.1.1.4 템플릿 문자열(Template Strings)
템플릿 문자열은 문자열에 표현식들을 추가 할 수 있게 해줍니다. 또한 여러 줄의 문자열을 한 번에 표현 할 수 있습니다. 템플릿 문자열은 문자열임을 나타낼 때, 따옴표('') 또는 쌍 따옴표("")를 대신 `` 를 사용하여 문자열을 표현합니다. 그리고 달러 문자와 중괄호를 사용하여 표현식(${표현식})을 문자열에 추가할 수 있습니다. 이 외에도 태그 함수와 결합하여 템플릿 문자열을 조작하는 태그 템플릿 문자열이 있습니다.
// 기본 형태
console.log(`문자열 입니다.`);
// 여러 줄의 문자열 표현
console.log(`첫 번째 문자열
두 번째 문자열`);
// 표현식으로 변수 바인딩
var a = 5;
var b = 10;
console.log(`덧셈 결과는 ${a + b}입니다.`);
// 태그 함수와 태그 템플릿 문자열
function tag(strings, ...values) {
console.log(strings[0]); // "덧셈 결과는 "
console.log(strings[1]); // "이고 곱셈 결과는 "
console.log(strings[2]); // "입니다."
console.log(values[0]); // 15
console.log(values[1]); // 50
return "태그 템플릿 문자열";
}
tag`덧셈 결과는 ${a + b}이고 곱셈 결과는 ${a * b}입니다.`;
// "태그 템플릿 문자열"
1.1.1.5 비구조화 할당(Destructing)
비구조화 할당은 배열이나 객체의 데이터를 개별적인 변수로 추출 할 수 있는 문법입니다. 객체나 배열을 문자열로 선언 및 데이터 할당하는 것과 유사한 방법으로 객체와 배열의 데이터를 추출하여 개별적인 변수로 할당합니다. 비구조화 할당은 객체에서 프로퍼티를 참조할 때 처럼 실패에 관대합니다. 따라서, 순서 혹은 구조에 맞는 데이터를 찾지 못하는 경우 undefined
를 자동으로 할당합니다.
// 배열
var x = [1, 2, 3, 4, 5];
var [y, z] = x;
console.log(y); // 1
console.log(z); // 2
// 배열에서 데이터 무시하기
[y, , , z] = x;
console.log(y); // 1
console.log(z); // 4
// 기본값 설정
[y, , , , , z = 10] = x;
console.log(y); // 1
console.log(z); // 10
// 객체
var o = {p : 42, q : true};
var {p, q} = o;
console.log(p); // 42
console.log(q); // true
// 기본값 설정
var {p, q, r = 20} = o;
console.log(p); // 42
console.log(q); // true
console.log(r); // 20
// 객체에서 새로운 이름으로 변수 할당하기
var {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
1.1.1.6 기본(Default) 및 나머지(Rest) 매개변수
함수의 매개변수에도 다음과 같은 기능들이 추가되었습니다.
- 기본값(Default) - 매개변수의 기본값을 지정한다.
- 나머지(Rest) - 명확하지 않은 매개변수들을 배열로 처리한다.
// 매개변수의 기본값 지정
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
// 임의의 매개변수를 배열로 처리
function printLength(...args) {
console.log(args.length);
}
printLength(); // 0
printLength(5); // 1
printLength(5, 6, 8); // 3
1.1.1.7 전개 연산자(Spread)
전개 연산자는 배열을 함수 호출이나 배열 선언, 변수 할당에 있어서 개별적인 값으로 인식 시켜줍니다. 이런 경우 많이 사용되는 배열의 apply 메소드와 유사하지만 좀 더 유연합니다.
// 함수 호출
var spreadArr = [0, 1, 2];
function myFunction(x, y, z) {
...
}
myFunction(...spreadArr);
myFunction(...spreadArr, 3, 4);
// 배열 선언
var arr = [...spreadArr, 3, 4];
1.1.1.8 블록기반 변수(Let)과 상수(Const)
변수 선언에 있어서도 기존에 사용되는 var
외에 고유한 성질을 갖는 변수를 만들 수 있게 되었습니다. 이러한 다양화로 상황에 따라서 적절한 성질을 갖는 변수들을 선언하고 사용 할 수 있게 되었습니다.
블록 기반 변수(let)
- 블록 기반으로 영역을 나누어 지역 변수를 선언 및 사용 할 수 있게 해줍니다.블록 기반 상수(const)
-let
처럼 블록 기반의 지역 변수 이지만, 선언 시 초기화된 값을 바꿀 수 없습니다.
// var를 사용한 변수 선언
function varTest() {
var x = 1;
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
}
// let를 사용한 변수 선언
function letTest() {
let x = 1;
if (true) {
let x = 2;
console.log(x); // 2
}
console.log(x); // 1
}
// const를 사용한 상수 선언
Const MY_VAL = 20;
console.log(MY_VAL); // 20
MY_VAL = 25; // 에러 발생
1.1.1.9 그 외 여러 추가 기능들
앞서 서술한 기능들 외에도 다양한 기능들이 ECMAScript 2015에 추가되었습니다. 그러한 기능들을 모두 설명하기에는 많은 지면이 필요하기 때문에 간략하게 요약하는 것으로 마무리 하도록 하겠습니다. 이 중 에서는 모듈이나 프로미스 처럼 라이브러리를 통해서 이미 많이 사용되던 기능들도 존재하는 것을 알 수 있습니다. 이제는 외부의 라이브러리를 사용하지 않고 자체 기능으로 해당 기능들을 사용 할 수 있게 된 것입니다.
- 반복자(Iterator)와 For...of 문법
- 모듈
- 프록시
- 심볼
- 프로미스(Promise)
- 2진수와 8진수 리터럴
- 기본 객체(Math, Number, String, Object)의 내장 메소드 추가
- 맵(Map, WeakMap), 셋(Set, WeakSet) 객체
- 강화된 유니코드 지원
- 기타 등등
1.1.2 ECMAScript 2016와 2017
2015년부터 ECMAScript는 1년 단위로 갱신되고 있기 때문에 당연하게도 2016년과 2017년에도 새로운 기능들이 추가되었습니다. 하지만 앞으로 사용할 타입스크립트가 아직 ECMAScript2016과 2017을 정식으로 지원하고 있지 않기 때문에 해당 기능들을 따로 설명하지 않도록 하겠습니다. 하지만 지금도 옵션을 통해서 해당 기능들을 사용 할 수는 있습니다. ECMAScript 2016과 2017에서의 변화점들이 궁금하신 분들은 Ecma의 홈페이지에서 해당 내용들을 확인 하실 수 있습니다.