몸과 마음이 건전한 SW 개발자

[JavaScript] ECMAScript 2022 -- ES2022 본문

프론트엔드/JavaScript

[JavaScript] ECMAScript 2022 -- ES2022

스위태니 2024. 11. 11. 15:46

▶▷ 서론◁◀

  • ES2022의 특징을 살펴보려고 하는데 문제는 정규표현식이 있다는 점이다.
  • 정규표현식에 대해서 잘 모르기 때문에 나중에 정규표현식만 따로 살펴보면 좋을 것 같다.

▶▷ 목차 ◁◀

  1. (Array, String) at
  2. RegExp /d
  3. (Object) hasOwn
  4. error.cause
  5. await import
  6. Class filed declarations
  7. Private methods and fields

1. (Array, String) at ◁◀

1. Array.prototype.at() 메서드

  • at() 메서드는 배열의 인덱스를 기준으로 요소를 반환하는 ES2022에서 도입된 메서드다. [] 표기법과 유사하지만, 음수 인덱스를 사용하여 배열의 끝에서부터 요소에 접근할 수 있는 기능이 있다.

예제 1: at() 메서드로 요소 가져오기

const fruits = ["Banana", "Orange", "Apple", "Mango"];
let fruit = fruits.at(2);
console.log(fruit); // 출력: Apple

 

예제 2: [] 표기법으로 요소 가져오기

const fruits = ["Banana", "Orange", "Apple", "Mango"];
let fruit = fruits[2];
console.log(fruit); // 출력: Apple

 

at() 메서드의 장점

  • 음수 인덱스 지원: at() 메서드는 음수 인덱스를 지원하여 배열의 끝에서부터 요소를 접근할 수 있다.
  • 배열 끝 요소 접근:
const fruits = ["Banana", "Orange", "Apple", "Mango"];
let lastFruit = fruits.at(-1);
console.log(lastFruit); // 출력: Mango

 

[] 표기법과의 차이점

  • [] 표기법은 정수 인덱스만 지원하고, 음수 인덱스는 지원하지 않는다.
  • at() 메서드는 직관적으로 음수 인덱스를 사용할 수 있어 코드 가독성이 높아진다.

2. String.prototype.at() 메서드

const name = "W3Schools";
let letter = name.at(2);
console.log(letter); // 출력: S
let lastLetter = name.at(-1);
console.log(lastLetter); // 출력: s

 2. RegExp /d ◁◀

RegExp의 /d 수정자

  • ES2022에서 새로 추가된 /d 수정자는 정규 표현식의 매치된 문자열의 시작과 끝 위치 정보를 제공한다. 이 수정자는 match 메서드와 함께 사용할 때, 매칭된 부분의 인덱스를 함께 반환하여 시작과 끝 위치를 명확히 알 수 있도록 한다.

예제: /d 수정자를 사용한 매칭

let text = "aaaabb";
let result = text.match(/(aa)(bb)/d);

console.log(result); 
// 출력: [
//   'aabb',
//   'aa',
//   'bb',
//   indices: [
//     [0, 4],  // 'aabb'의 시작과 끝 인덱스
//     [0, 2],  // 'aa'의 시작과 끝 인덱스
//     [2, 4]   // 'bb'의 시작과 끝 인덱스
//   ]
// ]

 

설명

  • /d 수정자는 매칭된 결과에 indices 속성을 추가하여 각 그룹의 시작 및 끝 위치를 반환한다.
  • 이를 통해 문자열 내에서 특정 부분이 어디에서 시작하고 끝나는지를 정확히 파악할 수 있다.

기존 RegExp 수정자와 비교

수정자 설명 예제 사용
i 대소문자 구분 없이 매칭 수행 /abc/i
g 전체 문자열에서 일치하는 모든 부분 찾기 /abc/g
m 여러 줄 매칭 수행 /abc/m
d 부분 문자열 매칭의 시작과 끝 인덱스 반환 (ES2022 신규) /abc/d

 

활용 사례

  • 텍스트 분석: /d 수정자는 매칭된 부분의 위치를 알고 싶을 때 유용하다. 예를 들어, 문서 내 특정 패턴의 위치를 추적하거나 데이터를 분석할 때 사용할 수 있다.
  • 정규 표현식 디버깅: 정규식이 문자열의 어느 부분을 매칭하는지 시각적으로 확인할 수 있다.

 3. (Object) hasOwn ◁◀

