디스트럭처링 (destructuring) 자바스크립트 표현식

원본: 자바스크립트의 객체 디스트럭처링 사용 방법

객체 디스트럭처링은 객체에서 속성을 가져오고 변수에 바인딩하는 자바스크립트의 유용한 기능입니다.

또한 디스트럭처링은 코드 한 줄로 여러 속성을 추출하고 중첩된 객체의 속성에 접근할 수 있으며 속성이 존재하지 않을 경우 기본 값을 할당할 수 있습니다.

이 포스트에서는 자바스크립트의 디스트럭처링을 사용하는 방법을 알아보겠습니다.

디스트럭처링 표현식의 필요성

ES2015 이전 환경에서 객체의 속성을 가져오려면 다음과 같은 코드를 작성해야 합니다:

var hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

var name = hero.name;
var realName = hero.realName;

console.log(name);
console.log(realName);

위의 예제에서는 속성 hero.name의 값을 name 변수에 할당하고 hero.realName의 값을 realName 변수에 할당 후 console.log() 메소드를 통해 콘솔에 출력했습니다.

여기서 “var name = hero.name”을 작성할 때 name을 두 번이나 언급해야하고 realName의 경우도 마찬가지 입니다.속성에 접근하고 변수에 속성을 할당하려면 상용구를 사용해야 합니다.

이런 상황이 바로 객체 디스트럭처링이 필요한 부분입니다. 이는 속성 명을 중복해서 쓰지 않고 속성 값을 읽어 변수에 할당할 수 있습니다. 또한 코드 한 줄로 동일한 객체에서 여러 개의 속성을 읽어낼 수 있습니다.

위의 예제 스크립트를 리펙토링하여 속성 name과 realName을 가져올 때 디스트럭처링을 적용해 보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { name, realName } = hero;

console.log(name);
console.log(realName);

“const { name, realName } = hero” 이 구문이 객체 디스트럭처링입니다. 이 구문은 name 및 realName 변수를 정의한 다음 그에 따른 hero.name 및 hero.realName 속성의 값을 변수에 할당합니다.

다음은 객체의 속성을 가져오는 두 가지 접근법의 비교입니다:

const name = hero.name;
const realName = hero.realName;

// 동일한 기능을 하는 코드

const { name, realName } = hero;

속성 이름이나 객체 변수를 중복으로 입력하지 않아도 되기 때문에 객체 디스트럭처링이 더 편리하다는 것을 알 수 있습니다.

객체의 속성 추출 방법

객체 디스트럭처링의 문법은 아주 간단합니다:

const { identifier } = expression;

여기서 identifier는 가져올 속성의 이름이고 expression은 객체입니다. 디스트럭처링 후에는 변수 identifier에 속성의 값이 할당됩니다.

기존의 속성 접근자를 사용하는 동일한 코드는 다음과 같습니다:

const identifier = expression.identifier;

이제 개발자 도구를 열고 실제 사용 예제를 살펴보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { name } = hero;

console.log(name);
디스트럭처링 예제

“const { name } = hero” 구문은 변수 이름을 정의하고 hero.name 속성의 값으로 초기화합니다.

여러 속성 추출 방법

디스트럭처링을 사용하여 객체의 여러 속성을 가져오려면 변수 이름을 쉼표로 구분해 나열하면 됩니다:

const { identifier1, identifier2, ..., identifierN } = expression;

identifier1, identifier2, …, identifierN은 가져올 속성의 이름이고 expression은 객체입니다. 디스트럭처링이 끝나면 각각의 변수에 각각의 속성 값이 할당됩니다.

다음은 기존에 쓰던 동일한 코드입니다:

const identifier1 = expression.identifier1;
const identifier2 = expression.identifier2;
// ...
const identifierN = expression.identifierN;

두 개의 속성을 추출했던 첫 번째 섹션의 예제를 다시 한번 살펴보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { name, realName } = hero;

console.log(name);
console.log(realName);
디스트럭처링 예제

“const { name, realName } = hero” 구문은 두 개의 변수 name과 realName을 생성하고 각각의 속성에 해당하는 값을 할당합니다.

속성이 존재하지 않는 경우

만일 디스트럭처링할 객체에 해당 속성이 존재하지 않는다면 변수에는 undefined가 할당됩니다. 다음 예제를 보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { enemies } = hero;

console.log(enemies);
속성이 존재하지 않는 예제 1

디스트럭처링 후 변수 enemies의 값은 undefined가 됩니다. 왜냐하면 hero 객체에는 enemies라는 속성이 없기 때문입니다. 여기서 객체에 해당 속성이 없을 경우 기본 값을 설정할 수 있습니다:

const { identifier = defaultValue } = expression;

identifier는 속성의 이름이고 expression은 객체입니다. 디스트럭처링 후에 변수 identifier에 객체의 속성을 전달하지만 속성이 없는 경우 defaultValue를 할당합니다.

다음은 기존에 쓰던 동일한 코드입니다:

const identifier = (expression.identifier === undefined) ? defaultValue : expression.identifier;

위의 예제를 수정하여 기본 값을 넣어 보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { enemies = ['Joker'] } = hero;

console.log(enemies);
속성이 존재하지 않는 예제 2

이제 변수 enemies에 undefined 대신 [‘Joker’]가 들어갔습니다.

디스트럭처링 alias

