본문 바로가기

Develop/Frontend 가이드

[FE] JavaScript 완벽 가이드, ECMAScript 를 읽는 방법 (1/2)

반응형

TC39
TC39

JavaScript 완벽 가이드, ECMAScript 을 읽는 방법

ECMAScript 는 완벽한 자바스크립트 가이드입니다. ECMAScript 가 자바스크립트 언어를 정의한 문서이며 표준이기 때문입니다. 모든 자바스크립트 엔진은 표준인 ECMAScript 에서 요구하는 사항은 반드시 구현해야 합니다.

ECMAScript 일부
ECMAScript 일부

ECMAScript 를 읽고 싶어도 위 그림과 같이 특유의 단어와 문법으로 적혀 있어서 단순하게 읽을 수가 없습니다. 그래서 혹시 잘 정리한 문서가 있나 찾아봤지만 ECMAScript 에 추가된 새로운 기능을 소개하는 글만 있을 뿐, ECMAScript 를 구체적으로 설명하는 글을 찾을 수는 없었습니다. 그래서 제가 ECMAScript 을 읽다보니, 미리 알았으면 읽기 수월했을 개념들을 정리해서 글로 작성했습니다.

Language types

ECMAScript 에서 Language types 자바스크립트가 사용하는 타입을 의미합니다. 그래서 자바스크립트의 데이터 타입인 undefined, Boolean, Number, String, BigInt, SymbolObject 는 Language types 으로 분류되어 있습니다.

ECMAScript 의 Language types 목차
ECMAScript 의 Language types 목차

Specification Types

Specification Types 은 Language types 외에 ECMAScript 문서 내부에서만 사용하기 위한 타입입니다. ECMAScript 내부에서 기능을 설명하기 위한 용도로 만들어진 타입입니다. 따라서 자바스크립트에서는 직접적으로 사용할 수 없으며, 자바스크립트 엔진에 따라 실질적인 구현이 달라질 수 있습니다. Specification Types 의 대표적인 타입으로는 Reference, Completion Record, Property Descriptor 등이 있습니다.

ECMAScript 내부에서만 활용하는 Specification Types
ECMAScript 내부에서만 활용하는 Specification Types

Abstract Operations

Abstract Operations 중 하나인 [[GetOwnProperty]](P)
Abstract Operations 중 하나인 [[GetOwnProperty]](P)

Abstract Operations 는 ECMAScript 문서에 정의된 함수입니다.

ECMAScript 에서 Abstract Operations 에 대한 설명

위 그림처럼 Abstract Operations 은 개발자에게 익숙한 함수 선언문과 동일한 형식으로 작성되어 있습니다.

Internal Methods and Internal Slots

Abstract Operations 중 [[함수명]](변수) 형식으로 적힌 Abstract Operations 는 Internal Methods 입니다. Internal Methods 는 ECMAScript 내에서 동작을 설명하기 위한 개념일 뿐이라 자바스트립트에서 접근할 수 없습니다. ECMAScript 내부에서만 사용하는 Abstract Operation 입니다.

예를 들어 [[GetOwnProperty]](P)[[함수명]](변수) 형태이기 때문에 Internal method 입니다. [[GetOwnProperty]](P) 는 Internal method 이기 때문에 ECMAScript 문서에는 정의되어 있지만, MDN API 문서 에서는 찾을 수 없습니다.

Internal Methods 만이 아니라 Internal Slots 이라는 개념도 있습니다. Internal Slots 는 Internal Methods 와 비슷하게 [[속성명]] 형식으로 정의되어 있습니다. Internal Slots 은 Object 의 상태 또는 속성을 설명하기 위한 개념입니다. Internal Methods 와 마찬가지로 자바스크립트에서 접근할 수 없습니다.

Internal Methods and Internal Slots 설명 일부
Internal Methods and Internal Slots 설명 일부

Internal Methods 와 Internal Slots 은 ECMAScript 의 정의를 설명하기 위한 개념이기 때문에 자바스크립트 엔진은 ECMAScript 에 정의된 Internal Methods 와 Internal Slots 을 동일한 이름의 함수 또는 클래스로 정의하지 않아도 됩니다. 심지어 구현할지 말지 조차 자바스크립트 엔진이 결정합니다. 자바스크립트 엔진은 ECMAScript 에 정의된 개념과 절차대로만 동작하도록 구현할 뿐입니다. 따라서 ECMAScript 에서는 하나의 Internal Methods 로 정의되어 있지만 자바스크립트 엔진에 따라 구현이 없을 수도 있고 다르게 구현될 수도 있습니다.

'Ordinary' Object vs 'Exotic' Object

ECMAScript 문서에서 말하는 Ordinary Object 는 'essential internal methods' 를 Object 의 공통된 정의대로 구현한 Obejct 를 의미합니다.

ECMAScript 내 Ordinary Object 설명
ECMAScript 내 Ordinary Object 설명

