본문으로 바로가기

이 글은 [인프런] Javascript ES6+ 제대로 알아보기 - 초급(정재남)를 토대로 작성되었음을 알려드립니다.


destructuring assignment는 한 마디로 정의하기 어렵다고 합니다.
용어에 대한 번역이 여전히 뜨거운 감자로 의견이 분분한 가운데 구조분해 할당란 용어에 무게가 실리고 있지만 책마다 제각기 다른 용어들을 사용하고 있기 때문에 유사한 용어들로 쓰이고 있다라는 정도만 숙지하고 의사소통하는 데에 유사한 용어를 사용하면 크게 문제될 것은 없을 것입니다.

 

 

destructuring assignment

여기서는 위에서 언급한 여러 용어들 중에 혼동을 줄이고자  해체할당이란 용어를 사용해 이 문법에 대해 살펴보도록 하겠습니다.

 

해체 할당이란?

해체 할당이란 말 그대로  해체하였다가 해체했던 것을 모두 할당을 한다란 의미입니다.

위 용어 중에  구조분해할당도 역시 구조를 분해하였다가 분해했던 것을 할당한다란 뜻이기 때문에  해체할당과 의미적으로 일맥상통한다고 할 수 있습니다.

 

 

배열 해체할당

위에서 언급한 의미를 코드를 통해 알아보도록 하겠습니다.

js
var colors = ['red', 'white', 'orange'];
var first = colors[0];
var second = colors[1];
var third = colors[2];

console.log(first, second, third)

기존 ES5 에서 배열 요소 하나하나를 위와 같이 접근하여 사용했다면 ES6 는 아래와 같이 할 수 있습니다.

js
var colors = ['red', 'white', 'orange'];
var [ first, second, third ] = colors;

console.log(first, second, third);

위 예제를 분석해 보자면  colors 의 내용들을 모두 펼쳐서(해체)  대괄호([ ]) 안의 각각의 변수 하나하나에 다시 할당한다란 의미입니다.

js
var colors = ['red', 'white', 'orange'];
const [ first, second, third ] = colors;

console.log(first, second, third);

first = 10; // Assignment to constant variable.

로그를 확인해 보면  const 또는  let 으로 변수를 선언한 방식에 따라서 대괄호 안에 있는 변수들이 영향을 받는 것입니다.
즉, 위 예제의  ES5 코드와 해체할당 코드는 완전히 동일한 문장이라고 할 수 있습니다.

 

발췌하기

해체할당의 장점은  원하는 것만 할당할 수 있다는 것입니다.

js
var colors = ['red', 'white', 'orange'];
let [ , second ] = colors;
let [ , , third ] = colors;

console.log(second);
console.log(third);

let [ first ] = ['red', 'white', 'orange'];
console.log( first );

우측에서 좌측 방향으로 펼쳐서 할당하는데 오른쪽에 있는 것들을 그대로 매칭해서 하나하나 할당하는 것이 destructuring assignment 입니다.

매칭할 대상이 없다면 undefined 가 할당된다.

js
const colors = ['red', 'white', 'orange']
const [ , , third, fourth] = colors
console.log(third)

 

배열 해체할당 활용

1)  rest parameter 와의 연동

js
const arr = [1, 2, 3, 4, 5];
const [ a, ...b ] = arr;
const [ , , ...c ] = arr;

console.log(a, b, c);

 

2)  default parameter 와의 연동

js
const [a = 10, b = 20] = [undefined, 5];
console.log( a, b );

위 코드를 풀이하자면 해체하여 할당하려고 하는데  a 에 값이 없으면  10으로 하고,  b에 값이 없으면  20 으로 한다는 의미입니다.

js
 const [c, d = c * 2] = [5];
console.log( c, d );
js
const [e = f, f] = [undefined, 10];

분석해 보면  e 에 해체할당하여  undefined 이기 때문에  default parameter로 호출이 되어  f 를 보니 뒤에 선언한  f 를 가지고 할당하려고 하니  TDZ 영역에 걸려 에러가 발생하게 됩니다.

 

3)  다차원 배열에서의 동작

