ECMAScript

aborile·2023년 3월 31일
0

Basic CS & Web

목록 보기
1/2
post-thumbnail

ECMAScript / Modern JavaScript

ECMAScript

ECMAScript란 ECMA international이라는 국제 표준 기구에서 관리하는 자바스크립트의 표준이다. ECMA-262 기술 규격에 따라 정의된다.

ES6(ES2015)에서 자바스크립트의 발전에 큰 영향을 준 유용한 문법이 많이 등장했다. ECMAScript에 대한 위키백과에서 한 눈에 확인할 수 있는 주요 변화는 다음과 같다.

Modern JavaScript

새로운 문법이 출시되더라도, 브라우저에서 항상 새로운 문법을 완벽하게 지원하는 것이 아니기 때문에 어떤 브라우저에서 어떤 문법을 지원하고 지원하지 못하는지가 관건이 되기도 한다. ES 최신 버전이 등장하더라도 최신 문법을 바로 적용하기보다는 보편적으로 지원되는 범위 내에서 ES버전을 준수하는 것이 일반적이다.

Modern JavaScript라는 명칭에 대해서는 2020 Google Chrome Dev Summit 에서도 언급되었다. (요약 문서)

Modern JavaScript is JavaScript code written in syntax that is supported in all modern browers (Chrome, Firefox, Safari, Edge, Samsung browser, Opera)

즉, 현시점에 사용하기 적합한 범위 내에서 최신 버전의 표준을 준수하는 자바스크립트를 이르는 말로 정의하였다. 해당 영상이 발표된 시점을 기준으로 Chrome, Firefox, Safari, Edge가 90%, Samsung browser, Opera가 5%의 점유율을 차지했고, 95%의 브라우저가 ES2017을 지원, 70%의 브라우저가 ES2021을 지원했다고 한다. 다시 말해, ES2017의 거의 모든 문법은 이미 대다수의 브라우저에서 흔히 사용되고 있으므로, (해당 시점에서) ES2017이 가장 modern syntax에 가깝다고 볼 수 있다.

  • 재밌는 점
    const, let과 같이 호이스팅 이슈를 방지하는 Block Scoping 문법은 명목상 97%의 브라우저가 지원하지만, IE11과 Opera Mini 등 일부 브라우저에서 에러가 발생하므로 실질 지원율은 95%라고 한다.

주요 문법 별 브라우저 지원 현황을 확인할 수 있는 사이트도 있다.

ESNext

ECMAScript는 Ecma international의 여러 기술 위원회(Technial Committee, TC) 중 TC39 라는 위원회가 관리한다. 아직 출시되지 않은 ECMAScript의 준비 버전을 ESNext라 부르며, ESNext는 TC39 Process라 불리는 과정을 통해 제정된다. (허수아비(strawperson) stage와 4개의 stage로 총 5단계로 이루어져 있으며, 각 단계마다 TC39의 승인이 필요하다.)

위 동일 사이트에서 ESNext의 진행 현황도 볼 수 있다.

ECMAScript에 대한 개인적인 감상

사실 JavaScript를 사용한 개발을 처음 해 본 것이 2019년이었고, 심지어 TypeScript로 입문하여서 ES6니 하는 문법에는 크게 관심이 없었다. 그냥 처음 들었을 때 몇 번 찾아보고 '아, 그렇구나. 최신 문법 편하네~' 하는 정도의 안일한 생각 뿐이었다.

그러다 회사에서 최신 ES 문법을 지원하지 않는 브라우저로 인해 버그가 발생한 경험을 몇 번 한 뒤로 새로운 문법을 사용하려고 할 때마다 저도 모르게 움찔하며 경각심이 생기게 되었다. 내가 지금 애용하고 있는 문법 중 어디까지가 ES6 도입이었고 어디부터가 최신 문법에 가까웠을까. 😇

아래는 내가 겪었던 ES문법 지원 여부로 인한 버그들이다. 첫번째, 두번째 사건이 있은 뒤 이 글을 적었고, 세번째 사건은 이 글을 정리해 올리기 전에 겪은, 비교적 최근에 있었던 일이다.

첫번째 사건

특정 형태의 문자열을 대치해야 해서 stackoverlow를 참고하여 lookbehind assertion(?<=..., ES2018 도입)을 사용한 정규표현식을 세워서 코드를 짠 적이 있었는데, 해당 코드를 반영한 업데이트 이후 아이폰에서만 사이트가 아예 터졌었다. 당시에 업데이트 전후로 바뀐 코드가 많아 디버깅을 위해 동료 분들이 많이 애써 주셨는데(ㅠㅠ) 결국 이 정규표현식을 제거하고 다른 방식으로 코드를 수정한 뒤에야 오류를 잡을 수 있었다.

당시, 사파리나 크롬 등의 일반 브라우저가 아닌, '별도 어플의 인앱 브라우저'에서만 우리 사이트에 접속할 수 있었는데, 해당 인앱 브라우저에서 호환성 문제가 있었던 걸로 추정된다. 이 정규표현식을 사용한 함수가 온 페이지의 곳곳에서 사용되고 있어서 사이트에 접속하자마자 바로 에러가 나며 정상적으로 이용할 수 없었던 것...