구체적으로 Ordinary Object 를 설명하자면, Ordinary Object 는 [[Prototype]] 이라는 internal slot 을 가져야 하며, [[Prototype]] 의 데이터 값은 null 이거나 상속을 위한 Object 여야 합니다. 그리고 Boolean 값인 [[Extensible]] 은 Object 가 확장 가능한지를 표현하는 internal slot 으로 모든 Ordinary Object 는 동일한 internal slot 을 가집니다. 그리고 모든 Object 는 아래 표와 같은 Essential Internal Methods 를 가집니다.

Internal MethodSignature
[[GetPrototypeOf]]( )  Object | Null
[[SetPrototypeOf]](Object | Null)  Boolean
[[IsExtensible]]( )  Boolean
[[PreventExtensions]]( )  Boolean
[[GetOwnProperty]](propertyKey)  Undefined | Property Descriptor
[[DefineOwnProperty]](propertyKey, PropertyDescriptor)  Boolean
[[HasProperty]](propetyKey) → Boolean
[[Get]](propertyKey, Receiver)  any
[[Set]](propertyKey, value, Receiver)  Boolean
[[Delete]](propetyKey) → Boolean
[[OwnPropertyKeys]]( )  List of propertyKey

Exotic Object 는 Ordinary Object 가 아닌 Object 입니다. Object 이기 때문에 위 표와 같은 Essential Internal Methods 가지고 있습니다. 하지만 Essential Internal Methods 가 일반적인 정의와는 다른 방식으로 동작합니다. 대표적인 Exotic Object 로는 Array 가 있습니다. 자바스크립트에서 Array 는 다른 언어의 배열과는 다르게 동작하며 일반적인 배열의 동작을 흉내내는 Object 입니다. 따라서 Array 는 일반적이지 않고 특수한 Object 입니다.

Completion Records

Specification Types 중 하나인 Completion Records 는 Abstract Operations 가 끝날 때 반환하는 데이터 집합입니다. ECMAScript 에 정의된 모든 함수는 암묵적으로 Completion Records 를 반환합니다. 예를 들어 Abstract Operations 에 정의된 절차 중 다음과 같이 Completion Records 가 아닌듯이 반환한다고 하더라도, Completion Records 를 반환하는 거라 생각하고 ECMAScript 를 읽어야 합니다.

Return "Infinity"

Return NormalCompletion("Infinity")

Abstract Operations 정의에 아무런 반환이 없더라도, 마지막에 Return NormalCompletion(undefined) 가 있다고 생각해야 합니다. 그리고 이 Completion Records 에 대한 ECMAScript 정의때문에 자바스크립트 함수에 return 문이 없어도 undefined 가 반환됩니다.

그런데 ECMAScript 를 편집하는 TC39 내부에서 Abstract Operations 가 암묵적으로 Completion Records 를 반환하는건 문제가 있다고 판단했는지 명시적으로 Completion Records 를 반환하도록 하는 작업을 진행하고 있는 듯합니다.

Completion Records 는 Record 타입이므로 다음과 표와 같은 데이터의 집합으로 이루어져 있습니다.

NameDescription
[[Type]]normal, break, continue, return, 또는 throw 중 하나의 데이터를 가집니다. normal 이 아닌 데이터는 모두 함수를 강제로 중단시켰음을 의미하는 데이터입니다.
[[Value]]함수가 완료되었을 때 생성된 데이터를 가집니다. 예를 들어 반환값이나 예외가 발생했을 때 예외에 대한 데이터를 가집니다.
[[Target]]만약 [[Type]] 이 break 또는 continue 일 때 어디서 중단되었는지를 나타내는 label 데이터를 가집니다.

ReturnIfAbrupt(argument)

ECMAScript 의 Abstract Operations 에 자주 등장하는 물음표 ? 와 느낌표 !ReturnIfAbrupt(argument) 를 짧게 표현한 문법입니다.

ECMAScript 의 Abstract Operations 중 하나인 ReturnIfAbrupt
ECMAScript 의 Abstract Operations 중 하나인 ReturnIfAbrupt

ReturnIfAbrupt(argument) 은 ECMAScript 에 정의된 Abstract Operations 중 하나입니다. argument 로 제공된 Completion Record 의 [[Type]] 값을 검사해서 normal 이면 Completion Record 의 [[Value]] 를 반환하고, 만약 Completion Record 의 [[Type]] 값이 normal 이 아니면 argument 를 반환합니다.

ECMAScript 에서는 아래와 같은 패턴으로 자주 등장하니, ECMAScript 를 읽기 위해서는 반드시 알아둬야 하는 개념입니다.

Let val be ! OperationName()

위의 패턴을 풀어쓰면 다음과 같이 됩니다.

Let val be OperationName().
Assert: val is never an abrupt completion.
If val is a Completion Record, set val to val.[[Value]].

마찬가지로,

? OperationName()

를 풀어서 쓰면 아래와 같이 됩니다.

ReturnIfAbrupt(OperationName())

ECMAScript 내부에서 자주 사용해서 알아둬야 하는 약어

O Ordinary object
PProperty key value
Vlanguage Value
DescProperty Descriptor

참고

How to Read the ECMAScript Specification
Understanding the ECMAScript spec

반응형