[모던 JavaScript 튜토리얼] 29. 구조 분해 할당(destructuring)

3 분 소요

본문 바로가기


구조 분해 할당은 ES6(ES2015)에서 추가된 문법이다. 구조 분해 할당 구문은 배열이나 객체의 속성을 해체하여, 그 값을 개별 변수에 담게 해주는 표현식이다.


배열 분해하기

let arr = ["Bora", "Lee"];
let [firstName, surname] = arr;

console.log(firstName); // Bora
console.log(surname); // Lee

구조 분해 할당을 이용해, firstName에는 arr[0]을, surname에는 arr[1]을 할당했다.


let [a, b, c] = "abc";
let [one, two, three] = new Set([1, 2, 3]);

할당 연산자 우측엔 모든 이터러블이 올 수 있다.


let user = {};
[user.firstName, user.surname] = "Bora Lee".split(" ");

console.log(user.firstName); // Bora

할당 연산자 좌측엔 할당할 수 있는 어떠한 것이든 올 수 있다.


let user = {
  name: "John",
  age: 30,
};

for (let [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`); // name: John, age: 30
}

Object.entries(obj) 에 구조 분해를 적용하면, 위와 같이 변수에 키, 값을 할당할 수 있다.


let a = 1,
  b = 2,
  c = 3;
[a, b, c] = [c, a, b];

console.log(a, b, c); // 3, 1, 2

구조 분해 할당을 사용하면, 별도의 변수 할당 없이 둘 혹은 그 이상의 변수의 값을 서로 바꿀 수 있다.


…로 나머지 요소 가져오기

let [name1, name2, ...rest] = [
  "Julius",
  "Caesar",
  "Consul",
  "of the Roman Republic",
];

console.log(name1); // Julius
console.log(name2); // Caesar

console.log(rest[0]); // Consul
console.log(rest[1]); // of the Roman Republic
console.log(rest.length); // 2

...를 붙인 매개변수를 하나 추가하면 나머지(rest) 요소를 저장할 수 있다. rest는 배열의 나머지 요소들이 모두 저장된 새로운 배열이다.


기본 값

let [firstName, surname] = [];

console.log(firstName, surname); // undefined undefined

위에서 볼 수 있듯이, 할당하고자 하는 변수의 개수가 분해하고자 하는 배열의 길이보다 크더라도 에러가 발생하지 않고 undefined가 할당된다.


let [name = "Guest", surname = "Anonymous"] = ["Kim"];

console.log(name, surname); // Kim Anonymous

=를 이용하면, 할당할 값이 존재하지 않을 때 기본 값을 설정할 수 있다.


let user = {
  firstName: "Museong",
  surname: "Kim",
};
let [firstName = getName(user), surname = getSurname(user)] = ["Museong"];

console.log(firstName, surname); // Museong Kim

function getFirstName(user) {
  return user.firstName;
}

function getSurname(user) {
  return user.surname;
}

위처럼 함수 호출문을 디폴트 값 할당문에 작성함으로써, 함수가 리턴하는 값을 기본 값으로 설정할 수도 있다.


객체 분해하기

let options = {
  title: "Menu",
  width: 100,
  height: 200,
};
let { title, width, height } = options;
// let { height, title, width } = options;

console.log(title, width, height); // Menu 100 200

객체도 분해할 수 있다. 배열을 분해하는 방법과 동일하다. 변수 이름에 매칭되는 프로퍼티 값을 할당하므로, 위의 주석 처리된 부분을 실행해도 동일한 결과를 얻을 수 있다.


let options = {
  title: "Menu",
  width: 100,
  height: 200,
};
let { width: w, height: h, title } = options;

console.log(title, w, h); // Menu 100 200

혹은 { 객체 프로퍼티 명: 타겟 변수 명 } 의 방식으로, : 뒤에 타겟 변수 명을 지정해줄 수 있다.


let options = {
  title: "Menu",
};
let { width = 100, height = 200, title } = options;

console.log(title, width, height); // Menu 100 200

프로퍼티가 존재하지 않는 경우를 대비해, =을 사용해 디폴트 값을 설정해줄 수 있다. 또한, 콜론(:)과 할당 연산자(=)를 동시에 사용할 수도 있다.


let options = {
  title: "Menu",
  width: 100,
  height: 200,
};
let { height } = options;

console.log(height); // 200

프로퍼티가 많은 경우, 객체에서 원하는 정보만 뽑아올 수도 있다.


…로 나머지 요소 가져오기

let options = {
  title: "Menu",
  width: 100,
  height: 200,
};
let { title, ...rest } = options;

console.log(title); // Menu
console.log(rest); // { width: 100, height: 200 }

배열과 마찬가지로 나머지 개념을 사용할 수 있다. rest는 하나의 객체로써, 나머지 프로퍼티들이 담겨 새로운 객체를 이룬다.


중첩 구조 분해

let options = {
  size: {
    width: 100,
    height: 200,
  },
  items: ["Cake", "Donut"],
  extra: true,
};

let {
  size: { width, height },
  items: [item1, item2],
  title = "Menu",
} = options;

console.log(width, height, item1, item2, title); // 100 200 Cake Donut Menu

배열이나 객체가 다른 배열이나 객체를 포함하는 복잡한 구조의 경우에도 정보를 추출할 수 있다. 이 과정을 중첩 구조 분해(nested destructuring)라고 한다. 구조 분해를 하는 과정에서, sizeitems 같이 실제 객체 내부의 프로퍼티 명에 해당하는 값은 가지지 않는 점을 유의하자.


똑똑한 함수 매개변수

function showMenu(title = "Untitled", width = 200, height = 100, items = []) {
  console.log(`${title} ${width} ${height}`); // My Menu 200 100
  console.log(items); // [ 'Item1', 'Item2' ]
}

showMenu("My Menu", undefined, undefined, ["Item1", "Item2"]);

위처럼 매개변수의 디폴트 값을 사용하기 위해서는 그 인자로 undefined를 전달해야 한다. 그렇지 않으면, 정해진 파라미터의 순서를 어겨, 잘못된 곳에 값을 할당하게 된다. 위 경우보다 파라미터의 개수가 더 많다면, 선택적으로 매개변수를 전달하는 위의 방법은 지저분한 코드로 보일 것이다.


let options = {
  title: "My Menu",
  items: ["Item1", "Item2"],
};

function showMenu({
  title = "Untitled",
  width = 200,
  height = 100,
  items = [],
}) {
  console.log(`${title} ${width} ${height}`); // My Menu 200 100
  console.log(items); // [ 'Item1', 'Item2' ]
}

showMenu(options);

위처럼 전달할 매개변수들을 하나의 객체에 모아 객체 자체를 전달하면, 알아서 구조 분해해 올바른 이름의 매개변수에 할당한다.

댓글남기기