Javascript/Javascript

[Javascript] spread와 rest

금요일인줄 2025. 6. 24. 09:00
728x90
반응형

 

 

 

전개 연산자(...)는 ES6에서 새로 도입된 문법이다. 이 전개 연산자를 사용하는 spread와 rest는 서로 완전히 다르지만 한편으로는 은근히 비슷하다.

 

 

 

spread

spread라는 단어는 펼치다, 퍼뜨리다라는 의미를 가지고 있다. 이 문법을 사용하면 객체 또는 배열을 펼칠 수 있다. 예를 들어 다음과 같은 객체들이 있다고 가정해 보자.

const slime = {
  name: '슬라임'
};

const cuteSlime = {
  name: '슬라임',
  attribute: 'cute'
};

const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

console.log(slime);
console.log(cuteSlime);
console.log(purpleCuteSlime);

 

위 코드에서는 먼저 slime이라는 객체를 선언했다. 그리고 cuteSlime이라는 객체를 만들었는데 기존에 선언한 slime을 건드리지 않고 새로운 객체를 만들어 slime이 가지고 있는 값을 그대로 사용했다. 그리고 나서 purpleCuteSlime이라는 객체를 만들었는데 이 객체는 다시 cuteSlime이 가지고 있는 속성을 그대로 사용하면서 color라는 속성을 추가하였다.

 

위 코드에서의 핵심은 기존의 것을 건드리지 않고 새로운 객체를 만든다는 것이다. 이러한 상황에서 유용하게 사용할 수 있는 문법이 바로 spread이다. 이는 spread를 사용하면 아래와 같이 작성할 수 있다.

const slime = {
  name: '슬라임'
};

const cuteSlime = {
  ...slime,
  attribute: 'cute'
};

const purpleCuteSlime = {
  ...cuteSlime,
  color: 'purple'
};

console.log(slime);
console.log(cuteSlime);
console.log(purpleCuteSlime);

 

여기서 사용한 ... 연산자가 바로 spread 연산자이다. spread 연산자는 배열에서도 사용할 수 있다.

 

const animals = ['개', '고양이', '참새'];
const anotherAnimals = [...animals, '비둘기'];

console.log(animals); // ['개', '고양이', '참새']
console.log(anotherAnimals); // ['개', '고양이', '참새', '비둘기']

 

기존의 animals는 건드리지 않으면서 새로운 anotherAnimals 배열에 animals가 가지고 있는 내용을 모두 집어넣고 비둘기라는 항목을 추가적으로 넣었다.

 

배열에서 spread 연산자를 여러 번 사용하는 것도 가능하다.

const numbers = [1, 2, 3, 4, 5];

const spreadNumbers = [...numbers, 1000, ...numbers];
console.log(spreadNumbers); // [1, 2, 3, 4, 5, 1000, 1, 2, 3, 4, 5]

 

 


 

rest

rest는 생김새는 spread와 비슷하지만 역할에 큰 차이가 있다. rest는 객체, 배열 그리고 함수의 파라미터에서 사용이 가능하다.

 

 

 

객체에서의 rest

const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

const { color, ...rest } = purpleCuteSlime;
console.log(color); // purple
console.log(rest); // { "name": "슬라임", "attribute": "cute" }

 

rest 안에는 color를 제외한 값들이 들어 있다. rest는 객체와 배열에서 사용할 때에는 이처럼 비구조화 할당과 함께 사용되곤 한다. 주로 사용할 때에는 위와 같이 rest라는 키워드를 사용하게 되는데 그렇다고 추출한 값의 이름이 꼭 rest일 필요는 없다.

const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

const { color, ...cuteSlime } = purpleCuteSlime;
console.log(color);
console.log(cuteSlime);

 

이렇게 해도 무방하다. 이어서 attribute까지 없앤 새로운 객체를 만들고 싶다면 아래와 같이 해주면 될 것이다.

const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

const { color, ...cuteSlime } = purpleCuteSlime;
console.log(color); // purple
console.log(cuteSlime); // {name: '슬라임', attribute: 'cute'}

const { attribute, ...slime } = cuteSlime;
console.log(attribute); // cute
console.log(slime); // {name: '슬라임'}

 

 


 

객체에서의 rest

 

이번에는 배열에서의 사용 예시를 살펴보자.

const numbers = [0, 1, 2, 3, 4, 5, 6];

