Spread/Rest — ... 세 개의 점이 하는 일
이 토픽을 마치면
...이 "펼치기(Spread)"와 "모으기(Rest)" 두 가지 역할을 하는 것을 이해하게 됩니다.
같은 기호, 다른 역할
JavaScript에서 ...은 위치에 따라 역할이 달라집니다:
- Spread: 배열이나 객체를 "펼칩니다"
- Rest: 나머지 값들을 "모읍니다"
같은 ...인데 쓰이는 자리에 따라 반대 동작을 합니다.
Spread: 펼치기
배열을 펼칩니다:
javascript
const a = [1, 2, 3];
const b = [0, ...a, 4];
// [0, 1, 2, 3, 4]...a가 배열 a의 요소들을 하나하나 꺼내서 나열합니다. 배열을 복사할 때도 씁니다:
javascript
const original = [1, 2, 3];
const copy = [...original];객체도 펼칩니다:
javascript
const defaults = { theme: "light", lang: "ko" };
const userSettings = { lang: "en", fontSize: 14 };
const config = { ...defaults, ...userSettings };
// { theme: "light", lang: "en", fontSize: 14 }뒤에 오는 객체가 같은 키를 덮어씁니다. 기본 설정에 사용자 설정을 합치는 패턴입니다.
함수 인자로 배열을 넘길 때도 씁니다:
javascript
const nums = [3, 1, 4, 1, 5];
Math.max(...nums); // 5Rest: 모으기
함수 파라미터에서 "나머지 전부"를 배열로 받습니다:
javascript
function sum(first, ...rest) {
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
return rest.reduce((a, b) => a + b, first);
}
sum(1, 2, 3, 4, 5); // 15...rest가 첫 번째 인자 이후의 나머지를 모두 배열로 모읍니다.
구조 분해에서도 씁니다:
javascript
const [head, ...tail] = [1, 2, 3, 4];
// head: 1, tail: [2, 3, 4]
const { name, ...others } = { name: "Alice", age: 25, city: "Seoul" };
// name: "Alice", others: { age: 25, city: "Seoul" }특정 속성만 빼고 나머지를 따로 모을 때 유용합니다.
Spread vs Rest 구분법
javascript
// Spread — "넣는 쪽"에서 펼침
const arr = [...other];
func(...args);
// Rest — "받는 쪽"에서 모음
function func(...params) {}
const [a, ...rest] = arr;값을 보내는 자리(대입 오른쪽, 함수 호출)에서는 Spread. 값을 받는 자리(대입 왼쪽, 함수 선언)에서는 Rest.
실무 패턴: 불변 업데이트
React에서 상태를 업데이트할 때 원본을 직접 수정하면 안 됩니다. Spread로 새 객체를 만듭니다:
javascript
const [user, setUser] = useState({ name: "Alice", age: 25 });
setUser({ ...user, age: 26 });배열에 요소를 추가할 때도:
javascript
const [items, setItems] = useState(["a", "b"]);
setItems([...items, "c"]); // 뒤에 추가
setItems(["z", ...items]); // 앞에 추가원본 배열/객체는 건드리지 않고 새 것을 만듭니다.
핵심
...은 보내는 자리에서 Spread(펼침), **받는 자리에서 Rest(모음)**입니다. Spread로 배열/객체를 복사하고 합칠 수 있고, Rest로 나머지 값들을 모을 수 있습니다. React의 불변 상태 업데이트에서 가장 많이 쓰이는 패턴입니다.