본문 바로가기
dev/javascript

[javascript] 자바스크립트 객체 디스트럭처링 (destructuring)

by 최연탄 2023. 5. 30.
728x90
반응형

참고: https://dmitripavlutin.com/javascript-object-destructuring/

객체 디스트럭처링은 객체에서 속성을 가져오고 변수에 바인딩하는 JavaScript의 유용한 기능입니다. 또한 디스트럭처링은 코드 한 줄로 여러 속성을 추출하고 중첩된 객체의 속성에 접근할 수 있으며 속성이 존재하지 않을 경우 기본 값을 할당할 수 있습니다. 이 포스트에서는 JavaScript에서 디스트럭처링을 사용하는 방법을 알아보겠습니다.

1. 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 변수에 할당했습니다. "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;

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

2. 속성 추출 방법

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

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 속성의 값으로 초기화합니다.

3. 여러개의 속성 추출 방법

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

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을 생성하고 각각의 속성에 해당하는 값을 할당합니다.

4. 속성이 없을 경우 기본 값

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

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

const { enemies } = hero;

console.log(enemies);

디스트럭처링 후 변수 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);

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

5. 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);

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

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

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

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);

7. 동적 속성 추출

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

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);

8. 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);

9. 일반적인 사용 사례

9.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);
}

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

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

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

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

console.log(names);

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

10. 정리

객체 디스트럭처링은 객체에서 속성을 추출하고 그 값을 변수에 바인딩하는 강력한 기능입니다. 간결한 구문과 하나의 명령문으로 여러 변수를 가져오는 기능은 매우 유용합니다.

관련 글

자바스크립트 루프 사용 방법 (for...of)

자바스크립트 map 사용 방법

자바스크립트 스프레드 연산자 (spread operator)

반응형

댓글