React : Shallow copy & deepCopy

★ 단순배열(값으로만 이루어진)의 경우 얕은복사(참조) 깊은복사(값)처리가 정상적으로 이루어지지만
     객체를 포함하고 있는 배열의 경우 객체들은 복사되지않음 (값은 정상적으로 깊은복사가됨)

ㆍ1) 단순배열의 얕은복사와 깊은 복사

const  [ data , setData ] = useState([1,2,3,4,5,6,7]);
const myDataShallow = data;  // 앝은복사  myDataShallow 은 원본 data 를 “참조”

  console.log(‘myDataShallow === data : ‘ , myDataShallow === data) // true : 같은 객체 (참조)
  myDataShallow[1] = 22   // myDataShallow[1] 의 값을 변경 했지만 data를 [참조]하고 있기때문에  같이변함
  console.log(data[1])    // 22 출력
  console.log(myDataShallow[1]) // 22출력

  data[1] = 2 // 다음테스트를위해 원래대로 값 변경
 
  const myDataDeep = […data]; // 깊은복사  myDataDeep 은 원본 data 에서 “복사” (… 전개연산자 이용)
  console.log(‘myDataDeep === data : ‘ , myDataDeep === data); // false : 다른객체( 데이터만 복사)
  myDataDeep[1] = 22 // myDataDeep[1] 의 값을 변경 했지만 data의 값만 [복사] 했기때문에 data 는 변경되지 않음
  console.log(data[1]) // 2 출력   
  console.log(myDataDeep[1]) // 22 출력
 

ㆍ2) 객체를 가진 배열의 2중 구조(이상) 에서의 얕은복사 와 깊은복사
  const  [ Info , setInfo] = useState([
        { name:’Michael’ ,  tel : [‘010-0000-0000’ , ‘010-000-0001’] } ,
        { name:’Jhon’    , tel : [‘010-1111-0000’ , ‘010-111-1001’] } ,
        { name:’Steve’   , tel : [‘010-2222-0000’ , ‘010-222-2001’] } ,
  ])
 const myArrayShallow= Info; // // 앝은복사  myDataShallow 은 원본 data 를 “참조”
  myArrayShallow[0] = ‘My friend List’  
  myArrayShallow[1].tel[0] = ‘010-xxxx-xxxx’  
  myArrayShallow[1].name = ‘Json’  
  myArrayShallow[2].name = ‘Tom’  
 
  console.log(“Info[0]” , Info[0])
  console.log(“myArrayShallow[0]” , myArrayShallow[0])  
  console.log(“Info[1].name” , Info[1].name)  
  console.log(“Info[2].name” , Info[2].name)  
  console.log(“Info[1].tel[0]” , Info[1].tel[0])  

  console.log(“myArrayShallow[1].name” , myArrayShallow[1].name)    
  console.log(“myArrayShallow[2].name” , myArrayShallow[2].name)    
  console.log(“myArrayShallow[1].tel[0]” , myArrayShallow[1].tel[0])
 
  console.log(‘Info === myArrayShallow’, Info === myArrayShallow)
  console.log(‘Info[0] === myArrayShallow[0]’, Info[0] === myArrayShallow[0])
  console.log(‘Info[1] === myArrayShallow[1]’, Info[1] === myArrayShallow[1])
  console.log(‘Info[1].tel[0] === myArrayShallow[0].tel[0]’,Info[1].tel[0] === myArrayShallow[1].tel[0])
 

★ 참조에 의한 얕은복사(shallowcopy)는 요소 , 배열  ,배열깊은 객체들까지 모두 [참조]함
Info[0] : My friend List
myArrayShallow[0] My friend List
Info[1].name Json
Info[2].name Tom
Info[1].tel[0]  : 010-xxxx-xxxx
myArrayShallow[1].name Json
myArrayShallow[2].name Tom
myArrayShallow[1].tel[0] 010-xxxx-xxxx
Info === myArrayShallow true
Info[0] === myArrayShallow[0] true
nfo[1] === myArrayShallow[1] true
Info[1].tel[0] === myArrayShallow[0].tel[0] true

  const myArrayDeep =  […Info]  // 깊은복사  myArrayDeep 은 원본 Info 에서 값  “복사” 함 (… 전개연산자 이용)
 
  // 깊은복사 테스트를 위해 원래대로 변경
  Info[1].tel[0] = ‘010-0000-0000’  
  Info[0] = ‘friend List’  
  myArrayShallow[1].name = ‘Michael’  

 // 값 변경
  myArrayDeep[0] = ‘My friend List’  
  myArrayDeep[1].tel[0] = ‘010-xxxx-xxxx’  
  myArrayDeep[1].name = ‘Jenny’
  myArrayDeep[2].name = ‘Jackson’

 
  console.log(“Info[0]” , Info[0])
  console.log(“myArrayDeep[0]” , myArrayDeep[0])  
  console.log(“Info[1].name” , Info[1].name)  
  console.log(“Info[2].name” , Info[2].name)  
  console.log(“Info[1].tel[0]” , Info[1].tel[0])  

  console.log(“myArrayDeep[1].name” , myArrayDeep[1].name)    
  console.log(“myArrayDeep[2].name” , myArrayDeep[2].name)    
  console.log(“myArrayDeep[1].tel[0]” , myArrayDeep[1].tel[0])

  console.log(‘Info === myArrayDeep’, Info === myArrayDeep)
  console.log(‘Info[0] === myArrayDeep[0]’, Info[0] === myArrayDeep[0])
  console.log(‘Info[1] === myArrayDeep[1]’, Info[1] === myArrayDeep[1])
  console.log(‘Info[1].tel[0] === myArrayDeep[0].tel[0]’,Info[1].tel[0] === myArrayDeep[1].tel[0])

