JavaScript / push·pop·unshift·shift로 배열 요소 추가·삭제하기

push()와 unshift()는 배열의 뒤와 앞에 요소를 추가합니다. pop()과 shift()는 뒤와 앞에서 요소 하나를 제거합니다. 네 메서드는 모두 원본 배열을 직접 바꾸지만, 추가 메서드는 새 길이를, 제거 메서드는 제거한 값을 반환합니다.

네 메서드의 위치와 반환값

메서드 원본 배열에서 하는 일 반환값
push(value) 뒤에 추가 새 배열 길이
unshift(value) 앞에 추가 새 배열 길이
pop() 마지막 요소 제거 제거한 요소
shift() 첫 요소 제거 제거한 요소

배열을 바꾸지 않고 새 배열을 만들어야 하는지 먼저 판단하세요. 이 네 메서드는 새 배열을 반환하지 않습니다. 특히 const result = items.push("four")의 result는 배열이 아니라 숫자입니다.

push()와 unshift()로 추가하기

push()는 끝에, unshift()는 앞에 하나 이상의 값을 넣습니다. 여러 값을 한 번에 unshift("A", "B")하면 전달한 순서인 A, B가 앞에 놓입니다. 호출을 두 번 나누어 맨 앞에 넣으면 결과 순서가 달라집니다.

const colors = ['blue', 'green'];
const afterPush = colors.push('red');
console.log(colors);    // ['blue', 'green', 'red']
console.log(afterPush); // 3

const afterUnshift = colors.unshift('black', 'white');
console.log(colors);
// ['black', 'white', 'blue', 'green', 'red']
console.log(afterUnshift); // 5

반환값은 늘어난 길이입니다. 요소를 추가하기만 하면 반환값을 버려도 되지만, 현재 길이를 계속 사용한다면 items.length와 반환값 중 무엇을 읽는지 코드를 분명히 하세요. MDN의 Array.push() 문서와 Array.unshift() 문서에 여러 인수를 줄 때의 동작이 나옵니다.

pop()과 shift()로 제거하기

pop()은 마지막 요소, shift()는 첫 요소를 제거하고 그 값을 반환합니다. 비어 있는 배열에 호출하면 둘 다 undefined를 반환하며 배열 길이는 0으로 남습니다. 제거한 값을 다시 사용할 계획이라면 반환값을 저장하세요.

const colors = ['blue', 'green', 'red'];
console.log(colors.pop());   // 'red'
console.log(colors);         // ['blue', 'green']
console.log(colors.shift()); // 'blue'
console.log(colors);         // ['green']

const empty = [];
console.log(empty.pop());   // undefined
console.log(empty.shift()); // undefined

undefined 반환만으로 ‘배열이 비어 있었다’고 단정할 수는 없습니다. 마지막 요소 자체가 undefined여도 같은 반환값이 나옵니다. 비었는지 알아야 한다면 호출 전 items.length === 0을 확인하세요. MDN의 Array.pop() 문서와 Array.shift() 문서를 참고하세요.

전체 예제: 네 동작을 이어서 시험하기

아래 코드를 UTF-8로 array-ends.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>
<label for="value">추가할 값</label>
<input id="value" type="text" value="four">
<button id="push" type="button">push: 뒤에 추가</button>
<button id="unshift" type="button">unshift: 앞에 추가</button>
<button id="pop" type="button">pop: 뒤에서 제거</button>
<button id="shift" type="button">shift: 앞에서 제거</button>
<button id="reset" type="button">처음으로</button>
<pre id="output" aria-live="polite"></pre>
<script>
const original = ['one', 'two', 'three'];
let items = original.slice();
const value = document.querySelector('#value');
const output = document.querySelector('#output');

function show(label, returned) {
  output.textContent = `${label} 반환값: ${String(returned)}\n` +
    `현재 배열: ${JSON.stringify(items)}\n길이: ${items.length}`;
}

function add(method) {
  const text = value.value.trim();
  if (text === '') {
    output.textContent = '추가할 값을 입력하세요.';
    return;
  }
  const returned = method === 'push' ? items.push(text) : items.unshift(text);
  show(`${method}()`, returned);
  value.value = '';
}

document.querySelector('#push').addEventListener('click', () => add('push'));
document.querySelector('#unshift').addEventListener('click', () => add('unshift'));
document.querySelector('#pop').addEventListener('click', () => show('pop()', items.pop()));
document.querySelector('#shift').addEventListener('click', () => show('shift()', items.shift()));
document.querySelector('#reset').addEventListener('click', () => {
  items = original.slice();
  value.value = 'four';
  show('초기 상태', '-');
});
show('초기 상태', '-');
</script>
</body>
</html>

처음 배열은 ["one","two","three"]입니다. 입력된 four를 push()로 추가하면 반환값 4와 뒤에 붙은 four가 보입니다. 그 뒤 pop()을 누르면 반환값은 four이고 처음 배열로 돌아옵니다. 값을 입력해 unshift()한 뒤 shift()하는 경우도 같은 방식으로 비교하세요. 모두 제거한 뒤 제거 버튼을 더 누르면 undefined가 나옵니다.

원본 보존이 필요한 경우

원본 배열을 그대로 두고 결과 배열을 만들려면 앞·뒤 추가에 concat()이나 배열 전개 구문을 사용할 수 있습니다. 양쪽에서 제거할 때는 slice(1) 또는 slice(0, -1)로 복사할 수 있습니다. 원본을 바꾸는 네 메서드와 새 배열을 만드는 방법은 사용하는 상태 관리 방식에 맞춰 선택하세요.