두번째 사건

위 사건이 있은지 얼마 안 되었을 때의 일로 기억한다. 이번에는 안드로이드에서만 사이트의 특정 페이지가 에러가 나며 표시되지 않는 일이 있었다. 문제는 바로 StringreplaceAll(ES2021 도입) 함수에 있었다. 해당 함수를 replace(/../g, "~") 꼴로 수정하자 정상작동 하였다... (이 뒤로 다시는 replaceAll을 차마 사용하지 못하는 중이다.)

세번째 사건

React Native로 개발한 어플에서 코드푸시를 사용하고 있었는데, 코드푸시 배포 시 갑자기 Unknown Variable이라는 에러가 뜨며 배포가 되지 않았던 적이 있다. 분명 로컬에서 정상작동했는데, 이상한 마음에 에러 로그를 살펴 보니 상수로 선언해 둔 숫자의 numeric separator(_, ES2021 도입)를 변수로 인식해서 에러가 발생하더라... 숫자 사이의 모든 _를 제거하자 바로 성공적으로 배포되었다.

ECMAScript version history

아래는 ES2022까지의 주요 문법을 내가 생각하기에 중요하거나 흥미로웠던 내용 위주로 대강 정리한 내용이다.

~ES5

  • 강력한 정규 표현식, 향상된 문자열 처리, 새로운 제어문 , try/catch 예외 처리, 엄격한 오류 정의, 수치형 출력의 포매팅 등
  • 더 철저한 오류 검사를 제공하고 오류 경향이 있는 구조를 피하는 하부집합인 "strict mode"를 추가
  • 3번째 판의 규격에 있던 수많은 애매한 부분을 명확히 한다.
  • ES5 (2014)
    • JSON Method (JSON.parse, JSON.stringify)
    • String.trim()
    • String.charAt()
    • Array.isArray()
    • Object trailing commas 허용

ES2015 (ES6)

6판에는 클래스와 모듈 같은 복잡한 응용 프로그램을 작성하기 위한 새로운 문법이 추가되었다. 하지만 이러한 문법의 의미는 5판의 strict mode와 같은 방법으로 정의된다. 이 판은 "ECMAScript Harmony" 혹은 "ES6 Harmony" 등으로 불리기도 한다. (위키백과)

ES2016

ES2017

ES2018

ES2019

  • Object.fromEntries obj = Object.fromEntries([['a', 0], ['b', 1]]); // { a: 0, b: 1 }
  • String trimming (trimStart, trimEnd, trimLeft, trimRight)
  • Array flat, flatMap
    const arr1 = [1, 2, [3, 4]];
    arr1.flat();
    // [1, 2, 3, 4]
    
    const arr2 = [1, 2, [3, 4, [5, 6]]];
    arr2.flat();
    // [1, 2, 3, 4, [5, 6]]
    
    const arr3 = [1, 2, [3, 4, [5, 6]]];
    arr3.flat(2);
    // [1, 2, 3, 4, 5, 6]
    
    const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
    arr4.flat(Infinity);
    // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    let arr1 = [1, 2, 3, 4];
    
    arr1.map(x => [x * 2]);
    // [[2], [4], [6], [8]]
    
    arr1.flatMap(x => [x * 2]);
    // [2, 4, 6, 8]
    
    // 한 레벨만 평탄화됨
    arr1.flatMap(x => [[x * 2]]);
    // [[2], [4], [6], [8]]
  • Symbol.description
  • optional catch

ES2020

ES2021

  • String.prototype.replaceAll
  • Promise.any
  • AggregateError
  • WeakReferences (for referring to a target object without preserving it from garbage collection)
  • Logical Assignment Operators (||=, &&=, ??=)
    // "Or Or Equals" (or, the Mallet operator :wink:)
    a ||= b;
    a || (a = b);
    
    // "And And Equals"
    a &&= b;
    a && (a = b);
    
    // "QQ Equals"
    a ??= b;
    a ?? (a = b);
  • numeric separators (_)
    1_000_000_000           // Ah, so a billion
    101_475_938.38          // And this is hundreds of millions
    
    let fee = 123_00;       // $123 (12300 cents, apparently)
    let fee = 12_300;       // $12,300 (woah, that fee!)
    let amount = 12345_00;  // 12,345 (1234500 cents, apparently)
    let amount = 123_4500;  // 123.45 (4-fixed financial)
    let amount = 1_234_500; // 1,234,500
    
    0.000_001 // 1 millionth
    1e10_000  // 10^10000 -- granted, far less useful / in-range...

ES2022

  • top-level await
  • Class field 개선
  • .at() method on the built-in indexables
    const arr = [1, 2, 3]
    arr[-1] // undefined
    arr[arr.length - 1] // 3
    arr.at(-1) // 3
  • Object.hasOwn
  • RegExp flag /d
  • Error.prototype.cause (for Error chaining)

ES2023

References

profile
기록하고 싶은 것을 기록하는 저장소

0개의 댓글