상태의 배열 업데이트하기

상태의 배열 업데이트하기

배열도 상태에 넣을 수 있어요. 다만 객체와 마찬가지로 배열을 상태에 넣으면 그 배열을 바꿀 수 없어요. 배열을 업데이트하고 싶다면 새 배열을 만들어 상태 설정 함수에 전달해야 해요. 이 글에서는 배열의 추가·제거·정렬·중첩 객체 업데이트를 어떻게 안전하게 다루는지 정리할게요.

출처: https://react.dev/learn/updating-arrays-in-state

배열을 변형하지 않고 업데이트하기

배열을 업데이트할 때마다 상태 설정 함수에 새 배열을 전달해야 해요. 기존 배열에서 filter()map() 같은 비변형(non-mutating) 메서드를 호출해 새 배열을 만들면 돼요.

작업 피하기 (배열 변형) 선호 (새 배열 반환)
추가 push, unshift concat, [...arr] 스프레드 문법
제거 pop, shift, splice filter, slice
정렬 reverse, sort 먼저 복사본 만들기

배열에 항목 추가하기

배열 스프레드 문법으로 항목을 뒤에 붙이거나, 앞에 추가할 수도 있어요.

setArtists([
  { id: nextId++, name: name },
  ...artists  // 기존 항목은 뒤로
]);

배열의 다른 변경

배열을 복사했다고 해서 그 안의 기존 항목을 직접 변형하면 안 돼요. 복사는 얕은(shallow) 복사라서, 복사한 배열의 항목 객체는 원본 배열과 같은 객체를 가리켜요. nextList[0].seen을 바꾸면 list[0].seen도 함께 바뀌는 상태 변형이 되어버려요.

배열 안의 객체 업데이트하기

객체는 진짜로 배열 "안에" 있는 게 아니에요. 배열 각 요소는 별개의 값이고, 배열이 그 값을 "가리킵니다." 그래서 list[0] 같은 중첩 필드를 바꿀 때는 조심해야 해요.

중첩 상태를 업데이트할 때는 바꾸려는 지점부터 최상위까지 복사본을 만들어야 해요.

map을 쓰면 변형 없이 기존 항목을 수정된 버전으로 교체할 수 있어요.

setMyList(myList.map(artwork => {
  if (artwork.id === artworkId) {
    // 변경 사항이 있는 *새* 객체 생성
    return { ...artwork, seen: nextSeen };
  } else {
    // 변경 없음
    return artwork;
  }
}));

원칙 정리

일반적으로 방금 만든 객체만 변형할 수 있어요. 예를 들어 새 artwork를 삽입할 때는 그 객체 자체를 변형해도 되지만, 이미 상태에 있는 무언가를 다룰 때는 복사본을 만들어야 해요.

요약

  • 배열을 상태에 넣을 수 있지만, 그 배열을 바꿀 수는 없어요.
  • 배열을 변형하는 대신 새 버전을 만들어 상태를 그걸로 갱신해요.
  • [...arr, newItem] 배열 스프레드 문법으로 새 항목이 포함된 배열을 만들 수 있어요.
  • filter()map()으로 필터링되거나 변형된 항목이 들어간 새 배열을 만들 수 있어요.

더 알아보기