ES6

2015년에 발표된 JavaScript의 6번째 표준 명세(ECMAScript 2015)로, let/const, 화살표 함수, 클래스, Promise, 모듈 등 현대 JavaScript의 핵심 문법 대부분이 도입된 가장 큰 변화의 버전입니다.

핵심 개념

항목내용
정식 명칭ECMAScript 2015 (ES2015)
발표2015년 6월 (ECMA International)
이전 버전ES5 (2009년) — 6년 만의 대규모 업데이트
의미현대 JavaScript의 기준점
ES5 (2009) ──── 6년 공백 ──── ES6 (2015) ── ES7 ── ES8 ── ...
                                  │
                          현대 JS의 기준점
                      이후 매년 소규모 업데이트

주요 변경 사항 요약

기능ES5 (이전)ES6 (이후)
변수 선언varlet, const
함수function화살표 함수 =>
문자열'hello ' + name템플릿 리터럴 `hello ${name}`
객체지향프로토타입 직접 조작class 문법
비동기콜백Promise
모듈없음 (CommonJS 등 외부)import / export
구조분해수동 추출구조분해 할당
반복for, for...infor...of, 이터레이터
기본 매개변수수동 체크기본값 지원
컬렉션Object, ArrayMap, Set, WeakMap, WeakSet

주요 문법 상세

1. let / const (블록 스코프)

// X var — 함수 스코프, 호이스팅 문제
var x = 1;
if (true) {
    var x = 2;  // 같은 x를 덮어씀
}
console.log(x);  // 2 (의도치 않은 변경)

// O let — 블록 스코프, 재할당 가능
let y = 1;
if (true) {
    let y = 2;  // 블록 내부의 별도 y
}
console.log(y);  // 1 (외부 y 유지)

// O const — 블록 스코프, 재할당 불가
const PI = 3.14;
PI = 3.15;  // X TypeError

// 단, 객체의 내부 속성은 변경 가능
const user = { name: "홍길동" };
user.name = "김철수";  // O 가능
user = {};             // X 재할당 불가
구분varletconst
스코프함수 스코프블록 스코프블록 스코프
재선언가능불가불가
재할당가능가능불가
호이스팅초기화됨 (undefined)TDZ (에러)TDZ (에러)
// 호이스팅 차이
console.log(a);  // undefined (var는 호이스팅 시 undefined 초기화)
var a = 1;

console.log(b);  // X ReferenceError (TDZ — Temporal Dead Zone)
let b = 2;

2. 화살표 함수

// ES5
var add = function(a, b) {
    return a + b;
};

// ES6 — 화살표 함수
const add = (a, b) => a + b;

// 본문이 여러 줄이면 중괄호 + return 필요
const greet = (name) => {
    const message = `안녕하세요 ${name}님`;
    return message;
};

// 매개변수 1개면 괄호 생략 가능
const double = x => x * 2;

화살표 함수의 핵심 차이는 this 바인딩입니다.

// X 일반 함수 — this가 호출 방식에 따라 변함
const obj = {
    name: "홍길동",
    greet: function() {
        setTimeout(function() {
            console.log(this.name);  // undefined (this = window/global)
        }, 100);
    }
};

// O 화살표 함수 — this가 선언된 위치의 this를 그대로 사용
const obj2 = {
    name: "홍길동",
    greet: function() {
        setTimeout(() => {
            console.log(this.name);  // "홍길동" (상위 스코프의 this)
        }, 100);
    }
};

3. 템플릿 리터럴

const name = "홍길동";
const age = 25;

// ES5
var msg = '이름: ' + name + ', 나이: ' + age + '세';

// ES6 — 백틱(`) + ${표현식}
const msg = `이름: ${name}, 나이: ${age}세`;

// 여러 줄 문자열
const html = `
    <div>
        <h1>${name}</h1>
        <p>${age}세</p>
    </div>
`;

// 표현식 삽입 가능
const result = `합계: ${10 + 20}`;  // "합계: 30"

4. 구조분해 할당 (Destructuring)

// 객체 구조분해
const user = { id: 1, name: "홍길동", age: 25 };

// ES5
var id = user.id;
var name = user.name;

// ES6
const { id, name, age } = user;
const { name: userName, age: userAge } = user;  // 변수 이름 변경
const { id, ...rest } = user;  // rest = { name: "홍길동", age: 25 }

