JavaScript에서 Spread vs Rest 연산자: 전문가처럼 확장하거나 수집하기
Source: Dev.to
Spread와 Rest 연산자: JavaScript에서 확장과 수집을 마스터하기
JavaScript에서는 Spread(...)와 Rest(...) 연산자를 사용해 배열·객체를 복사하거나, 함수 인자를 다루는 등 다양한 상황에서 코드를 간결하고 가독성 있게 만들 수 있습니다. 두 연산자는 문법적으로 동일해 보이지만, 실제 동작은 전혀 다릅니다. 이번 포스트에서는 각각의 용도와 차이점을 예시와 함께 살펴보겠습니다.
1️⃣ Spread 연산자 – “펼치다”
Spread 연산자는 iterable(반복 가능한) 객체를 개별 요소로 “펼쳐” 새로운 배열이나 객체를 만들 때 사용합니다.
배열에 적용하기
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4, 5]; // [1, 2, 3, 4, 5]
객체에 적용하기
const user = { name: 'Alice', age: 25 };
const updatedUser = { ...user, city: 'Seoul' };
// { name: 'Alice', age: 25, city: 'Seoul' }
함수 호출에 적용하기
function sum(a, b, c) {
return a + b + c;
}
const args = [1, 2, 3];
console.log(sum(...args)); // 6
핵심: Spread는 값을 “펼쳐서” 전달하거나 복제할 때 사용합니다.
2️⃣ Rest 연산자 – “모으다”
Rest 연산자는 함수 매개변수, 배열 디스트럭처링, 객체 디스트럭처링 등에서 여러 개의 값을 하나의 배열로 모을 때 사용합니다.
함수 매개변수에 적용하기
function logAll(...messages) {
console.log(messages);
}
logAll('Hello', 'World', '!'); // ['Hello', 'World', '!']
배열 디스트럭처링에 적용하기
const colors = ['red', 'green', 'blue', 'yellow'];
const [primary, secondary, ...others] = colors;
// primary: 'red', secondary: 'green', others: ['blue', 'yellow']
객체 디스트럭처링에 적용하기
const person = { name: 'Bob', age: 30, city: 'Busan', job: 'Developer' };
const { name, ...details } = person;
// name: 'Bob', details: { age: 30, city: 'Busan', job: 'Developer' }
핵심: Rest는 여러 값을 “모아서” 하나의 배열(또는 객체)로 만든다는 점에서 차이가 있습니다.
3️⃣ 언제 어떤 연산자를 써야 할까?
| 상황 | 사용 연산자 | 이유 |
|---|---|---|
| 기존 배열/객체를 복제하거나 새로운 요소를 추가하고 싶을 때 | Spread | 원본을 변형하지 않고 새로운 구조를 만들 수 있음 |
| 함수에 가변 인자를 전달하거나, 남은 요소를 별도 변수에 담고 싶을 때 | Rest | 인자를 자동으로 배열에 모아주어 가독성이 향상 |
| 배열·객체 디스트럭처링에서 남은 부분을 한 번에 받고 싶을 때 | Rest | 남은 요소들을 한 번에 처리 가능 |
4️⃣ 흔히 하는 실수
-
Spread와 Rest를 혼동
const arr = [1, 2, 3]; const copy = [...arr]; // ✅ 올바른 Spread 사용 const rest = [...arr]; // ❌ Rest가 아니라 Spread -
Rest를 객체 리터럴에 직접 사용
const obj = { a: 1, b: 2 }; const { ...rest } = obj; // ❌ 문법 오류 (Rest는 디스트럭처링에서만 사용) const newObj = { ...obj }; // ✅ 올바른 Spread 사용 -
함수 매개변수에 Spread 사용
function foo(...args) { /* ... */ } foo(...[1, 2, 3]); // ✅ 필요에 따라 Spread와 Rest를 조합 가능
5️⃣ 마무리
- Spread (
...) → “펼쳐서” 기존 데이터를 새로운 구조에 삽입한다. - Rest (
...) → “모아서” 여러 값을 하나의 배열(또는 객체) 로 만든다.
두 연산자를 올바르게 이해하고 상황에 맞게 사용한다면, 코드가 더 간결하고 예측 가능해집니다. 이제 여러분도 Spread와 Rest를 자유롭게 활용해 보세요! 🚀
소개
자바스크립트에서 배열과 객체를 마치 저글링하듯 다루면서, 복사하거나 병합하거나 슬라이스해야 할 때 땀 한 방울 흘리지 않고 처리하고 싶다고 상상해 보세요.
여기에 **spread 연산자(...)**와 **rest 연산자(...)**가 등장합니다—겉모양은 동일하지만 역할이 다른 두 문법 슈퍼히어로입니다. 이들은 현대 JS에서 깔끔하고 가독성 높은 코드를 위한 게임 체인저이며, 특히 React 앱과 Node.js 백엔드에서 큰 도움이 됩니다.
- Spread 값을 개별 요소로 확장합니다.
- Rest 값을 하나의 배열이나 객체로 수집합니다.
예시와 함께 살펴보며 실제 상황에서 어떻게 빛을 발하는지 확인해 봅시다.
스프레드 연산자가 하는 일: 값 펼치기
스프레드 연산자(...)는 배열이나 객체와 같은 iterable을 받아 그 요소들을 개별 항목으로 펼칩니다(확장합니다). 마치 상자를 풀어놓는 것처럼 모든 것이 흘러나와 쉽게 사용할 수 있습니다.
const fruits = ['apple', 'banana'];
const moreFruits = ['orange', ...fruits, 'grape'];
// Result: ['orange', 'apple', 'banana', 'grape']
const user = { name: 'Ritam', city: 'Kolkata' };
const updatedUser = { ...user, age: 20, hobby: 'coding' };
// Result: { name: 'Ritam', city: 'Kolkata', age: 20, hobby: 'coding' }
스프레드는 얕은 복사를 만들고 병합합니다—상태 관리에서 불변성을 유지한 업데이트에 이상적입니다.

