Contents
see ListES2026이란?
ECMAScript 2026(ES17)은 2026년 공식 확정된 JavaScript 표준으로, 개발자들이 오랫동안 요청해온 날짜 처리, 자원 관리, 비동기 패턴 등 실용적인 기능이 대거 포함되었습니다. 이 글에서는 ES2026의 핵심 기능을 코드 예시와 함께 상세히 설명합니다.
1. Temporal API: 드디어 Date를 대체하다
수십 년간 JavaScript 개발자를 괴롭혀 온 Date 객체의 문제를 해결하는 Temporal API가 ES2026에 포함되었습니다. Temporal 객체는 불변(immutable)이며, 타임존과 비그레고리력 달력을 일급 지원합니다.
// 기존 Date의 문제점
const d = new Date(2026, 0, 1); // 월이 0부터 시작하는 혼란
console.log(d.getMonth()); // 0 (1월인데 0을 반환)
// Temporal API - 직관적이고 명확한 API
const today = Temporal.Now.plainDateISO();
console.log(today.toString()); // "2026-04-13"
// 날짜 계산 - 불변 객체라 항상 새 객체 반환
const nextWeek = today.add({ weeks: 1 });
const thirtyDaysLater = today.add({ days: 30 });
console.log(nextWeek.toString()); // "2026-04-20"
console.log(thirtyDaysLater.toString()); // "2026-05-13"
// 타임존 처리
const seoulTime = Temporal.Now.zonedDateTimeISO("Asia/Seoul");
console.log(seoulTime.hour); // 현재 서울 시간의 시
console.log(seoulTime.offset); // "+09:00"
// 두 날짜 사이의 차이 계산
const start = Temporal.PlainDate.from("2026-01-01");
const end = Temporal.PlainDate.from("2026-12-31");
const diff = start.until(end);
console.log(diff.days); // 364
// 날짜 비교
const date1 = Temporal.PlainDate.from("2026-03-15");
const date2 = Temporal.PlainDate.from("2026-04-01");
console.log(Temporal.PlainDate.compare(date1, date2)); // -1 (date1이 이전)
2. Explicit Resource Management: using / await using
파일, DB 연결, 네트워크 스트림 등 자원을 블록 스코프 종료 시 자동으로 정리하는 키워드가 추가되었습니다. 기존의 번거로운 try...finally 패턴을 대체합니다.
// 기존 방식 - try/finally로 수동 정리
let conn;
try {
conn = await db.connect();
const result = await conn.query("SELECT * FROM users");
return result;
} finally {
if (conn) await conn.close(); // 반드시 정리해야 함
}
// ES2026 - using으로 자동 정리 (동기)
class TempFile {
constructor(path) {
this.handle = fs.openSync(path, "r");
}
[Symbol.dispose]() {
fs.closeSync(this.handle); // 블록 종료 시 자동 호출
}
}
{
using file = new TempFile("/tmp/data.txt");
const content = readFromHandle(file.handle);
// 블록 끝에서 자동으로 file[Symbol.dispose]() 호출
}
// 여기서 이미 파일이 닫혀 있음
// ES2026 - await using으로 비동기 자동 정리
class DatabaseConnection {
static async connect(url) {
const conn = new DatabaseConnection();
conn.socket = await openSocket(url);
return conn;
}
async [Symbol.asyncDispose]() {
await this.socket.close(); // 비동기 정리
}
}
async function fetchUsers() {
await using conn = await DatabaseConnection.connect(DB_URL);
return await conn.query("SELECT * FROM users");
// 블록 종료 시 자동으로 conn[Symbol.asyncDispose]() 호출
}
3. Set 메서드 표준화
ES2026에서 Set에 집합 연산 메서드들이 추가되어 수학적 집합 연산을 간편하게 처리할 수 있습니다.
const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5, 6]);
// 합집합 (union)
console.log([...a.union(b)]); // [1, 2, 3, 4, 5, 6]
// 교집합 (intersection)
console.log([...a.intersection(b)]); // [3, 4]
// 차집합 (difference)
console.log([...a.difference(b)]); // [1, 2]
// 대칭 차집합 (symmetricDifference)
console.log([...a.symmetricDifference(b)]); // [1, 2, 5, 6]
// 부분집합 검사
const small = new Set([3, 4]);
console.log(small.isSubsetOf(a)); // true
console.log(a.isSupersetOf(small)); // true
console.log(a.isDisjointFrom(new Set([7, 8]))); // true
4. Array.fromAsync
비동기 이터러블에서 배열을 만드는 편의 메서드입니다.
// 기존 방식 - 번거로운 for-await-of
async function collectStream(stream) {
const chunks = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
return chunks;
}
// ES2026 - Array.fromAsync
async function collectStream(stream) {
return await Array.fromAsync(stream);
}
// 변환 함수와 함께 사용
const numbers = await Array.fromAsync(
asyncNumberGenerator(),
n => n * 2 // 매핑 함수
);
// 실용 예시: API 페이지네이션
async function* fetchAllPages(url) {
let nextUrl = url;
while (nextUrl) {
const res = await fetch(nextUrl);
const data = await res.json();
yield* data.items;
nextUrl = data.nextPage;
}
}
const allItems = await Array.fromAsync(fetchAllPages("/api/products"));
5. Error.isError()
값이 Error 객체인지 신뢰할 수 있게 검사하는 정적 메서드입니다.
// 기존 방식의 문제점 - instanceof는 크로스-realm에서 실패
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const IframeError = iframe.contentWindow.Error;
const err = new IframeError("test");
console.log(err instanceof Error); // false! (다른 realm)
// ES2026 - Error.isError() 사용
console.log(Error.isError(err)); // true (realm 무관)
console.log(Error.isError(new Error())); // true
console.log(Error.isError("error str")); // false
console.log(Error.isError({ message: "" })); // false
// 실용 예시: 에러 핸들러
function handleResult(result) {
if (Error.isError(result)) {
logger.error(result.message, result.stack);
return null;
}
return result;
}
6. RegExp.escape()
사용자 입력 문자열을 정규식에서 안전하게 사용할 수 있도록 특수문자를 이스케이프합니다.
// 기존 방식 - 직접 이스케이프 함수 작성
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
// ES2026 - 내장 RegExp.escape()
const userInput = "(안녕하세요) 가격: $100.00";
const escaped = RegExp.escape(userInput);
// "\(안녕하세요\)\ 가격:\ \$100\.00"
const regex = new RegExp(escaped, "g");
const result = text.match(regex);
// 실용 예시: 검색어 하이라이트
function highlightSearch(text, searchTerm) {
const escaped = RegExp.escape(searchTerm);
const regex = new RegExp(`(${escaped})`, "gi");
return text.replace(regex, "$1");
}
7. Promise.try()
동기/비동기 함수를 통일된 방식으로 Promise로 감쌉니다.
// 기존 방식 - 동기 에러를 Promise.reject로 변환해야 함
function loadConfig(path) {
return new Promise((resolve, reject) => {
try {
const config = JSON.parse(fs.readFileSync(path)); // 동기 에러 발생 가능
resolve(config);
} catch (e) {
reject(e);
}
});
}
// ES2026 - Promise.try()
function loadConfig(path) {
return Promise.try(() => {
const config = JSON.parse(fs.readFileSync(path)); // 동기 에러도 자동 처리
return config;
});
}
// 함수가 비동기든 동기든 동일하게 처리
const result = await Promise.try(mightBeAsyncFn);
마치며
ES2026은 JavaScript 생태계의 오랜 불편함을 해소하는 실용적인 업데이트입니다. 특히 Temporal API는 날짜 처리 라이브러리(day.js, date-fns 등)의 필요성을 크게 줄이고, using 키워드는 자원 누수를 언어 차원에서 방지합니다. 지금 바로 프로젝트에 적용해 보세요.