Harmony에서 ECMAScript 2015까지
ES42의 종결은 TC39가 1999년 이래 처음으로 Javascript의 미래 발전 경로를 계획함에 있어 상대적으로 깨끗한 기반으로 시작할 수 있도록 해주었다. TC39는 언어를 개선하기 위해 처음부터 다시 시작하는 것을 더 이상 고려하지 않았다. TC39는 성공을 향해 나아가기 시작했다. 그 목표에 도달하는 데 7년이 걸렸다.
21.1 Harmony의 시작(Getting Started with Harmony)
TC39의 Harmony 프로젝트는 ES4 작업 중에 이루어진 이전의 결정에 의한 제약을 받지 않았지만 여전히 그 결정들을 참조할 수 있었다. TC39는 ES5 프로젝트에서 내려진 결정들에 의한 제약을 받기는 했지만 그 작업은 Harmony가 나아갈 것으로 예상되는 방향과 전반적으로 일치했다. 실제로 2008년 하반기와 2009년의 TC39 회의 시간 대부분은 ES5를 완성하는 데 할애되었다. 이는 전체 위원회가 Harmony를 위한 기반으로 ES5 명세를 작업하는 데 익숙해질 기회를 제공했다.
21.1.1 Strawmen과 목표들(Strawmen and Goals)
2008년 8월 ECMAScript 위키에 "Harmony Strawman" 페이지가 생성되었다. 그리고 es4-discuss
메일링 리스트는 es-discuss
g로 이름이 바뀌었다. Harmony 발표 이후 es-discuss
에서는 잠재적인 Harmony 기능에 대한 새로운 토론이 폭발적으로 일어났다. 개발된 워크플로우는 새로운 아이디어가 es-discuss
또는 TC39 회의에서 나타나고, TC39 멤버가 그 아이디어가 좋다고 생각하면 초기 디자인이나 기능 설명을 작성하여 Strawman 위키 페이지에 게시하는 것이었다. Strawman은 TC39 회의에서 발표되었고, 위 원회의 반응에 따라 아이디어가 버려지거나 또는 아이디어를 정제하기 위해 해당 과정이 반복되었다. 2008년 11월 21일, 위키 Strawman 페이지 [TC39 Harmony 2008]에는 다음 항목들이 나열되어 있었다.
- classes
- names
- const 키워드
- return to label
- lambdas
- types
- lexical scope
간단한 strawmen 제안들을 가리키는 모든 항목들은 원래 작성되어 있던 classes를 제외하고 모두 Dave Herman이 작성했다.
가능한 Harmony 기능에 대한 논의는 광범위했고 2009년 여름까지 위원회는 활동에 더 많은 구조를 도입하기로 결정했다. 2009년 7월 회의 [TC39 2009a]에서 TC39 멤버들은 Harmony의 목표를 정의할 때라고 결정했다. 그들은 ES3.1의 목표 [Crockford 2008a]가 몇 가지 추가 사항과 개선이 있다면 여전히 적용 가능하다고 결론지었다. Brendan Eich [2009a]는 그 목표의 업데이트된 버전을 게시했다. 그 결과인 Harmony의 목표 선언문이 그림 38에 나타나 있다.
요구 사항
- 새로운 기능은 구체적인 시연을 해야 한다.
- 언어를 일반적인 개발자들이 사용하기 쾌적하도록 유지한다.
- 언어의 "작게 시작하고 반복적으로 프로토타입을 만드는" 특성을 보존한다.
목표
- 다음과 같은 것들을 작성하는 데에 더 나은 언어가 된다:
- 복잡한 애플리케이션
- 해당 애플리케이션들에 의해 공유되는 라이브러리(DOM을 포함할 수 있음)
- 새 버전을 대상으로 하는 코드 생성기
- 테스트 가능한 명세로 전환한다. 이상적으로는 주로 ES5로 호스팅되는 정의적 인터프리터가 된다.
- 가능한 경우 사실상의 표준을 도입하며 구현체 간 호환성을 향상시킨다.
- 버전 관리를 가능한 한 단순하고 선형적으로 유지한다.
- 정적으로 검증 가능한, 객체-능력 보안 부분 집합을 지원한다.
방법
- ES5 이외에 필요한 추가적인 의미 상태를 최소화한다.
- 다음을 위한 구문적 편의성을 제공한다:
- 좋은 추상화 패턴
- 응집도 높은 패턴
- 커널 시맨틱으로의 디슈거링으로 정의됨
- 혼란스럽거나 문제가 되는 구조를 버저닝이나 컴파일러 지시문을 통해 제거한다.
- Harmony가 ES5 엄격 모드를 기반으로 만들어지도록 고려한다.
- 호스트 객체 에뮬레이션을 허용하는 가상화 지원을 제공한다.
그림 38. Harmony의 목표 선언문, 2009년 7월 [Eich 2009a]
21.1.2 챔피언스 모델(The Champions Model)
Dave Herman은 "챔피언 모델" 개발 방식을 도입할 것을 위원회에 제안했다1. 챔피언 모델을 적용하면 개별 멤버나 소규모 그룹이 하나의 기능을 담당한다. 이런 담당자를 챔피언이라고 하는데 챔피언은 초기 strawman 제안을 작성하고 그 제안이 실제 명세에 통합될 준비가 될 때까지 개선하려고 시도한다. 초기 제안에서 시작해서 이후 제안이 점점 발전해 나감에 따라 챔피언은 전체 위원회에 발표를 하고 위원회와 다른 리뷰어들로부터 피드백을 받는다. 피드백을 소화하고 피드백에 기반하여 제안을 업데이트할지 여부를 결정하는 것은 챔피언의 몫이다. 챔피언 모델에 따르면 챔피언의 발표 과정이 진행되는 도중에 위원회가 다시 설계를 맡기로 하는 것을 피해야 한다. 단 궁극적으로 최종 제안을 명세에 포함시키기 위해서는 전체 위원회의 광범위한 합의 결정이 필요하다.
위원회는 챔피언 모델을 따르자는 Herman의 제안을 받아들였으며 전반적으로 이를 효과적으로 사용했다. 그러나 이 방식은 때때로 실패했다. 당시의 핵심 그룹 멤버들은 비교적 작은 규모였고 기술적으로 매우 능숙했다. 그들은 때때로 "위원회에 의한 설계"를 조금이라도 하고 싶은 유혹을 참지 못했고 어떨 때는 이것이 실제로 제안에 대한 진전을 이루는 가장 효과적인 방법이었다. 가끔 특정 기능이나 설계 문제에 대해서 대안적인 접근 방식과 제안을 가진 여러 챔피언이 등장했다. 이런 경우 서로 다른 제안을 한 챔피언들이 합의에 이르지 못하면 위원회는 하나를 선택하거나 경우에 따라 모든 제안들을 거부해야 했다.
21.1.3 기능 집합 정하기(Choosing a Feature Set)
테마들
- 모듈 기능 혹은 외부 사용자로부터 내부를 숨기기 위해 소스 코드 단위를 구분하는 방법
- 사이드 이펙트의 전파를 방지하거나 특정 참조를 통해서만 허용하기 위한 격리 방법
- 권한이 전혀 없는 제작자 스타일의 모듈
- 원시형/컨텍스트/내장 기능과 모듈의 다른 조합
- 브라우저의 격리 부족: 연결되어 있는 다수의 전역 객체
- 계층화된 게스트 코드 호스팅, 분리된 객체 시스템 연결, 특히 호스트 객체 에뮬레이션을 위한 가상화 방법
- 프록시
- 약한 참조 또는 수명이 아주 짧은 객체
- 반복과 상태 머신 코드를 단순화하기 위한 제어 효과
- 구분된 연속성
- 제너레이터, 이터레이터
- TC39 위원회가 라이브러리 진화를 방해하지 않도록 하는 라이브러리/도구 지원
- Object.hashcode
- 몇몇 종류의 바이트 배열
- 십진법 산술 등을 위한 값 타입
- 사용자를 나쁜 형태의 코드에서 벗어나도록 이끄는 "더 나은 유인책"을 제공하는 언어 개혁
- 블록 범위 내에서 let, const, function
- 기본 및 나머지 매개변수, 스프레드 연산자
- 구조 분해
- 새로운 문법이 Harmony의 일부이기 때문에 하는 버전 관리
- 이 테마는 최소한의 옵트인 버 전 관리, 마이그레이션 용이성, 다음 에디션을 위한 미래 지향성을 강조한다.
그림 39. 2010년 Harmony의 기능 테마들 [Eich 2010a]
2009년, 2010년과 2011년 상반기의 대부분 기간 동안 TC39의 챔피언들은 제안의 초안을 개발하고 위원회와 그 제안들을 검토하고 제안이 명세에 받아들여질 수 있도록 제안에 대한 광범위한 합의를 얻으려는 시도를 했다. 2009년 8월까지 Strawman 페이지 [TC39 Harmony 2009]는 원래 7개였다가 21개의 제안으로 성장했다. 2010년 초에는 Harmony 기능 집합의 전체적인 형태가 드러나기 시작했다. Brendan Eich [2010a]는 Harmony의 목표에 관한 페이지에 테마들(그림 39)을 추가하고 거기에 따라 제안들을 조직화했다. 2010년 12월에는 Strawman 페이지 [TC39 Harmony 2010b]가 66개의 제안으로 늘어났고 추가적인 17개의 제안 [TC39 Harmony 2010a]이 이미 연기되었거나 포기되었다. 2011년 5월 초에 Strawman 페이지 [TC39 Harmony 2011c; 부록 N]는 100개가 넘는 항목을 가지고 있었고, 승인된 제안 페이지 [TC39 Harmony 2011a]에는 17개의 항목이 있었다.
2009년 Brendan Eich [TC39 2009b]는 TC39가 2011년 5월까지 "ES.next"의 기능 목록을 확정하고 2012년 6월 Ecma 총회에서 이를 승인받는 것을 목표로 할 것을 제안했다. 5월 목표일이 다가오면서 2012년 6월에 승인받는 게 달성 불가능하다는 게 명백해졌다. 하지만 명세 개발에 집중하기 위해 확정된 기능 목록을 작성하는 것은 여전히 의미가 있었다. 5월 회의 [TC39 2011b]의 대부분은 기능 제안 목록을 분류하고 어떤 남은 제안이 "Harmony Proposal" 상태로 승격될지에 대한 광범위한 합의에 도달하는 데에 쓰였다. 각 기능 제안은 승격 여부에 대한 합의가 존재하는지를 가늠하기 전에 논의되었다. 일부 제안은 최소한의 검토 후에 승격되거나 거부되었다. 다른 중요한 기능을 나타내는 제안들은 위원회가 당시의 기능 제안 초안에 만족하지 않았음에도 불구하고 승격되었다. 이런 제안들은 더 개선된 제안의 개발을 기다리는 의미의 플레이스홀더 역할을 했다. 모듈과 클래스가 이런 식으로 다루어졌다. Harmony의 최종적인 기능 집합은 그 회의에서 엄격하게 확정되지 않았다. ES.next의 개발이 계속됨에 따라 몇몇 제안이 추가되었고 몇몇은 제외되었다. 그러나 이 회의에서 나온 제안 목록은 이후 ES2015의 뼈대가 되었다. 그림 40은 5월 회의의 참가자들을 나열하고, 부록 O는 회의 후의 Harmony Proposal 페이지 [TC39 Harmony 2011b]를 보여준다.
21.1.4 작성 시작(Writing Starts)
Avner Aharon | Microsoft | Waldemar Horwat | |
Douglas Crockford | Yahoo! (Phone) | Mark Miller | |
Brendan Eich | Mozilla | John Neumann | Ecma |
Cormac Flanagan | UCSC | Alex Russell | |
David Fugate | Microsoft | Mike Samuel | |
Dave Herman | Mozilla | István Sebestyén | Ecma |
Luke Hoban | Microsoft | Sam Tobin-Hochstadt | Northeastern Univ |
Bill Frants | Periwinkle (guest) | Allen Wirfs-Brock | Mozilla |
그림 40. 2011년 5월 TC39에서 기능 선별에 참가한 사람들 [TC39 2011b]
5.1.4 보충 문법 개념 도입
5.3 정적 시맨틱 규칙(Static Semantic Rules) 개념 도입
8.6.2 [8.6.2] 및 여러 곳에서[[Class]]
내부 속성 제거. 대신 다양한 내부 트레이드마크 속성 추가
10.1.2 새로운 Es.next 문법을 사용할 수 있는 "확장된 코드"라는 개념 정의. 또한 "엄격한 코드"를 ES5 엄격 모드 코드 또는 확장된 코드를 의미하도록 재정의.
11.1.4 배열 리터럴에서 스프레드 연산자 사용에 대한 문법과 시맨틱 추가
11.1.5 속성 값 축약 및 다양한 시맨틱 헬퍼 추상 연산에 대한 문법과 시맨틱 추가
11.2, 11.2.4 인수 목록에서 스프레드 연산자에 대한 문법과 시맨틱 추가
11.13 구조 분해 할당 연산자에 대한 문법과 시맨틱 추가
12.2 선언 및 형식 매개변수 목록에서 구조 분해를 지원하기 위해 BindingPattern 문법과 부분적인 시맨틱 추가
13 형식 매개변수 목록에서 나머지 매개변수, 매개변수 기본 값, 구조 분해 패턴을 지원하는 문법 추가. 또한 그에 대한 정적 시맨틱도 포함됨. 그러나 이러한 매개변수의 인스턴스화는 아직 이루어지지 않았음. 이런 개선된 매개변수 목록에 대해 인수 목록의 "length" 정의
15 조항 15의 함수 명세가 사실상[[Call]]
내부 메소드의 정의임을 명확히 함.
15.2.4.2[[Class]]
를 사용하지 않고 toString을 다시 명세함. 명시적 확장 메커니즘 추가는 아직 해야 할 일임.
부록 B 웹 브라우저 ES 구현의 규범적 선택 기능으로 제목 변경.그림 41. 첫번째 ES6 초안의 수정 사항 로그 [Wirfs-Brock et al. 2011a, reformatted]
Allen Wirfs-Brock은 프로젝트의 편집자로서 TC39의 챔피언들에 의해 개발된 Harmony 제안으로부터 ES.next 명세 문서를 생성하는 것을 전반적으로 담당했다. Microsoft에서 그의 업무는 TC39 관련 작업과 다른 프로젝트로 나뉘어 있었다. 2010년 12월, 그는 ES Harmony에 집중하기 위해 Microsoft를 떠나 모질라로 이직했다.
Allen Wirfs-Brock은 새로운 표준 판을 완성해 나가는 데 있어서 실제 명세 문서에 대한 지속적인 작업이 필수적이라는 걸 ES4, ES5 경험을 통해 알고 있었다. 2011년 6월 22일, 그는 심각한 결심을 가지고 최근 완성된 ES5.1 명세의 소스 파일을 열고, 표지 페이지를 "초안, 제6판"이라고 변경한 뒤 이를 ES6 초안 명세의 기반으로 저장했다. 그 다음 그는 즉시 지난 5월의 기능 분류와 지난 2년 동안 위원회가 내린 기타 결정들에 기반하여 새로운 자료를 편집하기 시작했다. 7월 12일 그는 "ES.next 명세의 첫 번째 작업 초안" [Wirfs-Brock et al. 2011a,b]을 게시했다. 그림 41은 그 초안의 변경 사항 요약이다. 이건 38개의 배포된 초안 중 첫 번째였으며 그 38개 중 가장 마지막으로 배포된 초안은 2015년 4월 14일 위키에 게시된 것이었다 [Wirfs-Brock et al. 2015a,c].
21.1.5 하나의 Javascript(One JavaScript)
Harmony 활동이 시작될 때부터 TC39는 Harmony의 새로운 기능 전부 혹은 대부분을 사용하기 위해서는 어떤 명시적인 허용이 있어야 할 거라고 가정했다. 이는 ES4의 시대에서 이어진 가정이다. 그때의 몇몇 제안들은 기존의 일부 Javascript 프로그램을 유효하지 않게 만들 수 있는 breaking change를 포함했기 때문이다. Harmony의 프로세스는 ES4에 비해 breaking change에 대해 더 보수적이었지만 몇몇 breaking change는 여전히 고려되고 있었다. Harmony 개발의 첫 3년 동안, 정확한 허용 메커니즘은 미정이었지만 자주 논의되었다. 첫 번째 ES6 초안은 ES5 엄격 모드의 슈퍼셋인 "확장된 코드" 개념을 포함했지만 아직 허용 메커니즘에 대한 설명은 포함하지 않았다. 고려된 대안들은 HTML의 <script>
요소 속성을 사용하는 외부적인 허용, 새로운 use mode
pragma 문, 구분된 구문 형태, 또는 "use strict"와 비슷한 추가 지시문을 추가하는 것 등이 있었다. 그런데 이렇게 하다 보면 미래에 얼마나 많은 모드가 있게 될지 에 대한 우려가 있었다. 표준의 각 주요 판은 새로운 허용 모드를 필요로 하게 될까? 이는 언어의 사용자와 구현자 모두에게 더 복잡한 일을 시키게 될 것이었다.
Dave Herman [2011b]은 "ES6는 허용이 필요하지 않다"라는 제목의 es-discuss
메시지에서 breaking change가 매우 제한되어야 하며 ES6 모듈로 캡슐화된 코드에만 적용되어야 한다고 주장했다. 대부분의 기능은 기존 코드의 기능을 해치지 않아야 하며 모듈 내부에 있는지에 상관없이 동일하게 작동해야 한다. 그렇게 하기 위해서는 일부 기능을 재설계해야 했고 몇몇 경우에는 고려된 몇 가지 기능을 포기해야 했다. 이 아이디어들은 es-discuss
메시지에 달린 150개 이상의 답글을 통해서 정제되었다. 다음 TC39 회의에서 Herman [2012]은 "One JavaScript"라는 제목의 발표에서 이러한 아이디어들을 정제한 결과를 소개했다. 핵심은 미래의 프로그래머와 ECMAScript Harmony의 구현자들이 모드, 버전, 또는 언어 방언에 대해 생각하지 않고 하나의 통합된 JavaScript 언어에 대해 생각할 수 있어야 한다는 거였다. 그 관점과 일관되게 ES.next를 설계하는 것은 TC39의 책임이었다. 회의의 많은 부분이 이 제안에 대한 논의와 이 제안이 여러 Harmony 기능에 미칠 영향에 대한 토론에 쓰였다. Harmony에서 "하나의 JS"를 만드려는 시도를 하자는 것이 최종적으로 합의되었다. 다음 명세 초안 [Wirfs-Brock et al. 2012a]에서는 확장된 코드 개념이 사라졌고 breaking change가 되었을 부분들을 없애기 위한 여러 변경사항들이 있었다.
21.1.6 Brendon의 꿈(Brendan's Dreams)
2011년 1월 Harmony 작업을 2년 이상 진행한 시점에 Brendan Eich [2011b]는 "내가 바라는 Harmony"라는 제목의 블로그 글을 게시했다. 이 글에서 그는 언어 발전과 표준 위원회에 대한 몇 가지 의견을 제시했다. 글의 핵심은 그가 희망하는 Harmony JavaScript가 어떤 모습일지에 대한 예시들을 제공한다.
...저는 JavaScript Harmony에 대한 새로운 비전을 제시하고 싶습니다. 이러한 시도는 (아직) 공식적이지는 않지만 그렇다고 목표도 없고 기이하기만 한 허구도 아닙니다. 이와 같은 것은 실제로 일어날 수 있으며 여러분의 도움이 있다면 더욱 그럴싸해지고 나아질 것입니다(어떻게 할지는 마지막 부분에서 더 설명할 것입니다).
저는 TC39에서 현재 합의된 Harmony, TC39의 일부가 선호하는 초안 제안들, 제 아이디어 사이의 경계를 의도적으로 흐리게 하고 있습니다. 왜냐하면 저는 JS에 새로운 개념적 완전성이 필요하다고 생각하기 때문입니다. 거기에는 위원회가 안전하게 설계하는 게 필요하지 않습니다. TC39에서 통과되지 않을 "모든 제안을 합치자"는 접근이든, 역시 TC39에서 통과되지 않을 것이지만 "제안들을 교집합하고 만약 공집합만 남는다면 그대로 두자"는 접근이든 말입니다.
그는 다양한 사용 사례들이 ES5 기능을 사용하여 어떻게 코딩되는지와 그가 꿈꾸는 Harmony에서는 같은 것을 어떻게 표현할 수 있는지에 대한 예시들을 제시했다. 이러한 예시들은 Harmony 제안들과 그것들이 실제 ES2015 기능으로 어떻게 진화했는지에 대한 중간 단계의 관점을 제공한다. 그가 제시한 것들의 일부는 ES2015에 포함되지 않았고 대부분의 기능들은 ES2015에 포함되었더라도 어떤 식으로든 변경되었다. 하나의 JS를 지향하는 접근 방식이 기존 기능의 문법과 의미를 명시적인 허용 모드 하에서 변경하는 것을 제한했으므로 다른 변경사항들이 필요했다.
이 기능 발전에 대한 관점을 얻기 위해서 Brendan Eich가 2011년 꿈꿨던 것2들과 결국 ES2015에서 실현된 것들을 비교해 보자.
- Dream: 바인딩과 스코핑
블록 스코프 선언과 자유 변수 참조(free variable reference)는 parse time에 에러가 난다.
let block_scoped = "yay!";
const REALLY = "srsly";
function later(f, t, type) {
setTimeout(f, t, typo); // EARLY ERROR
}
-
ES2015의 실제 구현:
let
과const
선언은 블록 스코프지만 자유 변수 참조에 대한 early error 기능은 하나의 JS를 위해 포기되었다. -
Dream: 개선된 함수 정의
function
키워드의 제거, 마지막 expression의 암시적인 return
, 자유 변수가 없는 함수의 불필요한 클로저 제거
const #add(a, b) { a + b }
#(x) { x * x }
- ES2015의 실제 구현: 화살표 함수가
#
표시 대신 나왔다. 암시적인 리턴은 화살표 함수의 본문 자체가 표현식일 때만 적용된다. 객체 리터럴과 클래스 본문의 축약 메서드 정의가 들어왔다. 내부적인 클로저 최적화는 구현체에게 넘겨졌다.
const add = (a, b) => a + b // expression body has implicit return
x => x * x
x => { console .log(x); return x * x} // statements body needs explicit return
// method definition in object literals and classes
class {
add(a, b) {return a + b} // No expression bodies
}