// 배열 구조분해
const arr = [1, 2, 3, 4, 5];

const [first, second] = arr;           // first=1, second=2
const [a, , c] = arr;                  // a=1, c=3 (2번째 건너뜀)
const [head, ...tail] = arr;           // head=1, tail=[2,3,4,5]

// 함수 매개변수에서 구조분해
function printUser({ name, age }) {
    console.log(`${name}, ${age}세`);
}
printUser({ name: "홍길동", age: 25 });

5. 스프레드 / 나머지 연산자 (...)

// 스프레드 — 배열/객체를 펼침
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];  // [1, 2, 3, 4, 5]

const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };  // { a: 1, b: 2, c: 3 }

// 배열 복사
const copy = [...arr1];  // 얕은 복사

// 함수 인자 전달
Math.max(...arr1);  // 3

// 나머지 매개변수 — 여러 인자를 배열로 수집
function sum(...numbers) {
    return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4);  // 10

6. 클래스

// ES5 — 프로토타입 직접 조작
function Animal(name) {
    this.name = name;
}
Animal.prototype.speak = function() {
    return this.name + ' makes a sound';
};

// ES6 — class 문법 (내부적으로는 여전히 프로토타입)
class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        return `${this.name} makes a sound`;
    }
}

// 상속
class Dog extends Animal {
    constructor(name, breed) {
        super(name);        // 부모 생성자 호출
        this.breed = breed;
    }

    bark() {
        return `${this.name} barks`;
    }
}

const dog = new Dog("바둑이", "진돗개");
dog.speak();  // "바둑이 makes a sound"
dog.bark();   // "바둑이 barks"

7. Promise

// ES5 — 콜백
getData(function(data) {
    getMore(data, function(more) {
        // 콜백 지옥...
    });
});

// ES6 — Promise
getData()
    .then(data => getMore(data))
    .then(more => console.log(more))
    .catch(error => console.error(error));

8. 모듈 (import / export)

// math.js — 내보내기
export const PI = 3.14;
export function add(a, b) { return a + b; }
export default class Calculator { /* ... */ }

// app.js — 가져오기
import Calculator, { PI, add } from './math.js';

console.log(PI);         // 3.14
console.log(add(1, 2));  // 3
구분Named ExportDefault Export
개수여러 개 가능파일당 1개
import{ 이름 }이름 자유
용도유틸 함수, 상수메인 클래스/함수

9. Map / Set

// Map — 키-값 쌍 (키에 모든 타입 가능)
const map = new Map();
map.set("name", "홍길동");
map.set(1, "one");
map.set(true, "yes");
map.get("name");  // "홍길동"
map.size;          // 3

// Set — 중복 없는 값의 집합
const set = new Set([1, 2, 3, 3, 3]);
console.log(set.size);    // 3
console.log([...set]);    // [1, 2, 3]
set.has(2);               // true

// 배열 중복 제거
const unique = [...new Set([1, 1, 2, 2, 3])];  // [1, 2, 3]

10. Symbol / Iterator / for...of

// Symbol — 고유한 식별자
const id = Symbol("id");
const user = { [id]: 123, name: "홍길동" };

// for...of — 이터러블 순회
const arr = [10, 20, 30];
for (const value of arr) {
    console.log(value);  // 10, 20, 30 (값을 순회)
}

// for...in과의 차이
for (const key in arr) {
    console.log(key);    // "0", "1", "2" (키/인덱스를 순회)
}

ES6 이후 주요 추가 기능

버전연도주요 기능
ES2016 (ES7)2016Array.includes(), ** 거듭제곱 연산자
ES2017 (ES8)2017async/await, Object.entries()
ES20182018객체 스프레드, Promise.finally()
ES20202020Optional Chaining ?., Nullish Coalescing ??
ES20222022Top-level await, private 필드 #, .at()
// ES2017: async/await
async function fetchUser() {
    const response = await fetch("/api/user");
    return await response.json();
}

// ES2020: Optional Chaining + Nullish Coalescing
const city = user?.address?.city ?? "서울";

// ES2022: private 필드
class Counter {
    #count = 0;       // private
    increment() { this.#count++; }
    get value() { return this.#count; }
}

CSLOG에서 보기