당신이 JS 개발자라면 반드시 알아야 할 ES2022 신규 기능 7가지
시작
안녕하세요, GDSC UOS FE팀에서 코어 멤버로 활동하고 있는 이명재입니다.
지난 6월 22일, ECMAScript 2022가 정식 스펙으로 채택되었습니다. FE 개발자로서 떼려야 뗄 수 없는 Javascript의 새 소식이기에, 언박싱하는 느낌으로 살펴보려고 합니다.
Javascript는 아는데, ECMAScript는 뭔가요?
수 년 전의 웹 시장은 춘추전국시대로 비유될 만큼 다양한 브라우저들이 각자 본인들만의 스크립트 언어가 존재하는 혼돈의 시기였습니다. 이때의 웹 개발은 각 브라우저에서 동작할 수 있게끔 같은 기능을 다른 언어로 여러 번 작성해야 하는 끔찍한 일이었습니다. 이를 해결하고자 Netscape는 ECMA 학회에 Javascript 표준안을 제시하였고, 그렇게 ECMAScript라는 Javascript 표준안이 세상에 등장하게 됩니다. 어쩌구 저쩌구 중간에 IE가 말을 안 듣는 바람에 JQuery 등 돌연변이가 등장하고 결국 Chrome이 천하 통일하는 이야기
ECMAScript(이하 ES) 1은 1997년에 출시된 이후로 버전 업데이트가 느렸지만 2009년의 ES5와 2015년의 ES6에 대거 업데이트가 되면서 현재 우리가 사용하고 있는 Javascript(이하 JS)의 대부분의 기능이 생겼고, 2015년 이후로는 1년에 한 번씩 버전 업데이트가 이루어지고 있습니다.
ES 2022의 새로운 기능
Class: private, static
우리가 알고 있는 class는 ES6에 추가된 비교적 최신 문법입니다.
JS는 애초에 객체지향 언어로 설계된 것이 아니기 때문에, 겉모습만 class일 뿐 내부적으로는 prototype이라는 기존 객체지향 언어들과는 다른 방식으로 동작해 객체지향을 흉내냅니다. 그래서인지 private이나 static 같은 class 문법은 TypeScript에만 존재했습니다. 이 두가지가 모두 ES2022에 추가되었습니다! private은 #
으로, static은 그대로 static
을 사용해 명시합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MyClass {
instancePublicField = 1;
static staticPublicField = 2;
#instancePrivateField = 3;
static #staticPrivateField = 4;
#nonStaticPrivateMethod() {}
get #nonStaticPrivateAccessor() {}
set #nonStaticPrivateAccessor(value) {}
static #staticPrivateMethod() {}
static get #staticPrivateAccessor() {}
static set #staticPrivateAccessor(value) {}
static {
// Static initialization block
}
}
// 코드 출처: https://2ality.com/2022/06/ecmascript-2022.html
in 연산자
기존 in
연산자는 속성이 객체에 존재하는 지 여부를 반환했습니다. 다만 private 필드에 대해서는 오류를 내뱉었는데요, in
연산자에 private 필드가 있는지 판단할 수 있게 되었습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass{
#instancePrivateField;
static hasIPF(obj) {
return #instancePrivateField in obj;
}
}
const a = new MyClass();
const b = {};
MyClass.hasIPF(a); // true
MyClass.hasIPF(b); // false
Object.hasOwn()
어떤 객체에 특정 이름의 속성(key)이 있는 지 판별하는 메소드로 Object.hasOwn
이 있었고, Object.hasOwnProperty
를 사용하도록 권장되었었습니다. 그러나 ES2022로 오면서 Object.hasOwn
에 class의 상속 관계에서 부모 class의 속성은 포함하지 않고 오로지 자체 속성만 검사하는 기능이 생겼습니다.
어쩌면 in
연산자와 비슷할 수 있는데, in
연산자는 부모 class의 속성까지 포함해서 검사한다는 차이점이 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
class Parent {
parentField = 1;
};
class Child extends Parent {
childField = 1;
};
const child = new Child();
'parentField' in child; // true
Object.hasOwn('parentField', child); // false
Top-Level await
비동기 처리를 할 때 사용하는 await
은 항상 async
함수의 하위에서만 사용이 가능했습니다. 그런데 모듈 자체를 async
로 정의하는 방법이 없어 최상위에서는 await
을 사용할 수 없었는데, ES2022부터는 최상위에서 await
을 사용할 수 있게 되었습니다.
1
2
import { getData } from '../apis/data';
const data = await getData;
Error.cause
기존 Error Handling은 Error
객체에 메시지를 담는 것이 전부였습니다. 이제는 Error
를 생성할 때, cause
속성에 접근해 조금 더 정확한 처리가 가능해졌습니다.
1
2
3
4
5
6
7
8
const err1 = new Error("Can't save comment", { cause: "Not allowed." });
const err2 = new Error("Can't save comment", { cause: "Post not found." });
const err3 = new Error("Can't save comment", { cause: "Database is full." });
err1.message; // Can't save comment
err1.cause; // Not allowed.
// 코드 출처: 노마드코더(https://www.youtube.com/watch?v=m-R7s7fnwvU)
.at()
JS가 다른 고급 언어에 비해 불편한 점 중 하나를 꼽으라면 저는 음수 인덱스를 꼽습니다. 대괄호 연산자에 추가되면 좋았겠지만, .at()
메소드에 추가되었습니다.
1
[1, 2, 3, 4, 5].at(-1); // 5
RegExp match indicies
정규식에서는 소괄호를 이용해 group
을 표시할 수 있습니다.
정규식 끝에 /d
플래그를 추가하면 indices
라는 각 group
의 시작과 끝 index를 나타내는 속성을 사용할 수 있게 되었습니다.
1
2
3
const regExp = /(a+)(b+)/d.exec('aaaabb'); // 'aaaabb', 'aaaa', 'bb'로 나눔
rexExp.indices // [[0, 6], [0, 4], [4, 6]]
마치며
새롭게 추가된 기능들을 살펴보면서 개인적으로는 JS의 좀 더 객체지향적으로, 고급 언어 쪽으로 가까워지려는 노력이 느껴졌습니다. 아마 이 부분은 객체지향이 익숙한 대다수의 개발자의 니즈를 충족하기 위함이 아닐까라는 생각이 듭니다.
그도 그럴 것이, 현재 ECMAScript를 설계하고 있는 TC39라는 기술 위원회는 우리가 흔히 알고 있는 A사
G사
M사
등등이 포함되어있다고 합니다.
FE는 정말 끊임없는 변화를 받아들여야 하는 분야라는 것을 새삼 다시 느끼며, 언젠가는 우리도 TC39에 기능을 제안해 이름 한 줄 남길 수 있는 순간을 상상하면서 이번 글을 마치려고 합니다. 읽어주셔서 감사합니다!
참고자료