코로 넘어져도 헤딩만 하면 그만

주말공부: 구조분해할당 본문

CODE STATES 44

주말공부: 구조분해할당

꼬드리 2023. 3. 19. 19:50

구조분해 할당에 대한 개념이 계속 헷갈렸습니다. 자주 쓰이지 않는 것 같아서 흐린 눈을 뜨고 넘기고 있었는데, 그래도 언제까지나 이럴 순 없다는 생각에 한번 파볼 생각입니다.

우선 정의를 살펴보겠습니다. 

 

구조분해 할당이란?
- spread 문법을 이용하여 값을 해체한 후, 개별값을 변수에 새로 할당하는 표현식을 말한다.
- let, const와 함께 쓰여야 오류를 막을 수 있다.

 

 

spread 문법이라? 그렇다면 ...을 사용하는 문법을 말하겠네요. [1, 2, 3] 같은 배열이 있을 때, ...[1, 2, 3]을 쓰면 결과가 1, 2, 3 이렇게 배열을 해체해주는 식으로 쓰입니다. 그렇다면 이걸 사용해서 개별값을 변수에 새로 할당한다는 뜻일까요. HOW...?

mdn에 나온 예시를 잠시 살펴봅기로 합니다. 어쩔 수 없어요, 개념부터 다시 잡기 위해서는.....

 

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

오호... 이런 예시가 보입니다. ...rest를 써서 첫번째(a), 두번째(b) 요소가 아닌 30, 40, 50을 전부 rest에 담은 뒤 그것을 출력하면 뒷부분만 자른 배열이 생성되는군요. 이런 과정이 객체로도 가능할까요?

({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}

가능하네요. 객체도 유사한 방식으로 출력이 됩니다. 객체 및 배열에 사용해서 쉽게 데이터 뭉치를 만든다고 해요.

사실 여기까지는 rest랑 비슷하니 이해가 되었는데 정작 헷갈린 건 '할당'이었습니다.

 

 

let foo = ["one", "two", "three"];
let [red, yellow, green] = foo;
console.log(red); // "one"
console.log(yellow); // "two"
console.log(green); // "three"

위의 예시를 한번 봅시다. ... foo안에 담긴 요소가 [red, yellow, green] 안에 할당되었습니다. 그랬더니 이 요소들이 각각의 변수들에 할당이 되네요?

맙소사... 전혀 이해가 가지 않습니다. 이런 식으로도 동작이 가능하다고? 

당황한 마음에 다른 예시도 살펴봅니다.

var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

배열을 구조분해 한 경우에, 이렇게 할당이 가능하다고 합니다. b는 배열로 나오네요. 

... 뭐지? 

어쩔 수 없이 mdn에서 조금 벗어나 다른 예시들을 만나러 떠납니다. 너무 어려워요. ..

 

// 이름과 국적을 요소로 가진 배열을 만듭니다.
let arr = ["Yuri", "Korean"]

// 구조 분해 할당을 이용해 name엔 arr[0]을 country엔 arr[1]을 할당하였습니다.
let [name, country] = arr;

alert(name); // Yuri
alert(country);  // Korean

아하. 이제 조금 이해가 가는 것 같습니다. 배열 내부에 있는 요소들마다 변수를 하나씩 할당해주는 것이군요?

let name = arr[0];
let country = arr[1];

이렇게 일일이 변수에 할당하는 것과도 결과는 다르지 않다고 합니다. 다만 다뤄야 하는 변수가 아주 많다면? 구조분해할당을 쓰는 것이 훨씬 코드를 짧게 작성하여 할당할 수 있겠죠. 

 

좀더 신기한 쓰임새도 한번 봅시다.

let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert( title ); // Consul

이렇게 쉼표를 사용하면 쓸모없는 두번째 Caesar은 버리게 됩니다. [3]값인 of the Roman Republic 역시 변수가 없기 때문에 쓸 수 없겠네요. title 옆에 변수를 하나 더 넣는다면 마지막 요소도 다룰 수 있게 될 것 같습니다.

그런데 여기서 spread 문법은 쓰이지 않았는데요?

 

아. 왜 헷갈렸는지 이제 알 것 같네요.

구조분해할당은 반드시 spread 문법이 쓰여야 하는 게 아닙니다. 말그대로 객체나 배열을 변수로 '분해'하게 해주는 문법이죠. 다만 이 과정에 spread 문법이 유용하게 '쓰일 수'도 있는 겁니다. 

이왕 알아보는 김에 어떻게 쓰이는지 더 자세히 보도록 합시다.

 

let guest = "Jane";
let admin = "Pete";

// 변수 guest엔 Pete, 변수 admin엔 Jane이 저장되도록 값을 교환함
[guest, admin] = [admin, guest];

alert(`${guest} ${admin}`); // Pete Jane(값 교환이 성공적으로 이뤄졌습니다!)

이처럼 값을 교환할 수도 있습니다. 임시 배열을 만들어 두 변수를 담고, 요소 순서를 교체해 배열을 분해합니다.

 

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

let {title, width, height} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200

객체에 이렇게 분해를 해줄 수도 있겠습니다. 단순히 분해뿐만이 아닙니다. 원하는대로 새로운 이름을 가진 변수에 할당해주는 것도 가능합니다. 아래처럼 :를 쓰면 말이죠. width가 w로 height가 h로 바뀌는 것을 볼 수 있습니다.

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

// { 객체 프로퍼티: 목표 변수 }
let {width: w, height: h, title} = options;

// width -> w
// height -> h
// title -> title

alert(title);  // Menu
alert(w);      // 100
alert(h);      // 200
let options = {
  title: "Menu"
};

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

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200

위와 같이 매개변수가 없는 경우를 대비하여 =를 사용해 기본값을 설정해주는 방식도 있습니다. 유용해보이는데요?

 

 

구조분해할당의 사용법을 살펴보던 중, 처음에 오해하고 있던 것처럼 spread가 쓰이는 사례를 찾았습니다. 

분해하려는 객체의 프로퍼티 개수가 할당하려는 변수의 개수보다 많은 경우에 쓰면 될 것 같네요.

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

// title = 이름이 title인 프로퍼티
// rest = 나머지 프로퍼티들
let {title, ...rest} = options;

// title엔 "Menu", rest엔 {height: 200, width: 100}이 할당됩니다.
alert(rest.height);  // 200
alert(rest.width);   // 100

그러니까 ...rest를 변수처럼 사용해서, 할당하고 싶은 변수 외 나머지를 전부 담아버릴 수 있네요. 이렇게 사용될 수 있다는 것이군요! 구조분해 할당에 대해서 이해가 좀 되나요?마지막으로 구조분해할당의 아주 좋은 예시와 함께 이해를 마치도록 하겠습니다.

 

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

위 객체를 다음과 같이 할당해봅시다.

  • name 프로퍼티의 값을 변수 name에 할당하세요.
  • years 프로퍼티의 값을 변수 age에 할당하세요.
  • isAdmin 프로퍼티의 값을 변수 isAdmin에 할당하세요. isAdmin이라는 프로퍼티가 없으면 false를 할당하세요.
더보기

해답:

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

alert( name ); // John
alert( age ); // 30
alert( isAdmin ); // false

 : 를 사용하여 각각 새 변수로 할당해주고, =를 사용해 없을 상황에 대비하는 기본값으로 false를 준 것을 볼 수 있습니다. 완벽합니다. 

 

 

오늘 이해에 도움을 준...

https://ko.javascript.info/destructuring-assignment

 

구조 분해 할당

 

ko.javascript.info

 

Comments