————– myArrayDeep[4][1] 400 으로 변경 —————————
myArrayDeep[4][1] 400 — 그래서 같이 변함(참조)
Info[4][1] 400   — 역시 2차원 배열에서도 깊은 복사가 안됨 
myArrayDeep[4][1] 400 — 그래서 같이 변함(참조)

————– myArrayDeep[5] 700 으로 변경 —————————
Info[5] 200 — 1차원 값 요소까지만 정상적으로 깊은 복사가됨(원본유지) — 정상
myArrayDeep[5] 700 — myArrayDeep[5] 는 700으로 변경된 값 그대로 출력

myArrayDeep[1].tel[0] 010-0000-0000
Info[0] friend List  
myArrayDeep[0] My friend List   — 0번 요소의 ‘값’들은  정상적으로 깊은 복사가 됨
Info[1].name Jenny  — 변경된값 출력
Info[2].name Jackson  — 변경된값 출력
Info[1].tel[0] 010-xxxx-xxxx
myArrayDeep[1].name Jenny — 0번 요소의 ‘값’이 아닌 객체들은 깊은복사가 안되고 , 얕은복사만된다
myArrayDeep[2].name Jackson — 0번 요소의 ‘값’이 아닌 객체들은 깊은복사가 안되고 , 얕은복사만된다
myArrayDeep[1].tel[0] 010-xxxx-xxxx
Info === myArrayDeep false
Info[0] === myArrayDeep[0] false //★[0] 요소는 값을 비교한다.(객체아님) 그래서 “friend list” 와 “My friend list” 비교 
Info[1] === myArrayDeep[1] true  // ★ 객체이기 때문에 참조를 비교, 깊은복사가 되지않아 같은 참조하고있음
Info[1].tel[0] === myArrayDeep[0].tel[0] true

ㆍ결론
ㆍ단순 1차원 배열(객체를 가지고 있지않은) 에서는 얕은복사와 깊은복사는 정상적으로 이루어짐
const  [ data , setData ] = useState([1,2,3,4,5,6,7]);

ㆍ객체(다차원배포함)를 포함한 배열에서의 얕은복사는 정상 이지만 ,깊은복사에서 배열안에 “객체들은 얕은복사”가 됨
   1차원의 값들은 정상적으로 깊은복사가됨
const  [
Info , setInfo] = useState([

       “friend List”,
        { name:’Michael’ ,  tel : [‘010-0000-0000’ , ‘010-000-0001’] } ,
        { name:’Jhon’    , tel : [‘010-1111-0000’ , ‘010-111-1001’] } ,
        { name:’Steve’   , tel : [‘010-2222-0000’ , ‘010-222-2001’] } ,

        [1,2,3],
        200,
  ])

[얕은복사] : 단순 배열일때와 같은 모든 요소가들이 참조로 복사된다.
[깊은복사]는  전개연산자를 통해 위의 info 배열을 다른 배열로 으로 복사(깊은복사)하면 1차원 요소들만 깊은복사 되며,

그 배열이 가지고 있는 객체들까지는 깊은복사가아닌 얕은복사가 되어 ‘참조’

info
객체 자체 , 그 다음 0,5 번째요소인 “friend List”200 만 정상적으로 깊은복사가 되고, 객체를 가진 요소는깊은 복사가 안됨(
얕은(참조) 복사가 됨)결국 0 번째요소의 “값” 은 정상적으로 깊은복사되지만 , “객체”는 여전히 얕은복사가 된다.)

그래서 Immer 를 이용하여 복잡한 객체를 가진 배열을 처리한다.

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다