티스토리 뷰

이 포스팅은 미완입니다.

써놓은 포스팅임에도 불구하고 미완이라니, 그럼 굳이 왜 써놓는거지? 싶은 생각을 하실 수도 있는데...
사실 앞선 포스팅(Javascript의 불변성)에서 설레발치듯 '밑밥'이라는 표현을 써서 이렇게 빈 포스팅을 남겨두게 되었습니다(밑밥을 깔아뒀더니 순서상 다른 주제로 포스팅하기가 뭔가 애매해져서...이렇게 영역부터 차지해두려고 합니다)

그래도 미완이지만 포스팅을 하는김에 또 썰을 풀어보자면, 이번 포스팅에서 다루고싶었던 주제는
React.js와 Vue.js에서 데이터를 바라보는 관점, 혹은 다루는 차이에 대해서 작성을 하려고 했습니다.

저는 보통 기술 포스팅을 할 때면, 눈을 감고도 입에서 술술 나올만큼 완전히 체화된 지식을 바탕으로 포스팅하려하는 편입니다. 그러다보니, 아직 미진한 React의 지식을 바탕으로 쓰기엔, 본 포스팅에 모자람이 너무 많이보였고 그에따라 미완이라는 타이틀을 남겨두었습니다.

아마 시간이 좀 더 흐른 뒤 React에 대한 이해도와 지식이 지금보다 더 짙어지게되면, 그때 아랫내용들을 더 보충해서 미완의 딱지를 때도록 하겠습니다.



그래서 오늘 포스팅을 하려는 주제에 대해 간력하게나마 설명을 나열해보자면,
Vue.js에서는 배열형 데이터를 다룰 때, 아래와 같이 래핑된 메소드를 활용해야합니다.

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

이와 같은 메서드들은 배열의 변경을 감지하게 설계되어있고, 그에따라서 호출시 배열의 변경점을 기준으로 화면에 렌더링된 Vue의 갱신을 트리거하게 됩니다. 예를들어, 아래와 같은 코드가 있다고 한다면

<!-- items : ['apple', 'banana', 'carrot'] --> 
<div> 
    <div v-for="(item, idx) in items" :key="idx"> 
        {{idx}} : {{item}} 
    </div> 
</div>

이와 같은 형태로 렌더링되게 될 것입니다.

이때, items라는 배열형 데이터에 'potato'라는 값을 추가하려 한다면 Vue파일 내의 메서드, 혹은 라이프사이클 어딘가에 아래와 같은 push 메서드를 활용한 코드를 추가해주면 됩니다.

this.items.push('potato')

추가된 감자


근데, 최근에 React.js에 대해 공부를 조금씩하다보니,
이와 같은 배열형 데이터를 다룰 경우 React.js는 Vue.js와는 다른 형식을 취한다는 걸 알게되었습니다.

윗 예제를 바탕으로 설명하자면, Vue.js에서는 push나 pop과 같은 메서드를 바탕으로 원본 데이터에 변경사항이 있을 경우 리렌더링을 위한 트리거가 발동이 되지만, React.js는 원본 데이터를 변경하는 작업을 지양하라고 가이드하고 있습니다. 그래서 위와 같이 Vue.js에서 push로 했던 로직과 동일한 상황을 발생시키려면, setState라는 메서드를 호출해야하는데, 이때 setState에 전달되는 배열은 items.concat('potato') 라는 형태의 코드로 전달하게 됩니다.

여기서 concat은 Javascript에서 새로운 배열을 리턴하는 함수인데요.
즉, 원본 데이터인 'items'를 훼손하지않으면서 items에 새로운 요소인 'potato'를 추가한 새 배열을 리턴하여 'items'에 매핑함으로써, items라는 변수가 가리키는 값이 변경되었다고 캐치해내는 것입니다. 그림으로보면, 아래와 같은 꼴이 되는건데요.

어, 이 그림은?!
이전 포스팅인 Javascript의 불변성을 보고오신 분이라면, 익숙한 그림일거라고 생각합니다.
그리고 바로 여기서, 제가 왜 불변성을 먼저 포스팅했는지가 드러나게 됩니다.

기존에 items라는 변수는 ['apple','banana','carrot'] 라는 배열형 데이터를 '값'으로 가리키고있었고, 우리는 concat을 통해서 potato를 추가했기 때문에, 기존의 ['apple','banana','carrot']와는 전혀 다른 ['apple','banana','carrot','potato'] 라는 배열형 데이터를 '값'으로 가리키게 된 것이죠(아, 혹시나해서 덫붙입니다만...실제 메모리 한 곳에 저렇게 모든 배열이 들어가지는 않습니다. 배열의 각 인덱스별로 나뉘어서 들어갑니다, 그림은 예시를 위해서 저렇게 했을 뿐...)

그리고 여기서 바로 '불변성(Immutability)'이 지켜지게 되는 겁니다.
왜냐면, ['apple','banana','carrot'] 라는 데이터는 변하지 않았거든요.

이 불변성이 React.js에서 중요한 포인트로 활용되는 이유는 아래와 같이 2가지 이유인 것 같습니다.
(사실 더 있을지도 모르지만...아직 React.js에 대한 공부가 미진하여 2개만...)

우선, React.js는 setState 메서드를 통해서 기존에 가지고 있던 state의 값과 새롭게 set하는 값을 비교해서, 해당 컴포넌트...혹은 요소의 변경을 트리거합니다. 마치 Vue.js에서 push나 pop을 호출하면 데이터의 변경에 따라 Vue 컴포넌트의 변경이 트리거되었듯이 말이죠. 따라서, React.js는 이와같이 불변성을 지키며 전혀 다른 메모리에 할당된 값과 기존에 값을 비교하는 절차를 바탕으로 컴포넌트의 트리거를 발동시키게 됩니다.

또하나는, 브라우져 GC적인 관점에서도 유효한 포인트를 가질 수 있습니다.
2012년을 기준으로 모든 최신 브라우져는 Mark-and-sweep 알고리즘을 바탕으로 Garbage Collection이 동작하게 되어있는데요. 만약, 위와 같이 items라는 변수가 가리키는 값이 변경되었다면 기존에 ['apple','banana','carrot'] 라는 값을 참조하는 변수는 없는 상황이되고 이는 해당 값이 GC의 정리 대상이 된다는 것을 의미합니다.

이 GC의 관점이 유효한 이유는, 위와 같이 간단한 코드가 아니라 웹 서비스가 가지는 로직이 복잡해지면 복잡해질수록 화면에서 다루게 되는 데이터이 양도 많아지게되고 그에따라 메모리에 적재된 각 데이터들을 참조하는 변수도 N:N의 형태를 띄게 될지도 모릅니다. 이와 같은 경우, 미처 인지하지 못 한 실수로 인해 활용하지 않는 값임에도 불구하고 메모리상에 남아있게 되는데, 이를 보통 Memory leak(메모리 누수)이라고하며 웹 서비스의 성능을 저하시키는 주효 원인이기도 합니다.


참고사이트
1. Vue.js 리스트 렌더링 : https://kr.vuejs.org/v2/guide/list.html
2. React : https://ko.reactjs.org/docs/react-component.html#state

댓글
최근에 올라온 글
Total
Today
Yesterday