본문 바로가기
JS

전개연산자 (Spread Opertor)

by spare8433 2022. 2. 13.

리액트 공부중 코드중에 처음 보는 녀석을 발견했다.

function reducer(state, action) {
 return {
     ...state,
    [action.name]:action.value
 }
}

...state

이렇게 생긴 이 녀석의 이름은 전개 연산자 스프레드 연산자로도 불리는 듯하다.

그나마도 쉽게 이해되는 설명은 이것이었다

'스프레드 연산자를 사용하면 배열, 문자열, 객체 등 반복 가능한 객체 (Iterable Object)를 개별 요소로 분리할 수 있습니다.'

쉽게 말하면 spread 의 뜻처럼 배열, 문자열, 객체 등을 펼쳐서 쓴다는 의미다.

그러나 완벽히 이해가 되지 않고 왜 쓰는지, 어떻게 활용이 되는지는 찾아볼 필요가 있었다.

왜 사용하는가?

일단 불변성의 중요성을 알아야 했다

객체 타입의 데이터를 변수에 할당하고 그 변수를 다른 변수에 다시 할당하면 똑같은 놈이 두 개가 될 뿐이다. (가끔 인지 못함)
그래서 만약 사본을 수정하면 원본도 함께 수정이 되어버리는 것은 문제도 문제지만 귀찮은 일이다.


리액트로 보면 특정 컴포넌트가 업데이트를 할 필요가 없다는 것을 어떻게 판단할 수 있을까?
가장 간단한 방법은 컴포넌트가 갖고 있는 데이터(props, state)의 이전 이후 값을 완전히 비교하는 것이다.
만약 불변성이 지켜지지 않아 객체 내부의 값이 새로워져도 바뀐 것을 감지하지 못하게 된다.


그럭타 불변성을 지켜주지 않으면 내가 귀찮아진다.

활용방법

배열 병합

var arr1 =['a','b']
var arr2 = ['c']
var arr = [...arr1, ...arr2]     

console.log(arr)     // [ 'a', 'b', 'c']

배열 복사

var arr1 =['a','b'];
var arr2 = [...arr1];

arr2.push('c');

console.log(arr1);     // [ 'a', 'b',]    원본은 안바뀜
console.log(arr2);     // [ 'a', 'b', 'c' ] 이놈은 바뀜 아까말한 불변성의 중요성이 생각나는 부분이다

Spread 연산자를 이용한 복사는 얕은(shallow) 복사를 수행하며,
배열 안에 객체가 있는 경우에는 객체 자체는 복사되지 않고 원본 값을 참조합니다.
따라서 원본 배열 내의 객체를 변경하는 경우 새로운 배열 내의 객체 값도 변경됩니다.

나머지 매개변수 (Rest Parameter)

함수를 호출할 때 함수의 매개변수(parameter)를 spread operator로 작성한 형태를 Rest parameter라고 부릅니다.
함수의 파라미터로 오는 값들을 모아서 "배열"에 집어넣습니다. 이를 통해서 깔끔한 함수 표현을 적용할 수 있습니다.

function add(...rest) {
  let sum = 0;
  for (let item of rest) {
    sum += item;
  }
  return sum;
}

console.log(add(1,5,7)); // 12



나머지 매개변수는 반드시 하나여야 하고 마지막 위치에서만 사용할 수 있다. (어찌 보면 당연한 이야기)
객체 리터럴 setter에서 사용할 수 없다. setter는 반드시 인자를 하나만 받을 수 있기 때문에 정의 단계부터 에러가 발생한다
배열 안에 객체가 있는 경우에는 객체 자체는 복사되지 않고 원본 값을 참조합니다.
따라서 원본 배열 내의 객체를 변경하는 경우 새로운 배열 내의 객체 값도 변경됩니다.

함수 호출 인자로 사용

var numbers = [9, 4, 7, 1]; 
console.log(Math.min(...numbers)); // 1

객체 복사

var currentState = { name: '철수', species: 'human'};
currentState = { ...currentState, age: 10};
console.log(currentState)    // { name: '철수', species: 'human', age: 10 }

객체 업데이트

var currentState = { name: '철수', species: 'human' age: 9};
currentState = { ...currentState, name: '영희', age: 11};
console.log(currentState)    // { name: '영희', species: 'human', age: 11 }

Destructuring 에서 활용

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

({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}



다시 돌아가서

function reducer(state, action) {
 return {
     ...state,
    [action.name]:action.value
 }
}



이 부분은 기존 state 객체에 [action.name]:action.value 이런 형식의 속성을 추가하고 리턴해주는 의미였다.



한 줄 요약 : 알고 보니 상당히 유용한 문법이었다.

'JS' 카테고리의 다른 글

JavaScript Set  (0) 2023.02.14
유사 배열 객체와 반복 작업  (0) 2022.08.26
웹팩과 번들러  (0) 2022.04.12
promise 와 async & await  (0) 2022.03.02
callback 함수  (0) 2022.02.24