AngularJS를 사용하다보면 객체를 복사하는 경우가 종종 있습니다. 보통은 angular.copy를 통해서 복사를 하는데요 운영 소스중에 angular.extend라는 것을 발견해서 차이가 뭔지 궁금해서 찾아보았습니다. 이번에 정리할 Copy, Extend, Merge는 모두 AngularJS에 내장되어있는 함수인데 영어단어 의미대로 객체 또는 배열을 복사, 확장, 병합하는 기능을 합니다. 각각의 차이점을 정리해보도록 하겠습니다.
Copy (복사)
angular.copy는 이미 사용하고 있던것으로 객체를 복사할 때 사용합니다. 복사가 필요한 경우는 원본 객체를 유지하되 수정이 필요할 경우가 있을 수 있습니다.
var obj1 = { key: 'object1', value: 'test1' };
var obj2 = angular.copy(obj1);
console.log(obj2);
console.log(obj1 === obj2);
console.log(obj1.value === obj2.value);
console.log(obj1.value == obj2.value);
실행결과
{ key: 'object1', value: 'test1' }
false
false
true
결과를 보면 obj1를 복사한 obj2는 들어있는 데이터는 같을지라도 서로 다른 객체임을 알 수 있습니다. 즉, 복사 결과로 객체의 사본을 뱉는다는 것을 알 수 있습니다.
위의 콘솔 결과에서 한가지 더 알 수 있는 것은 바로 ===비교연산자와 ==비교연산자의 차이점인데요 ===는 객체를 비교할 때는 해당 객체가 같은 객체인지를 비교하고 기본타입 즉, int, string 등은 값과 타입까지 비교를합니다. 그에 비해 ==는 객체를 비교할 때 안에 들어있는 값만 비교를 하고 기본타입 또한 타입은 비교하지않고 값만 비교하게 됩니다. 그래서 저는 보통 자바스크립트 영역에서 비교연산을 할 때 ==보다는 ===를 선호하는 편입니다. 왜냐하면 ==로 비교할 경우 나중에 혹시모를 문제가 생길 수 있기 때문이죠. 가능성은 줄일 수록 안전하고 단단한 프로그램이 되니까요.
Extend (확장)
angular.extend(dst, src1, src2) 는 원본 객체의 속성을 대상 객체의 오른쪽에서 왼쪽으로 복사합니다. 어렵게 말로 설명하는 것보다 실행결과를 한번 보는게 훨씬 이해가 빠를것입니다.
var src1 = { key: 'key1', value: 'test1' };
var src2 = { sub_key: 'sub_key1', value: 'test2' };
var dst = {};
angular.extend(dst, src1, src2);
console.log(dst);
console.log(src2.value === dst.value);
실행결과
{ key: 'key1', value: 'test2', sub_key: 'sub_key1' }
true
실행결과를 보니 extend가 어떤 기능을 하는지 확실하게 알 수 있네요. 위의 결과로 또 한가지 더 알 수 있는 것은 copy와는 다르게 복사된 객체는 사본이 아닌 동일한 객체를 단순히 주소값을 공유하는 것이라고 할 수 있겠네요.
Merge (합병)
angular.merge는 angular.extend와 비슷한 기능을 합니다.
var src1 = { key: 'key1', value: 'test1' };
var src2 = { sub_key: 'sub_key1', value: 'test2' };
var dst = {};
angular.merge(dst, src1, src2);
console.log(dst);
console.log(src2.value === dst.value);
실행결과
{ key: 'key1', value: 'test2', sub_key: 'sub_key1' }
false
merge의 결과는 extend과 같은 객체를 뱉어내내요. 그런데 extend와는 다르게 동일한 객체가 아닙니다. 즉, Extend와 Merge 둘 다 병합하는 기능을 하지만 차이점은 Extend는 동일한 객체를 공유 즉, 주소값을 공유하고 Merge는 Copy처럼 사본을 가지고 있네요.
Extend와 Merge의 차이점
위에서 밝혀진 차이점 말고도 둘의 차이점은 하위 속성이 있는 객체를 통해서 더욱 명확하게 밝혀집니다. Extend는 하위속성이 있는 객체를 복사하게 되면 하위 속성을 복사되지 않습니다. 그에 반해 Merge는 하위속성까지 복사가 됩니다.
AngularJS에도 설명되어있는 Extend와 Merge의 차이점은 angular.extend는 Shallow copy(얕은 복사) angular.merge는 Deep (recursive) copy(깊은복사) 라고 표현합니다. 이러한 차이점을 알고 적용하는게 좋을 거라 판단되어 정리해보았습니다.
※ 틀린 내용이 있다면 혹은 더 보충해주실 말씀이 있거나 지적사항이 있다면 답글로 남겨주세요! 환영합니다.
추가내용
주기적으로 목록을 업데이트해주어야하는 경우 (예를들어 10초마다 목록을 조회해서 출력해주어야하는 상황) merge를 써서 기존에 있는 객체에 대해서 바뀐 부분만 덮어쓰기 한다는 느낌으로 사용하시면 됩니다. extend를 사용할 경우 새로운 객체를 반환하기 때문에 too way binding이 되어있는 DOM에 대해서 10초마다 다시 rendering하는 현상이 발생하게 되어 사용자가 매우 불편해질것입니다. 따라서 이런 상황에서는 extend 보다는 merge를 사용하시는게 좋습니다.
이 글은 UI Lab을 참고하여 작성되었습니다.