const [one, ...rest] = numbers;

console.log(one); // 0
console.log(rest); // [1, 2, 3, 4, 5, 6]

 

배열의 비구조화 할당을 통해 원하는 값은 밖으로 꺼내고 나머지를 rest 안에 넣었다. 반면 아래와 같이 할 수는 없다.

const numbers = [0, 1, 2, 3, 4, 5, 6];

const [..rest, last] = numbers; // Uncaught SyntaxError: Unexpected token '.'

 

 


 

함수 파라미터에서의 rest

 

rest를 함수 파라미터에서 사용할 수도 있다. 예를 들어 파라미터로 넣어 준 모든 값들을 더해주는 함수를 만들고 싶다고 가정해 보자.

function sum(a, b, c, d, e, f, g) {
  let sum = 0;
  if (a) sum += a;
  if (b) sum += b;
  if (c) sum += c;
  if (d) sum += d;
  if (e) sum += e;
  if (f) sum += f;
  if (g) sum += g;
  return sum;
}

const result = sum(1, 2, 3, 4, 5, 6);
console.log(result);

 

여기서 sum()은 7개의 파라미터를 받도록 되어 있는데 아래에서 호출할 때에는 6개만 넣어줬다. 그러면 g의 값이 undefined가 되기 때문에 변수 sum에 더하는 과정에서 += undefined를 하게 되면 결과는 NaN이 되어버린다. 그렇기 때문에 함수에서 조건문으로 하나하나 유효한 값인지 확인을 해준 것이다.

 

함수의 파라미터가 몇 개가 될지 모르는 상황에서 rest 파라미터를 사용하면 매우 유용하다. 코드를 다음과 같이 수정해 보자.

function sum(...rest) {
  return rest;
}

const result = sum(1, 2, 3, 4, 5, 6);
console.log(result); // [1, 2, 3, 4, 5, 6]

 

result가 가리키고 있는 것은 함수에서 받아온 파라미터로 이루어진 배열이다. 이제 파라미터들이 들어 있는 배열을 받았으니 그냥 모두 더해주면 되겠다.

function sum(...rest) {
  return rest.reduce((acc, current) => acc + current, 0);
}

const result = sum(1, 2, 3, 4, 5, 6);
console.log(result); // 21

 

 


 

함수 인자와 spread

 

파라미터와 인자가 헷갈릴 수도 있기 때문에 먼저 이에 대해 간단히 짚고 넘어가려 한다. 함수에서 값을 읽을 때에는 해당 값들을 파라미터라고 하는 반면, 함수에 값을 넣어줄 때에는 인자라고 부른다.

const myFunction(a) { // 여기서 a는 파라미터
  console.log(a); // 여기서 a는 인자
}

myFunction('hello world'); // 여기서 'hello world'는 인자

 

이제 함수 인자와 spread 문법을 사용하는 것에 대해 알아보자. 앞서 함수 파라미터와 rest를 사용한 것과 비슷하지만 반대의 역할이라고 할 수 있다. 예를 들어 배열 안에 있는 원소들을 모두 인자로 넣어주고 싶다고 가정해 보자.

function sum(...rest) {
  return rest.reduce((acc, current) => acc + current, 0);
}

const numbers = [1, 2, 3, 4, 5, 6];
const result = sum(
  numbers[0],
  numbers[1],
  numbers[2],
  numbers[3],
  numbers[4],
  numbers[5]
);
console.log(result);

 

상당히 불편해 보인다. 그러나 만약 sum()을 사용할 때 인자 부분에서 spread를 사용하면 다음과 같이 표현할 수 있다.

function sum(...rest) {
  return rest.reduce((acc, current) => acc + current, 0);
}

const numbers = [1, 2, 3, 4, 5, 6];
const result = sum(...numbers);
console.log(result);

 

 

 


 

문자열과 spread

 

그리고 한 가지 더. 놀랍게도 문자열에도 spread 문법을 활용할 수 있다. 문자열도 자바스크립트에서는 하나의 객체로 취급되기 때문이다.

const strings = 'abcdefg'; 

const strings2 = {...strings}
console.log(strings2) // {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g'}

const strings3 = [...strings]
console.log(strings3) // (7) ['a', 'b', 'c', 'd', 'e', 'f', 'g']

 

 

 

 

 

 

728x90
반응형