나머지 연산자(Rest Operator)의 역할: 값 수집
나머지 연산자(...)는 반대로 요소들을 하나의 배열(또는 객체)로 모읍니다. 함수 매개변수와 구조 분해 할당에서 동작하며, 남은 값을 위한 “진공청소기”와 같습니다.
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
sum(1, 2, 3, 4); // Result: 10 (numbers = [1, 2, 3, 4])
const [first, ...rest] = ['apple', 'banana', 'orange']; // 배열 구조 분해
console.log(first); // 'apple'
console.log(rest); // ['banana', 'orange']
첫 번째 항목을 가져온 뒤, 나머지를 수집합니다.

주요 차이점: 스프레드 확장, 레스트 수집
| 항목 | Spread (...) | Rest (...) |
|---|---|---|
| 방향 | 확장 (언팩) | 수집 (팩) |
| 맥락 | 어디서든 (배열, 객체, 호출) | 함수 매개변수 또는 구조 분해 |
| 사용 사례 | 복사, 병합, 인자 전달 | 가변 인자, 구조 분해 남은 값 |
| 예시 | [...arr]는 배열을 복제합니다 | function(...args)는 인자를 수집합니다 |
스프레드는 값을 외부로 퍼뜨리는 용도이고, 레스트는 값을 내부로 모으는 용도입니다. 이들을 혼동하면 코드가 깨질 수 있습니다—스프레드는 매개변수 목록에서 작동하지 않습니다.
실용적인 사용 사례: 실제 성공 사례
배열/객체 복제 (Spread)
React 상태에서 변이를 방지합니다.
const state = { users: [] };
const newState = { ...state, users: [...state.users, newUser] };
함수 인자 (Spread)
배열을 동적으로 전달합니다.
const coords = [10, 20];
console.log(Math.max(...coords)); // 20
API 데이터 병합 (Spread)
기본값과 사용자 입력을 결합합니다.
const defaults = { method: 'GET' };
const config = { ...defaults, url: '/api/users' };
fetch(config.url, config);
Node.js 유틸리티에서 가변 인자 (Rest)
유연한 헬퍼 함수를 만듭니다.
function log(...messages) {
console.log(new Date(), ...messages);
}
log('User login:', userId, timestamp);
Props 구조 분해 (Rest) – React
function Button({ children, ...props }) {
return {children};
}
이러한 패턴은 Vercel에서의 풀스택 배포부터 면접 코딩 라운드까지 어디서든 나타납니다.
마무리: 두 가지를 모두 마스터하여 더 깔끔한 JS 만들기
Spread와 rest 연산자는 복잡한 배열/객체 작업을 우아한 한 줄 코드로 바꿔, 풀스택 개발에서 겪는 골칫거리를 줄여줍니다. 기억하세요:
- Spread 확장하여 복사/병합에 사용합니다.
- Rest 수집하여 유연한 매개변수에 사용합니다.
작은 예제로 연습하면 프로젝트에서 두 연산자가 자연스럽게 익숙해집니다. 다음에 Node.js 라우트나 React 컴포넌트를 리팩터링할 때 ...를 사용해 보세요—미래의 자신이 감사할 것입니다.