불변성

ljjunh·2024년 11월 19일

clean-code-javascript

목록 보기
25/38
post-thumbnail

참조 타입의 함정 🤔

자바스크립트에서 배열은 참조 타입이기 때문에, 단순 할당으로는 새로운 복사본이 만들어지지 않는다.

const originArray = ['123', '456', '789'];
const newArray = originArray;  // 참조만 복사됨

// 원본 배열 조작
originArray.push(10);
originArray.push(11);
originArray.push(12);
originArray.unshift(0);

console.log(originArray); // [0, '123', '456', '789', 10, 11, 12]
console.log(newArray);    // [0, '123', '456', '789', 10, 11, 12]
// 😱 newArray도 같이 변경됨

1. 배열의 불변성을 지키는 방법 ✨

1.1 배열 복사하기

// 방법 1: 전개 연산자 사용
const safeCopy1 = [...originArray];

// 방법 2: slice() 메서드 사용
const safeCopy2 = originArray.slice();

// 방법 3: Array.from() 사용
const safeCopy3 = Array.from(originArray);

originArray.push(13);
console.log(originArray); // [..., 13]
console.log(safeCopy1);   // 원본 그대로 유지

1.2 불변성을 지키는 배열 메서드 활용

const numbers = [1, 2, 3, 4, 5];

// ❌ 원본 배열을 변경하는 메서드들
numbers.push(6);       // 원본 변경
numbers.pop();         // 원본 변경
numbers.unshift(0);    // 원본 변경
numbers.shift();       // 원본 변경
numbers.splice(1, 1);  // 원본 변경

// ✅ 새로운 배열을 반환하는 메서드들
const added = [...numbers, 6];          // 새 배열 반환
const filtered = numbers.filter(n => n > 3);  // 새 배열 반환
const mapped = numbers.map(n => n * 2);       // 새 배열 반환
const sliced = numbers.slice(1, 3);           // 새 배열 반환
const concatenated = numbers.concat([6, 7]);  // 새 배열 반환

1.3 불변성을 지키면서 배열 수정하기

const todos = [
    { id: 1, text: '자바스크립트 공부하기' },
    { id: 2, text: '리액트 공부하기' }
];

// ❌ 나쁜 예: 원본 배열 직접 수정
todos.push({ id: 3, text: '타입스크립트 공부하기' });

// ✅ 좋은 예: 새로운 배열 생성
const newTodos = [...todos, { id: 3, text: '타입스크립트 공부하기' }];

2. 불변성을 지켜야 하는 이유 🎯

  • 예측 가능성 : 원본 데이터가 어디서 변경될지 모르는 상황 방지
  • 디버깅 용이성 : 데이터 변경 추적이 쉬워짐
  • React 최적화 : React 등의 프레임워크에서 변경 감지가 정확해짐
  • 사이드 이펙트 방지 : 의도치 않은 데이터 변경 방지

3. Best Practices 💪

// ❌ 피해야 할 패턴
function addUser(users, newUser) {
    users.push(newUser);  // 원본 배열 변경
    return users;
}

// ✅ 권장하는 패턴
function addUser(users, newUser) {
    return [...users, newUser];  // 새로운 배열 반환
}

// 🚀 함수형 프로그래밍 스타일
const removeUser = (users, id) => users.filter(user => user.id !== id);
const updateUser = (users, id, updates) => users.map(user => 
    user.id === id ? { ...user, ...updates } : user
);

배열을 다룰 때는 항상 "이 작업이 원본을 수정하는가?"를 생각해보자. 가능하면 항상 새로운 배열을 반환하는 메서드를 사용하거나, 명시적 배열을 복사한 후 작업하는 것이 안전하다.

profile
Hello

0개의 댓글