- 기술
- JavaScript
ECMAScript 버전 훑어보기
무슨 글을 쓰려고 하나요?🔗
자바스크립트는 제가 가장 사랑하는 언어이자 모던 웹의 베이스입니다. 이 자바와 이름이 비슷하여 자바스크립트는 오해도 많이 받고, 브라우저 내에서만 사용되던 비운의 언어였지만, 현재는 그 어떤 언어보다 많은 사랑을 받고, 모든 플랫폼을 아우르는 언어로 성장했습니다.
그 배경에는 스크립트 구현체인 JavaScript의 표준이자 규칙인 ECMAScript의 발전이 있었기 때문입니다. 이 글에서는 ECMAScript의 역사를 간략하게 살펴보려 합니다. 과거 버전부터 최신 버전까지, 무엇이 변하고 어떻게 발전해왔는지 함께 살펴봅시다.
ES1, ES2, ES3🔗
탄생과 성장
1997년, JavaScript는 자신의 표준인 ES1을 세상에 선보였습니다. 최초의 ECMAScript는 자바스크립트의 기본 구조를 담고 있었지만, 아직 개선할 점이 많았습니다. 그러나 이 버전이 가진 중요한 의미는, 표준을 통해 프로그래밍 언어의 기반을 닦아준 점입니다.
ES2는 1998년에, ES3는 1999년에 각각 출시되었습니다. ES3에서는 정규 표현식과 try/catch 등 중요한 개념들이 도입되어, 오류 처리와 데이터 검증에 있어서 큰 발전이 있었습니다. 하지만 이런 중요한 추가사항에도 불구하고, 여전히 JavaScript는 더 많은 기능이 필요했습니다.
ES4🔗
야심차지만 빛을 보지못한 버전
ES4는 거창한 계획을 세웠지만, 결국 세상에 공개되지 못하였습니다. 이 버전에서는 타입, 모듈 등 많은 새로운 기능을 추가하려 했지만, 그러한 변화가 너무 컸기 때문에 결국 이는 취소되었습니다. 그러나 이 과정에서 나온 아이디어들은 이후 버전들에게 많은 영향을 끼쳤습니다.
ES5🔗
안정화와 기능의 보완
ECMAScript 5, 흔히 ES5로 알려져 있습니다,는 2009년에 승인되어 널리 사용되고 있으며, ECMAScript의 큰 표준 업데이트 중 하나입니다. 이 버전에서 몇 가지 중요한 기능이 추가되었으며, 아래에 주요 기능에 대해 상세히 설명하겠습니다.
'use strict'🔗
ES5에서 도입된 'use strict'는 코드에 더 엄격한 오류 검사를 적용하는 방법입니다. 이 모드는 JavaScript에 안전하지 않은 동작을 금지하므로, 실수로 전역 변수를 생성하거나, 삭제할 수 없는 속성을 삭제하려고 시도하거나, 변수 또는 매개변수 이름을 중복 사용하는 등의 실수를 방지할 수 있습니다.
JSON 지원🔗
ES5는 JSON 데이터를 직접적으로 처리할 수 있도록 JSON.stringify()와 JSON.parse() 메소드를 도입했습니다. 이전 버전에서는 JSON 데이터를 처리하려면 외부 라이브러리가 필요했지만, ES5에서는 기본적으로 지원하기 때문에 JSON 데이터의 인코딩과 디코딩이 훨씬 간단해졌습니다.
Array 메소드🔗
ES5는 배열 처리를 위한 많은 새로운 메소드를 도입했습니다. 예를 들어, .forEach(), .map(), .filter(), .reduce(), .every(), .some() 등의 메소드를 이용하면, 배열을 다루는 작업이 훨씬 간단해지고 코드의 가독성이 향상됩니다.
Object.defineProperty()🔗
Object.defineProperty()는 객체의 새로운 속성을 직접 정의하거나 이미 있는 객체의 속성을 수정할 수 있게 해주는 메소드입니다. 이 메소드를 이용하면 객체 속성의 get, set 액세서를 설정하거나, 속성을 열거할 수 없도록 설정하는 등의 세부적인 객체 속성 설정이 가능해졌습니다.
ES6/ES2015🔗
이 버전은 JavaScript의 가장 유명한 업데이트입니다. 이전 버전과 비교해서 혁신적인 변화가 많이 일어났고, 이 업데이트 덕분에 편하고 더 안전하게 프로그래밍할 수 있게 된 부분이 많습니다. 다음은 ES6에서 도입된 주요 기능들입니다.
let과 const🔗
ES6에서는 'let'과 'const' 두 가지 새로운 변수 선언 키워드가 도입되었습니다. 'var'와 달리 'let'과 'const'는 블록 스코프를 가지므로, 코드의 가독성과 예측 가능성을 향상시키고 실수를 줄이는데 큰 도움이 됩니다.
화살표 함수 (Arrow Functions)🔗
ES6는 또한 화살표 함수를 도입했습니다. 화살표 함수는 간결한 문법을 제공합니다. 화살표함수의 도입은 복잡한 'this' 개념을 단순화하여 this 바인딩에 대한 혼란을 줄일 수 있게 되었습니다. 일반 함수와 다르게, 화살표 함수는 자신만의 'this'를 생성하지 않으며, 상위 스코프의 'this'를 사용합니다.
클래스 (Classes)🔗
ES6에서 클래스는 객체 지향 패턴을 JavaScript에 더 쉽게 적용할 수 있도록 하는데 있어 핵심적인 역할을 합니다. 이전 버전에서는 복잡한 프로토타입 기반 상속 패턴을 사용해야 했지만, ES6의 클래스를 이용하면 보다 간결하고 직관적인 문법으로 객체 지향 프로그래밍을 구현할 수 있습니다.
Promise🔗
Promise는 비동기 처리를 보다 편리하게 할 수 있도록 도와주는 객체입니다. 이전 버전에서는 비동기 로직을 처리하기 위해 콜백 함수를 사용했지만, 이는 코드가 복잡해지고 가독성이 떨어지는 콜백 지옥을 만들 수 있습니다. ES6의 Promise를 이용하면 비동기 로직을 체인으로 연결하여 간결하고 가독성 좋은 코드를 작성할 수 있습니다.
ES7/ES2016🔗
ES7은 큰 변화를 가져오진 않았지만, 지수 연산자(**)가 추가되었고 Array.prototype.includes 라는 사랑받는 함수도 추가되었습니다.
예를 들어, 이전에는 배열에서 특정 요소의 존재를 확인하기 위해 indexOf를 사용했지만, 이것은 값이 배열에 없을 때 -1을 반환하는 하기 때문에 평가후 비교에 번거로움이 있었습니다. 하지만 이번 버전에서 도입된 includes 메소드를 사용하면, 특정 요소의 존재 여부를 true/false 값으로 간단하게 확인할 수 있게 되었습니다.
ES8/ES2017🔗
Async/Await의 등장
ES8에서는 async/await가 도입되어 비동기 처리를 더욱 편리하게 만들어주었습니다. ES6에서 도입된 Promise는 비동기 처리를 더욱 쉽게 만들어주었지만, 여전히 then 체이닝이 복잡해지고 에러 처리가 어려운 단점이 있었습니다. async/await는 이러한 문제를 해결하고, 비동기 코드를 마치 동기 코드처럼 간결하게 작성할 수 있도록 도와주었습니다.
ES9/ES2018🔗
Rest, Spread 연산자와 비동기 이터레이션
ES9에서는 여러가지 흥미로운 기능들이 추가되었습니다. 그 중에서도 rest와 spread 연산자의 도입은 객체와 배열을 다루는 방법을 바꾸어 주었습니다.
spread 연산자를 사용하면 배열이나 객체의 요소를 쉽게 복사하거나 병합할 수 있습니다. 이전에는 Object.assign()이나 Array.concat()을 사용하여 객체나 배열을 복사하거나 병합해야 했지만, spread 연산자를 이용하면 간단하게 처리할 수 있게 되었습니다.
비슷한 맥락에서 rest 연산자를 이용하면 함수의 인자를 배열로 쉽게 만들 수 있습니다. 이전에는 arguments 객체를 사용해야 했지만, 이 방법은 배열이 아니기 때문에 불편한 점이 있었습니다. rest 연산자를 이용하면 이러한 불편함이 사라집니다.
또한, ES9에서는 비동기 이터레이션과 제너레이터를 도입하였습니다. 이는 비동기 데이터 스트림을 쉽게 다룰 수 있게 해주었습니다.
ES10/ES2019🔗
Array.prototype.flatMap, Object.fromEntries
ES10에서는 여러 유용한 기능들이 추가되었습니다. 그 중에서도 flatMap 메소드와 Object.fromEntries 함수는 개발자들에게 매우 유용한 도구로 인식되었습니다.
flatMap 메소드는 배열의 각 요소에 함수를 적용한 후, 결과를 새로운 배열로 평탄화합니다. 이는 map 메소드와 flat 메소드를 연결하는 것과 동일한 결과를 반환합니다.
Object.fromEntries 함수는 키-값 쌍의 배열을 객체로 변환합니다. 이는 Object.entries 함수와 반대의 작업을 합니다.
ES11/ES2020🔗
BigInt, Promise.allSettled, Nullish Coalescing
BigInt는 JavaScript에서 아주 큰 숫자를 안전하게 다룰 수 있는 새로운 프리미티브 형식입니다. JavaScript의 기존 Number 타입은 IEEE 754 표준을 따르기 때문에 안전하게 다룰 수 있는 가장 큰 정수는 2^53 - 1입니다. 그러나 BigInt를 사용하면 이 제한을 넘어 아주 큰 정수를 안전하게 다룰 수 있습니다.
Promise.allSettled 메소드는 모든 프로미스가 결정되었을 때 (즉, 성공하거나 실패하거나) 완료된 프로미스 배열을 반환합니다. 이전의 Promise.all 메소드는 하나라도 실패하면 즉시 실패하지만, allSettled 메소드는 모든 프로미스가 완료될 때까지 기다립니다.
Nullish Coalescing 연산자 ??는 좌측 피연산자가 null이나 undefined일 때만 우측 피연산자를 반환합니다. 이전에는 || 연산자를 사용하여 비슷한 효과를 낼 수 있었지만, || 연산자는 좌측 피연산자가 falsy한 값일 때도 우측 피연산자를 반환하므로 문제가 발생할 수 있습니다. ?? 연산자를 사용하면 이러한 문제를 피할 수 있습니다.
