JavaScript - 표면 복사: 초보자 가이드

안녕하세요, 미래의 JavaScript 마법사 여러분! 오늘 우리는 JavaScript의 표면 복사 세계로 흥미로운 여정을 떠납니다. 프로그래밍에 새로운 사람이라고 걱정하지 마세요 - 나는 친절한 안내자가 되어 단계별로 설명해 드릴게요. 그럼 커피 한 잔 (또는 당신의 좋아하는 음료)을 챙겨서, 함께 뛰어들어 보겠습니다!

JavaScript - Shallow Copy

표면 복사는 무엇인가요?

표면 복사의 복잡한 부분을 알기 전에, 간단한 비유로 시작해 보겠습니다. 아름다운 그림이 있다고 가정해 봅시다. 그 그림을 복사하고 싶어요. 두 가지 선택지가 있습니다:

  1. 그림을 사진으로 찍는다 (표면 복사)
  2. 그림을 완전히 새로 그린다 (깊은 복사)

JavaScript에서 표면 복사는 사진을 찍는 것과 같습니다. 새로운 객체나 배열을 만들지만, 내부 요소는 원본과 동일한 요소에 대한 참조입니다.

표면 복사의 작동 방식

표면 복사를 만들 때:

  1. 새로운 객체나 배열이 생성됩니다
  2. 최상위 프로퍼티가 복사됩니다
  3. 중첩된 객체나 배열은 여전히 원본에서 참조됩니다

다음 코드를 보고 이를 실제로 확인해 보겠습니다!

// 원본 객체
let original = {
name: "Alice",
age: 30,
hobbies: ["reading", "swimming"]
};

// 표면 복사
let shallowCopy = Object.assign({}, original);

// 복사본을 수정합니다
shallowCopy.name = "Bob";
shallowCopy.hobbies.push("coding");

console.log(original);
console.log(shallowCopy);

이 코드를 실행하면 흥미로운 결과를 볼 수 있습니다:

{name: "Alice", age: 30, hobbies: ["reading", "swimming", "coding"]}
{name: "Bob", age: 30, hobbies: ["reading", "swimming", "coding"]}

name을 변경하면 복사본에만 영향을 미치지만, hobbies를 수정하면 두 객체 모두에 영향을 미칩니다. 이것이 표면 복사의 본질입니다!

깊은 복사 vs. 표면 복사

이제 표면 복사를 이해했으므로, 그 형제인 깊은 복사와 비교해 보겠습니다.

특징 표면 복사 깊은 복사
새로운 객체 생성
최상위 프로퍼티 복사
중첩된 객체/ 배열 복사 아니요 (원본 참조) 예 (새 복사 생성)
성능 더 빠르다 더 느리다
메모리 사용량 적다 많다

표면 복사를 사용할 때

표면 복사는 다음과 같은 경우에 유용합니다:

  1. 최상위 프로퍼티만 수정해야 할 때
  2. 성능이 문제되는 경우
  3. 새로운 참조를 만들고 싶을 때

깊은 복사를 사용할 때

깊은 복사는 다음과 같은 경우에 더 나은 선택입니다:

  1. 중첩된 프로퍼티를 수정할 때 원본을 영향을 미치지 않고
  2. 완전히 독립적인 객체 복사를 원할 때

JavaScript에서 표면 복사의 예

표면 복사를 JavaScript에서 어떻게 만드는지 몇 가지 일반적인 방법을 탐구해 보겠습니다!

1. Object.assign()

let original = { a: 1, b: { c: 2 } };
let copy = Object.assign({}, original);

copy.a = 5;
copy.b.c = 10;

console.log(original); // { a: 1, b: { c: 10 } }
console.log(copy);     // { a: 5, b: { c: 10 } }

여기서 Object.assign()는 표면 복사를 만듭니다. a를 변경하면 복사본에만 영향을 미치지만, b.c를 변경하면 두 객체 모두에 영향을 미칩니다.

2. 확장 연산자 (...)

let fruits = ["apple", "banana", ["grape", "orange"]];
let fruitsCopy = [...fruits];

fruitsCopy[0] = "pear";
fruitsCopy[2].push("kiwi");

console.log(fruits);     // ["apple", "banana", ["grape", "orange", "kiwi"]]
console.log(fruitsCopy); // ["pear", "banana", ["grape", "orange", "kiwi"]]

확장 연산자는 배열의 표면 복사를 만듭니다. 첫 번째 요소를 변경하면 복사본에만 영향을 미치지만, 중첩된 배열에 추가하면 두 개 모두에 영향을 미칩니다.

3. Array.from()

let numbers = [1, 2, [3, 4]];
let numbersCopy = Array.from(numbers);

numbersCopy[0] = 10;
numbersCopy[2].push(5);

console.log(numbers);     // [1, 2, [3, 4, 5]]
console.log(numbersCopy); // [10, 2, [3, 4, 5]]

Array.from()도 표면 복사를 만듭니다. 최상위 요소는 복사되지만, 중첩된 배열은 여전히 참조됩니다.

표면 복사의 중요성

"왜 표면 복사가 필요한가요?"라는 생각이 드실 수 있습니다. 훌륭한 질문입니다! 표면 복사는 많은 시나리오에서 매우 유용합니다:

  1. 성능: 표면 복사는 깊은 복사보다 더 빠르고 메모리 사용량이 적어, 큰 객체나 빈도 높은 연산에 적합합니다.
  2. 불변성: 표면 복사는 코드에서 불변성을 유지하는 데 도움이 되어, 현대 JavaScript 프레임워크에서 예측 가능한 상태 관리에 필수적입니다.
  3. 부작용 피하기: 표면 복사를 사용하면 원본 객체를 직접 변경하지 않고 객체를 수정할 수 있어, 예상치 못한 부작용을 줄일 수 있습니다.
  4. React와 Redux: React와 Redux 애플리케이션에서는 표면 복사를 자주 사용하여 재렌더링을 유도하고 상태를 업데이트합니다.

다음은 실제 세계의 예입니다:

function updateUserProfile(user, newName) {
// 사용자 객체의 표면 복사를 만듭니다
let updatedUser = Object.assign({}, user);

// 이름을 업데이트합니다
updatedUser.name = newName;

return updatedUser;
}

let user = {
name: "Alice",
age: 30,
address: {
city: "Wonderland",
street: "Rabbit Hole Lane"
}
};

let updatedUser = updateUserProfile(user, "Alicia");

console.log(user);        // 원본 사용자 객체는 변경되지 않음
console.log(updatedUser); // 새로운 객체에 이름이 업데이트됨

이 예제에서 우리는 사용자의 이름을 수정하지만 원본 객체는 변경되지 않습니다. 이는 상태 관리에서 자주 사용되는 패턴으로, 데이터의 일관성을 유지하는 데 도움이 됩니다.

결론

축하합니다! 지금까지 JavaScript의 표면 복사 세계로 첫 걸음을 떠났습니다. 표면 복사는 빠르고 효율적이지만, 모든 세부 사항을 포함하지 않은 '사진'과 같습니다.

JavaScript 여정을 계속하면서, 표면 복사가 유용한 상황을 많이 만날 것입니다. 복잡한 데이터 구조와 상태 관리에서 강력한 도구로 활용할 수 있습니다.

계속 연습하고, 호기심을 가지고, 실험을 두려워하지 마세요. 얼마 지나지 않아, 당신은 객체를 프로처럼 만들고 수정할 수 있을 것입니다!

행복하게 코딩하세요, 그리고 복사가 항상 필요한 만큼 표면적이거나 깊을 수 있기를 바랍니다! ?

Credits: Image by storyset