Object.hasOwn() 메서드

  • ES2022에서 추가된 Object.hasOwn() 메서드는 객체가 특정 속성을 자체적으로 가지고 있는지를 안전하게 확인할 수 있는 방법을 제공다. 기존의 Object.prototype.hasOwnProperty() 메서드와 비슷하지만, 모든 객체 타입을 지원하며 보다 직관적인 사용법을 제공한다.

사용법

Object.hasOwn(object, property);

 

  • object: 속성을 확인할 객체.
  • property: 확인할 속성의 이름(문자열).

예제

const obj = {
  initProp: "value",
  anotherProp: 42
};

console.log(Object.hasOwn(obj, "initProp")); // 출력: true
console.log(Object.hasOwn(obj, "nonExistentProp")); // 출력: false

 

 

특징

  • 안전성: Object.hasOwn()은 기존의 hasOwnProperty() 메서드와 달리, 프로토타입 체인에 영향을 받지 않고 객체 자체의 속성을 안전하게 확인할 수 있다.
  • 모든 객체 타입 지원: Object.hasOwn()은 모든 객체 타입에서 사용할 수 있어 사용이 더 간단하고 직관적이다.

Object.prototype.hasOwnProperty()와의 차이점

  • 직접적인 메서드 호출: Object.hasOwn()은 Object 객체의 정적 메서드로, 객체 인스턴스의 메서드로 호출할 필요 없이 사용된다.
  • 모던 문법: Object.hasOwn()은 최신 표준에 맞춘 메서드로, 더 짧고 읽기 쉬운 코드를 작성할 수 있다.

기존 메서드와 비교:

// 기존 방식
console.log(obj.hasOwnProperty("initProp")); // 출력: true

// 새로운 방식
console.log(Object.hasOwn(obj, "initProp")); // 출력: true

 4. error.cause ◁◀

Error.cause 속성

  • ES2022는 오류를 던질 때, 해당 오류의 원인을 명확하게 지정할 수 있도록 error.cause 속성을 도입했다. 이를 통해 오류를 디버깅하거나 문제를 추적할 때 추가적인 맥락을 제공할 수 있다.

사용법

오류 객체를 생성할 때 cause 옵션을 사용하여, 다른 오류나 원인 정보를 추가할 수 있다.

throw new Error("에러 메시지", { cause: 원인 });

 

예제

function connectData() {
  // 오류가 발생했다고 가정
  throw new Error("Unable to connect to the database");
}

try {
  connectData();
} catch (err) {
  throw new Error("Connecting failed.", { cause: err });
}

 

설명

  • connectData() 함수에서 오류가 발생하여 catch 블록으로 넘어간다.
  • catch 블록에서는 새 Error 객체를 생성하면서 cause 옵션에 원래 오류 err를 추가한다.
  • 새 Error 객체를 던질 때 cause 속성을 통해 원래 오류를 포함시킴으로써, 오류의 근본적인 원인을 함께 전달할 수 있다.

Error.cause 출력 예제

try {
  connectData();
} catch (err) {
  console.error(err.message); // 출력: Connecting failed.
  console.error(err.cause);   // 출력: Error: Unable to connect to the database
}

 

특징 및 장점

  • 디버깅에 유용: cause 속성은 오류의 원인을 명확하게 전달하여 오류의 근본적인 이유를 쉽게 파악할 수 있다.
  • 오류 체인링: 하나의 오류가 다른 오류에 의해 발생한 경우, 오류의 원인을 체인링하여 디버깅 시 유용한 정보를 제공한다.

 5. await import ◁◀

await import

  • await import는 JavaScript 모듈 시스템에서 동적 모듈 로딩을 지원하여, 코드 실행 시 필요한 모듈을 비동기적으로 가져올 수 있게 한다. 이 기능은 ES2020에서 도입된 동적 import() 함수와 await 키워드를 결합하여 사용된다. 이를 통해 모듈을 로드하는 동안 JavaScript 코드가 해당 모듈을 기다릴 수 있다.

사용법

  • await import를 사용하면 모듈이 비동기적으로 로드될 때까지 코드 실행을 일시 중지하고, 로드가 완료되면 실행을 재개할 수 있다. 모듈을 동적으로 가져올 때 매우 유용하다.

예제:

// 모듈을 비동기적으로 가져오기
const { myData } = await import('./myData.js');

// 가져온 모듈 사용
const data = myData();
console.log(data);

 

