JavaScript / splice()로 배열 요소 삭제·추가·교체하기

Array.splice(start, deleteCount, ...items)는 원본 배열에서 지정한 수만큼 제거하고, 같은 자리에 새 요소를 넣을 수 있는 메서드입니다. 반환값은 제거된 요소를 담은 새 배열입니다. slice()와 달리 원본 배열 자체가 바뀌므로 반환값과 변경된 배열을 각각 확인해야 합니다.

제거 개수와 반환값

첫 인수는 0부터 시작하는 위치, 두 번째 인수는 끝 인덱스가 아니라 제거할 요소의 개수입니다. splice(2, 3)은 인덱스 2에서 시작해 요소 세 개를 제거합니다. 제거된 요소는 반환 배열에 담기고 나머지 요소는 원본 배열에서 이어집니다.

const items = ['One', 'Two', 'Three', 'Four', 'Five', 'Six'];
const removed = items.splice(2, 3);

console.log(removed); // ['Three', 'Four', 'Five']
console.log(items);   // ['One', 'Two', 'Six']

제거 개수가 남은 요소보다 크면 남은 요소만 제거합니다. 아무것도 제거하지 않았다면 빈 배열을 반환합니다. 시작 위치에 음수를 주면 배열 끝에서 거꾸로 셉니다. MDN의 Array.splice() 문서에서 경계 규칙을 확인할 수 있습니다.

값을 삽입하거나 기존 값을 교체하기

세 번째 인수부터는 같은 위치에 넣을 새 요소입니다. 제거 개수를 0으로 주면 기존 요소를 지우지 않고 삽입합니다. 제거 수와 삽입 수가 다르면 배열 길이도 달라집니다.

const colors = ['빨강', '파랑', '노랑'];
const replaced = colors.splice(1, 1, '초록', '보라');
console.log(replaced); // ['파랑']
console.log(colors);   // ['빨강', '초록', '보라', '노랑']

colors.splice(2, 0, '검정');
console.log(colors);   // ['빨강', '초록', '검정', '보라', '노랑']

제거 개수를 생략한 splice(start)는 시작부터 끝까지 지웁니다. 값을 삽입할 때는 이 인수를 생략할 수 없으므로 제거하지 않으려면 0을 지정하세요. splice(start, undefined, newItem)처럼 undefined를 명시하면 0으로 처리되어 끝까지 삭제하지 않습니다.

전체 예제: 배열을 바꾸고 원상복구하기

아래 코드를 UTF-8로 array-splice-example.html에 저장해 브라우저에서 엽니다. 시작 위치, 제거 개수와 쉼표로 구분한 삽입 값을 입력해 ‘배열 변경’을 누릅니다. 작업할 때마다 현재 배열이 다시 바뀌므로 이전 결과를 이어서 편집할 수 있습니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>배열 제거·삽입 실습</title>
</head>
<body>
<p>처음 배열: One, Two, Three, Four, Five, Six</p>
<label for="start">시작 인덱스</label>
<input id="start" type="number" step="1" value="1">
<label for="count">제거 개수(비우면 끝까지 제거)</label>
<input id="count" type="number" min="0" step="1" value="2">
<label for="add">삽입할 값(쉼표로 구분)</label>
<input id="add" type="text" value="Seven, Eight">
<button id="apply" type="button">배열 변경</button>
<button id="reset" type="button">처음으로</button>
<pre id="output" aria-live="polite"></pre>
<script>
const original = ['One', 'Two', 'Three', 'Four', 'Five', 'Six'];
let items = original.slice();
const startInput = document.querySelector('#start');
const countInput = document.querySelector('#count');
const addInput = document.querySelector('#add');
const output = document.querySelector('#output');

function display(removed) {
  output.textContent = `현재 배열: ${JSON.stringify(items)}\n` +
    `제거한 배열: ${JSON.stringify(removed)}\n` +
    `현재 길이: ${items.length}`;
}

document.querySelector('#apply').addEventListener('click', () => {
  const start = Number(startInput.value);
  const countText = countInput.value.trim();
  const additions = addInput.value.trim() === '' ? [] :
    addInput.value.split(',').map(item => item.trim());
  if (!Number.isInteger(start) ||
      (countText !== '' && (!Number.isInteger(Number(countText)) || Number(countText) < 0))) {
    output.textContent = '시작은 정수, 제거 개수는 0 이상의 정수를 입력하세요.';
    return;
  }
  if (countText === '' && additions.length > 0) {
    output.textContent = '값을 삽입하려면 제거 개수를 입력하세요. 삽입만 할 때는 0입니다.';
    return;
  }
  const removed = countText === ''
    ? items.splice(start)
    : items.splice(start, Number(countText), ...additions);
  display(removed);
});

document.querySelector('#reset').addEventListener('click', () => {
  items = original.slice();
  startInput.value = '1';
  countInput.value = '2';
  addInput.value = 'Seven, Eight';
  display([]);
});
display([]);
</script>
</body>
</html>

기본 입력인 시작 1, 제거 개수 2, 삽입 값 Seven, Eight을 적용하면 제거한 배열은 ["Two","Three"], 현재 배열은 ["One","Seven","Eight","Four","Five","Six"]입니다. 제거 개수를 0으로 바꾸면 삽입만 합니다. ‘처음으로’를 누르면 여섯 요소의 처음 배열과 입력값이 복원됩니다.

원본을 보존해야 한다면

같은 인수 형태로 새 배열을 만들어야 한다면 toSpliced()를 검토할 수 있습니다. 이 메서드는 제거된 요소가 아니라 변경 후의 새 배열을 반환하며 원본을 보존합니다. 지원 환경이 제한된다면 먼저 slice()로 배열을 복사한 뒤 복사본에 splice()를 적용할 수도 있습니다.

const base = ['A', 'B', 'C'];
const copy = base.slice();
copy.splice(1, 1, 'X');
console.log(base); // ['A', 'B', 'C']
console.log(copy); // ['A', 'X', 'C']

객체 요소가 있는 배열에서 slice()는 얕은 복사이므로 객체 내부를 수정할 계획이라면 별도 복제가 필요합니다. 단지 원본의 한 구간을 읽을 목적이라면 원본을 바꾸지 않는 slice()가 더 간단합니다. MDN의 Array.toSpliced() 문서에서 반환값과 지원 환경을 확인하세요.