js
const arr = [1, [2, [3, 4], 5], 6];
const [a, [b, [ , c], ], d] = arr;
const [e, [f], g] = [1, [2, [3, 4], 5], 6];

console.log(a, b, c, d);
console.log( e, f, g );

배열이 있는데 배열 안에 배열이 있고 또 그 안에 배열이 있는 다차원배열에서도 똑같이 매칭해 주면 위와 같이 추출되는 해체할당을 할 수 있습니다.

 

4)  값 교환하기

js
var a = 10;
var b = 20;
var temp = a;

a = b;
b = temp;

console.log(a, b)

기존에는  a 와  b의 값을 서로 바꾸고 싶을 경우(예제에서 a = 20, b = 10)에 임시로 변수 하나를 만든 후 바꿔치기할 값 중에 하나를 저장해 놓고 할당하는 복잡한 과정이 필요했습니다.

하지만  ES6에서는 간단하게 아래와 같이 할 수 있습니다.

js
let a = 10;
let b = 20;

[a, b] = [b, a];

console.log(a, b);

 

 

 

객체 해체할당

객체의 해체할당은 실무에서 다양하게 활용하고 자주 사용하기 때문에 무엇보다 중요합니다.

 

객체 해체할당 사용방법

1)  기본 : { 추출할 프로퍼티명 : 할당하고자 하는 변수명 }

js
const sora = {
    name : '강소라',
    age : 29,
    gender : 'female'
};

const {
    name: n,
    age: a,
    gender: g
} = sora;

console.log(n, a, g); // 강소라 29 female

앞서 살펴 본  배열 해체할당은 배열의 인덱스를 매칭시켜서 하나하나 변수명에 할당하는 형태였는데 객체에는 인덱스가 없는 대신에 그 역할을  key가 하는 것이므로  key를 매칭시켜서 변수에 담는 것이  객체 해체할당입니다.

그래서 위 예제를 보면  n, a, g가 변수가 되고  name과  name 을 매칭시켜서 매칭된  '강소라'를  n 에 할당하게 되는 형태입니다.

그리고  let으로 선언하면 내부의 모든 변수는  let 선언으로  const로 선언하면 모든 변수는  const 선언으로 되는 것은 배열 객체할당에서
알아본 내용과 동일합니다.

배열 해체할당에서  발췌하는 방법보다 객체 해체할당이 더 간단합니다.

js
const sora = {
    name : '강소라',
    age : 29,
    gender : 'female'
};

const {
    gender: g,
    age: a
} = sora;

console.log( a, g );

객체 해체할당의  발췌는 순서도 지킬 필요없이 해체할당하고자 하는 대상만을 사용할 수 있기 때문에 배열 해체할당보다 편리한 측면이 있습니다.

 

2)  할당할 변수명은 생략 가능하다. (property shorthand)

js
const sora = {
    name : '강소라',
    age : 29,
    gender : 'female'
};

const {
    name : name,
    age : age,
    gender :gender
} = sora;

console.log(name, age, gender);

위와 같은 코드를 프로퍼티를 축약형으로 변경하면 다음과 같습니다.

js
const sora = {
    name : '강소라',
    age : 29,
    gender : 'female'
};

const {
    name,
    age,
    gender
} = sora;

console.log(name, age, gender);

 

4)  중첩객체의 경우 - 접근자와 추출을 구분하는 것이 중요

js
const loginInfo = {
    device: {
        createdAt: '2019-12-06T00:14:04+0000',
        deviceId: '0000000000004Vx',
        deviceType: 'desktop'
    },
    user: {
        createdAt: '2019-03-08T18:00:28+0000',
        email: 'power4ce@gmail.com',
        name: '김재희',
        nickname: 'jinsangsiki',
        phoneNumber: '010-4542-7077'
    }
};

const {
    device,
    user: {
        name,
        nickname,
        phoneNumber: phone
    }
} = loginInfo;

// user 는 변수선언이 되어있을까?
// phoneNumber 와 phone 중에 선언된 변수는 어느쪽일까?

위 예제에서  user 는 변순 선언이 아니라 접근만 했을 뿐입니다.   즉,  user접근자일 뿐입니다.
그리고  phoneNumber 는 접근자이고  phone 이 변수가 됩니다.