디스트럭처링에서 속성의 이름과 다른 이름의 변수를 만들고 싶다면 앨리어스(별칭) 기능을 사용할 수 있습니다.

const { identifier: aliasIdentifier } = expression;

identifier는 가져올 객체의 속성 이름이고 aliasIdentifier는 코드에서 사용할 변수 이름, expression은 객체 입니다. 디스트럭처링 후에 aliasIdentifier에 expression.identifier 값이 할당됩니다.

다음은 기존의 동일한 코드입니다:

const aliasIdentifier = expression.identifier;

다음은 객체 디스트럭처링의 별칭 기능 예제입니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const { realName: secretName } = hero;

console.log(secretName);
디스트럭처링 alias 예제

위 코드의 “const { realName: secretName } = hero” 구문을 보면 새 변수 이름 secretName을 정의하고 여기에 hero.realName의 값을 할당했습니다.

중첩된 객체의 속성 가져오기

앞선 예제에서의 객체는 속성이 모두 기본 데이터 타입인 일반적인 객체였습니다. 그러나 객체는 다른 객체를 속성으로 가질 수도 있습니다. 디스트럭처링은 이러한 경우에도 사용할 수 있습니다. 다음은 기본 문법입니다:

const { nestedObjectProp: { identifier } } = expression;

nestedObjectProp이 expression 객체의 속성 이름이고 이 속성이 다른 객체를 가지고 있으면 그 객체의 속성 이름인 identifier로 중첩된 객체 속성의 값을 가져올 수 있습니다.

다음은 기존의 코드입니다:

const identifier = expression.nestedObjectProp.identifier;

디스트럭처링으로 가져올 수 있는 객체의 중첩 레벨은 제한이 없습니다. 엄청 많이 중첩된 객체에서 값을 가져오고 싶다면 다음과 같이 하면 됩니다:

const { propA: { propB: { propC: { .... } } } } = object;

예를 들어 hero 객체가 { city: ‘Gotham’ } 이라는 객체를 가지고 있다면:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne',
  address: {
    city: 'Gotham'
  }
};

const { address: { city } } = hero;

console.log(city);
중첩 객체의 속성 가져오기

동적 속성 추출

디스트럭처링으로 가져올 속성의 이름을 동적으로 지정할 수도 있습니다(예: 속성 이름이 런타임에 결정되는 경우):

const { [propName]: identifier } = expression;

[propName] 표현식이 객체에서 가져올 속성 이름입니다. identifier는 디스트럭처링 후 사용할 변수의 이름입니다.

다음은 기존의 동일한 코드입니다:

const identifier = expression[propName];

다음의 사용 예제를 보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne'
};

const prop = 'name';
const { [prop]: name } = hero;

console.log(name);
디스트럭처링 동적 속성 추출

디스트럭처링 rest object

rest 문법은 디스트럭처링 후에 남은 나머지 속성을 가져오고자 할 때 유용합니다:

const { identifier, ...rest } = expression;

identifier는 expression에서 가져올 속성의 이름이고 변수 rest에는 identifier 속성이 아닌 나머지 속성이 들어갑니다.

예를 들어 객체에서 name과 나머지 속성을 모두 가져오는 코드를 보겠습니다:

const hero = {
  name: 'Batman',
  realName: 'Bruce Wayne',
  company: 'WayneCorp'
};

const { name, ...rest } = hero;

console.log(rest);
디스트럭처링 rest object

디스트럭처링 사용 예제

1. 속성을 변수로 바인딩

위의 다양한 예제에서 봤듯이 디스트럭처링은 속성의 값을 변수로 바인딩합니다. 여기서 변수는 const, let, var, 심지어 이미 정의된 변수로 선언할 수 있습니다.

예를 들면 다음은 let 구문을 사용한 코드입니다:

const hero = {
  name: 'Batman',
};

let { name } = hero;

console.log(name);

변수를 var로 선언해도 됩니다:

const hero = {
  name: 'Batman',
};

var { name } = hero;

console.log(name);

그리고 이미 선언된 변수를 사용할 수도 있습니다:

let name;

const hero = {
  name: 'Batman',
};

({ name } = hero);

console.log(name);

for…of 루프에서 속성을 바로 사용하려면 다음과 같이 작성할 수 있습니다:

const heroes = [
  { name: 'Batman' },
  { name: 'Joker' }
];

for (const { name } of heroes) {
  console.log(name);
}
디스트럭처링 예제

2. 함수의 매개변수 디스트럭처링

객체 디스트럭처링은 값의 할당이 일어나는 어떤 부분에도 사용할 수 있습니다. 예를 들면 디스트럭처링을 함수의 매개변수 부분에 바로 사용할 수 있습니다:

const heroes = [
  { name: 'Batman' },
  { name: 'Joker' }
];

const names = heroes.map(
  function({ name }) {
    return name;
  }
);

console.log(names);
함수의 매개변수 디스트럭처링

“function({ name })”은 매개변수로 받은 객체에 바로 디스트럭처링하여 객체의 name 속성을 바로 가져옵니다.

정리

객체 디스트럭처링은 객체에서 속성을 추출하고 그 값을 변수에 바인딩하는 강력한 기능입니다.

간결한 구문과 하나의 명령문으로 여러 변수를 가져오는 기능은 매우 유용합니다.

관련 글