[JavaScript] 얕은 복사와 깊은 복사, React에서 이 개념을 알아야되는 이유

ujinsim·2025년 5월 6일
0
post-thumbnail

React에서 상태 관리와 데이터 변경을 다룰 때, 깊은 복사 (Deep Copy)얕은 복사 (Shallow Copy)의 개념은 매우 중요합니다. 이러한 복사 방식은 주로 불변성 (Immutability)을 지키는 데 사용되며, React의 성능과 렌더링 효율성을 높이는 데 큰 역할을 합니다.

1. 원시 타입과 참조형 타입의 차이점

  • 원시 타입 (Primitive Types): JavaScript의 숫자, 문자열, 불리언, null, undefined와 같은 타입을 포함합니다. 원시 타입은 값 자체를 저장하고, 변수에 값을 할당해도 다른 변수에는 영향을 주지 않습니다.
    • 예시:
      let a = 10;
      let b = a;
      b = 20;
      console.log(a); // 10
      console.log(b); // 20
      • ab는 독립적인 값으로, 하나를 변경해도 다른 변수에는 영향을 미치지 않습니다.
  • 참조형 타입 (Reference Types): 객체, 배열, 함수 등으로, 변수에는 참조(메모리 주소)가 저장됩니다. 참조형 타입은 주소를 저장하고 있기 때문에, 하나의 객체를 여러 변수에 할당하면, 하나를 변경할 경우 나머지 변수들도 영향을 받습니다.
    • 예시:
      let obj1 = { name: 'Alice' };
      let obj2 = obj1;
      obj2.name = 'Bob';
      console.log(obj1.name); // 'Bob'
      console.log(obj2.name); // 'Bo
      • obj1obj2는 같은 객체를 참조하고 있기 때문에, 하나를 수정하면 다른 것도 변경됩니다.

2. 얕은 복사 (Shallow Copy)

얕은 복사는 객체의 1단계만 복사하고, 중첩된 객체는 여전히 원본 객체와 동일한 참조를 공유합니다. 이 말은 중첩된 객체나 배열에 변경이 일어나면 원본 객체에 영향을 미친다는 뜻입니다.

  • 예시:
    const clubInfo = {
      name: 'COW Club',
      members: [
        { name: 'John', fee: 100, part: 'Server', isAttending: true },
        { name: 'Sara', fee: 150, part: 'Web', isAttending: false }
      ]
    };
    
    const newClubInfo = { ...clubInfo }; // 얕은 복사
    
    // 중첩된 객체는 여전히 참조를 공유
    newClubInfo.members[0].fee = 200;
    
    console.log(clubInfo.members[0].fee); // 200
    console.log(newClubInfo.members[0].fee); // 200
    • 위 코드에서 newClubInfoclubInfo의 얕은 복사본을 만들었지만, members 배열 안의 객체는 여전히 같은 메모리 주소를 참조하고 있습니다. 따라서 newClubInfo.members[0]을 수정하면 clubInfo.members[0]에도 영향을 미칩니다.

3. 깊은 복사 (Deep Copy)

깊은 복사는 객체의 모든 중첩된 속성까지 독립적으로 복사하는 방식입니다. 깊은 복사를 사용하면 원본 객체와 복사본 객체가 서로 영향을 미치지 않습니다.

  • 예시:
    const clubInfo = {
      name: 'COW Club',
      members: [
        { name: 'John', fee: 100, part: 'Server', isAttending: true },
        { name: 'Sara', fee: 150, part: 'Web', isAttending: false }
      ]
    };
    
    const deepCopyClubInfo = JSON.parse(JSON.stringify(clubInfo)); // 깊은 복사
    
    // 깊은 복사본에서 변경
    deepCopyClubInfo.members[0].fee = 200;
    
    console.log(clubInfo.members[0].fee); // 100
    console.log(deepCopyClubInfo.members[0].fee); // 200
    • JSON.parse(JSON.stringify()) 방법은 객체의 깊은 복사를 수행합니다. 이 방식은 객체 내부의 모든 속성을 복사하고, 원본 객체와 복사본이 완전히 독립적인 객체로 존재합니다.