아래와 같이 사용할 일은 없겠지만 가능하다는 것을 보여주기 위한 예제입니다.

js
const loginInfo = {
    device: {
        createdAt: '2019-12-06T00:14:04+0000',
        deviceId: '0000000000004Vx',
        deviceType: 'desktop'
    },
    user: {
        createdAt: '2019-03-08T18:00:28+0000',
        email: 'power4ce@gmail.com',
        name: '김재희',
        nickname: 'jinsangsiki',
        phoneNumber: '010-4542-7077'
    }
};

const {
    device: {
        createdAt,
        deviceType
    },
    user: userInfo,
    user: {
        nickname,
    },
    user: {
        createdAt: userCreatedAt,
        email,
        name
    }
} = loginInfo;

위 예제는 중첩된 객체의 key(접근자)를 여러번 작성하여 접근해 발췌할 수도 있다는 것을 보여주고 있습니다.

 

5)  default parameter 와의 연동

js
const phone = {
    name : 'iPhone',
    color : undefined
};

const {
    name: n,
    version: v = '8 edition',
    color: c = 'red'
} = phone;
console.log(n, v, c);

const {
    name,
    version = '11 Pro',
    color = 'space grey'
} = phone;
console.log(name, version, color);

name 에는  'iPhone' 값이 있으나  color 는  undefined 인 상태로 version: v = '8 edition'  version 과  version 을 매칭해서 값을 담으려고 할 때  version 값이 없으면  '8 edition'을 할당해라라고  default parameter를 사용한 것입니다.

이러한 패턴은 서버에서 정보를 받는데 해당 정보가 있을 수도 있고 없을 수도 있는 정보(프로퍼티)가 있다면  default parameter를 이용하면 간단히 해결할 수 있습니다. 다시 말해, 실무에서 통신할 때 유용하게 사용하실 수 있습니다.

 

 

객체 해체할당의 사용예

js
const getUrlParts = (url) => /^(https?):\/\/(\w{3,}\.[A-z.]{2,})(\/[a-z0-9]{1,}\/([a-z0-9\-.,]+))$/.exec(url);

console.log( getUrlParts( 'http://abc.com/es6/7-1.destructuring' ) );

const [ , protocol, host, , title] = getUrlParts('http://abc.com/es6/7-1.destructuring');
console.log(protocol, host, title);

 

 

다음은 함수에 인자를 넘겨서 넘긴 정보를 객체 해체할당을 하여 받아오는 형태로 아래와 같이 다양하게 활용될 수 있습니다.

Step #1

js
const getArea = (info) => {
    const {width, height} = info; // 함수 내부에서 추출(발췌)하고 있음
    return width * height;
};

const result = getArea( {width: 10, height: 50} );
console.log( result );

Step #2

js
const getArea2 = ({width, height}) => { // 함수 파라미터에서 추출함
    return width * height;
};

const result2 = getArea2( {width: 20, height: 60} );
console.log( result2 );

만약에 인자가 넘어오지 않을 경우를 대비한다면 아래와 같이  default parameter 이용할 수 있습니다.

Step #3

js
// 인자가 넘어오지 않을 경우에 대비하여 default parameter 정의
const getArea3 = ({width, height} = { width:0, height: 0 }) => {
    return width * height;
};

const result3 = getArea3();
console.log( result3 );

Step #3 을 좀더 줄여본다면 아래와 같이 정의할 수 있습니다.

Step #4

js
const getArea4 = ({ width = 0, height = 0 }) => {
    return width * height;
};

const result4 = getArea4( {width: 15, height: 30} );
console.log( result4 );

 

지금까지 살펴본  destructuring assignment를 활용하면 실무에서 매우 유용할 수 있습니다.

js
const getArea = ({ width, height = width }) => {
  return width * height;
};

getArea({ width: 10 });

 

 

Jaehee's WebClub

 

'JavaScript > ES6+' 카테고리의 다른 글

name property of function  (0) 2021.02.26
화살표 함수(Arrow function)  (1) 2021.02.26
enhanced object functionality  (0) 2021.02.26
shorthand property, concise method  (0) 2021.02.26
default parameter, rest parameter, spread operator  (0) 2021.02.26