특징

  • 비동기 로딩: await import는 동적으로 필요한 모듈을 로드하여, 페이지 로드 속도나 성능에 최적화할 수 있다.
  • 코드 분할: 애플리케이션이 필요할 때만 특정 모듈을 가져올 수 있으므로, 코드 분할 및 성능 최적화에 유용하다.
  • 사용 시점: await는 async 함수 안에서만 사용할 수 있으며, 모듈이 로드되기 전까지 기다렸다가 로드가 완료되면 코드 실행을 재개한다.

주의사항

  • 최상위 await: ES2022부터 최상위 await 기능이 추가되어, 모듈의 최상위 레벨에서도 await를 사용할 수 있다. 이를 통해 async 함수 내부가 아니더라도 모듈을 기다릴 수 있다.

 6. Class filed declarations ◁◀

JavaScript 클래스 필드 선언

  • JavaScript에서 클래스 필드 선언은 ES2022에서 표준화되어, 클래스 내에서 필드를 직접 선언할 수 있는 기능을 제공한다. 클래스 필드는 생성자 외부에서도 클래스 내에 필드를 정의할 수 있으며, 이를 통해 클래스 인스턴스의 속성을 더 간단하고 직관적으로 설정할 수 있다.

예제

class Hello {
  counter = 0; // 클래스 필드 선언
}

const myClass = new Hello();
let x = myClass.counter;

console.log(x); // 출력: 0

 

설명

  • counter는 Hello 클래스의 인스턴스가 생성될 때 초기화되는 클래스 필드다.
  • 클래스 필드는 생성자 함수 바깥에서 직접 선언할 수 있으며, 인스턴스가 생성될 때마다 해당 필드가 초기화된다.
  • 이를 통해 초기화 코드가 생성자에 종속되지 않고 클래스 구조 내에서 명확하게 정의된다.

특징 및 장점

  • 더 깔끔한 코드: 생성자 내부에서 초기화할 필요 없이 클래스 내에서 필드를 바로 정의할 수 있다.
  • 가독성 향상: 클래스의 속성 정의와 초기화가 클래스 바깥에서 한눈에 보이기 때문에 가독성이 향상된다.
  • 인스턴스별 초기화: 각 인스턴스가 생성될 때 필드가 새롭게 초기화된다.

기본 클래스 필드 초기화 예제

class Person {
  name = 'John'; // 클래스 필드 선언
  age = 30;      // 클래스 필드 선언
}

const person1 = new Person();
console.log(person1.name); // 출력: John
console.log(person1.age);  // 출력: 30

 7. Private methods and fields ◁◀

JavaScript 비공개 메서드 및 필드

  • ES2022는 클래스 내에서 비공개 필드와 메서드를 정의할 수 있는 기능을 도입했다. 비공개 필드와 메서드는 클래스 외부에서 직접 접근할 수 없으며, 클래스 내부에서만 사용할 수 있도록 보호된다. 이러한 필드는 # 기호로 선언된다.

예제

class Hello {
  #counter = 0;  // 비공개 필드
  #myMethod() {  // 비공개 메서드
    console.log('This is a private method');
  }

  publicMethod() {
    this.#myMethod(); // 비공개 메서드 호출
  }
}

const myClass = new Hello();

// 비공개 필드 및 메서드에 외부에서 접근하려고 할 때
let x = myClass.#counter; // 오류: Private field '#counter' must be declared in an enclosing class
myClass.#myMethod();      // 오류: Private method '#myMethod' is not accessible outside class 'Hello'

// 비공개 메서드 호출을 포함한 공개 메서드는 정상 작동
myClass.publicMethod();   // 출력: This is a private method

 

설명

  • 비공개 필드와 메서드는 클래스 외부에서 직접 접근하거나 수정할 수 없다.
  • # 기호로 시작하여 비공개로 선언되며, 클래스 내부에서만 접근할 수 있다.
  • 비공개 필드는 외부에서 접근할 경우 SyntaxError를 발생시킨다.

장점

  • 캡슐화: 클래스 내부 구현 세부 사항을 외부에서 숨길 수 있어 캡슐화가 강화된다.
  • 보안성: 외부에서 클래스의 내부 상태를 변경하지 못하도록 방지할 수 있어 코드의 안정성과 무결성을 유지할 수 있다.

특징

  • 비공개 필드와 메서드는 ES2022에서 도입되었으며, JavaScript 엔진은 이러한 비공개 멤버를 안전하게 관리한다.
  • 클래스 내부에서만 비공개 필드와 메서드에 접근할 수 있으므로 클래스 외부에서 코드의 수정 가능성을 줄여 안전성을 높인다.