4. 얕은 복사 vs 깊은 복사: 어떤 경우에 사용해야 할까?

  • 얕은 복사배열이나 객체의 1단계 속성만 복사할 때 유용합니다. 중첩된 데이터가 없거나, 중첩된 데이터를 수정할 필요가 없는 경우 적합합니다.
  • 깊은 복사는 객체나 배열이 중첩된 구조를 가지고 있고, 중첩된 데이터까지 독립적으로 다뤄야 할 때 사용합니다.

5. React에서 불변성(Immutability)과 상태 관리

React에서는 상태를 직접 수정하지 않고, 새로운 객체를 생성하여 상태를 업데이트해야 합니다. 이 과정에서 불변성(Immutability)을 지키는 것이 매우 중요합니다. 불변성을 지키면 React가 상태 변화(예: setState)를 쉽게 추적하고, 효율적인 리렌더링을 할 수 있습니다.

  • 불변성을 유지하는 이유:
    • React는 참조 비교를 통해 상태 변경을 감지합니다. 상태를 변경할 때마다 새로운 객체를 생성하면, React는 이전 상태와 새로운 상태를 비교하여 리렌더링을 최적화할 수 있습니다.
    • 불변성을 유지하면 코드가 더 예측 가능하고, 상태 관리가 쉬워집니다.
  • 불변성 예시:
    const [members, setMembers] = useState([
      { name: 'John', fee: 100, part: 'Server', isAttending: true },
      { name: 'Sara', fee: 150, part: 'Web', isAttending: false }
    ]);
    
    // 불변성을 유지하면서 상태 업데이트
    const updateFee = (index, newFee) => {
      const updatedMembers = [...members]; // 얕은 복사
      updatedMembers[index] = { ...updatedMembers[index], fee: newFee }; // 중첩 객체 복사
      setMembers(updatedMembers); // 새로운 배열로 상태 업데이트
    };

퀴즈

  1. 얕은 복사와 깊은 복사에 대한 설명이 올바른 것은?
    1. 얕은 복사는 중첩된 객체까지 독립적으로 복사하고, 깊은 복사는 객체의 1단계만 복사한다.
    2. 얕은 복사는 객체의 1단계만 복사하고, 깊은 복사는 중첩된 객체까지 독립적으로 복사한다.
    3. 얕은 복사는 객체와 배열을 모두 복사하고, 깊은 복사는 객체만 복사한다.
    4. 얕은 복사는 값 타입만 복사하고, 깊은 복사는 참조 타입만 복사한다.
  2. 다음 중 깊은 복사를 수행하는 방법으로 올바른 것은?
    1. Object.assign()
    2. JSON.parse(JSON.stringify())
    3. ... (스프레드 연산자)
    4. slice()
  3. 불변성을 지키지 않았을 때 발생할 수 있는 문제는 무엇인가요?
    1. React의 리렌더링 최적화가 이루어지지 않거나 예기치 않은 동작이 발생할 수 있다.
    2. 상태 업데이트가 불가능해진다.
    3. 코드가 더 간결해진다.
    4. 상태를 직접 변경할 수 없게 된다.
  4. React에서 상태를 업데이트할 때 얕은 복사를 사용하는 이유는 무엇인가요?
    1. 값 타입만 복사하고, 객체 타입을 무시하기 위해서
    2. 중첩된 객체가 변경되지 않기 때문에
    3. 상태를 변경할 때 새로운 객체를 생성하여 불변성을 지키기 위해서
    4. React에서 상태를 직접 변경할 수 없기 때문에
  5. 스프레드 연산자를 사용한 얕은 복사의 예시로 올바른 코드는?
    1. const newObj = { ...obj };
    2. const newObj = obj;
    3. const newObj = Object.assign({}, obj);
    4. const newObj = JSON.parse(JSON.stringify(obj));
profile
프론트엔드 공부 중인 학생입니다. 💻👩‍🎤

0개의 댓글