React와 Vue
1. React.js의 특징
React의 모든 컴포넌트는 JSX를 사용한 렌더 함수를 통해 표현된다. JSX는 React를 위해 태어난 새로운 자바스크립트 문법으로, 과거 페이스북이 만들었던 PHP의 개량판 XHP에 그 기원을 두고 있다.
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
ReactDOM.render(<HelloMessage name="John" />, mountNode)
이 코드는 “Hello, John”라는 div를 생성하는 컴포넌트이다. React는 작성한 코드를 컴파일하는 과정을 꼭 거쳐야 한다. 대부분 사실상 자바스크립트 표준이 되어가고 있는 Babel을 사용한다. Babel의 React 플러그인을 통해 위의 코드를 컴파일하면 다음과 같은 모습이 된다.
class HelloMessage extends React.Component {
render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
}
ReactDOM.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
이제 그냥 보통 자바스크립트 코드가 되었다. React는 Babel과 같은 트랜스파일러를 꼭 써야하기 때문에 Webpack 등을 통한 꽤 까다로운 초기 세팅이 필수적이다.
2. Vue.js의 특징
Vue.js는 여러모로 하이브리드형 프레임워크다. Angular의 양방향 바인딩과 React의 Virtual Dom 을 지원한다. 게다가 Flux 의 저장소 패턴을 구현한 vuex 를 통해 리액트의 단방향 데이터 바인딩도 활용 가능하다. jQuery 와 같이 cdn을 이용한 사용법까지 지원해서 유연성면에서는 가장 뛰어나며, 레거시 시스템을 점진적으로 개선할 때도 적합하다. vue.js의 .vue 파일(Single File Component)은 마크업과 스크립트, 스타일이 한 파일에 모여있다.
<template>
<div>
<h1></h1>
</div>
</template>
<script>
export default {
data () {
return {
message: 'Hello World'
}
}
}
</script>
<style>
h1 {
text-align: center;
}
</style>
3. React와 Vue의 공통점
- 가상 DOM을 활용한다.
- 반응적이고 조합 가능한 컴포넌트를 제공한다.
- 코어 라이브러리에만 집중하고 있고 라우팅 및 전역 상태를 관리하는 컴패니언 라이브러리가 있다.
- 속도는 비슷하게 빠르다.
4. React와 Vue의 차이점
4-1. 최적화 방식
둘은 최적화 방식이 다르다. React에서는 컴포넌트의 state가 변경되면, 해당 컴포넌트를 루트로 시작해 전체 자식 컴포넌트들을 다시 렌더링(re-render) 한다. 자식 컴포넌트의 불필요한 렌더링을 줄이려면 shouldComponentUpdate()
메소드를 사용해야 한다. shouldComponentUpdate()
는 자식 컴포넌트의 렌더링이 부모 컴포넌트로부터 받은 props에 의해 결정되게 해준다. 아래는 shouldComponentUpdate()
메소드를 사용해 자식 컴포넌트의 렌더링 여부를 결정하는 예제.
class CounterButton extends React.Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
shouldComponentUpdate(nextProps, nextState) {
// true를 반환할 때만 렌더링이 된다.
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}
하지만 Vue는 렌더링을 할 때 컴포넌트의 종속성이 자동으로 추적된다. 따라서 상태가 변경될 때 실제로 어떤 컴포넌트를 다시 렌더링해야 하는지를 정확하게 알고 있다. 어떻게 보면 Vue의 컴포넌트들은 React의 shouldComponentUpdate()
의 메소드를 가지고 있고, 이 메소드가 알아서 동작하는 것과 비슷한 느낌이라고 할 수 있다. 즉 최적화되지 않은 Vue의 업데이트는 최적화되지 않은 React보다 훨씬 빠르다.
4-2. JSX vs Template
JSX
React의 모든 컴포넌트는 JSX를 사용한 렌더 함수를 통해 표현된다. JSX를 사용하면 온전히 자바스크립트만을 이용해서 화면을 만들 수 있다. 따라서 같은 스코프 내에서 자바스크립트의 값을 직접적으로 가져다 쓸 수도(참조) 있다. Vue에서도 렌더링 함수와 JSX를 지원하지만 기본적으로는 템플릿을 사용한다. 아래는 JSX를 사용한 예시.
<div id="app"></div>
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: 'Hello React.js!'
};
}
reverseMessage() {
this.setState({
message: this.state.message.split('').reverse().join('')
});
}
render() {
return (
<div>
<p>{this.state.message}</p>
<button onClick={() => this.reverseMessage()}>
Reverse Message
</button>
</div>
)
}
}
ReactDOM.render(App, document.getElementById('app'));
Template
템플릿은 HTML과 비슷하기 떄문에 러닝 커브가 낮고, HTML으로 작업한 기존 애플리케이션을 Vue로 이전하기가 쉽다. 아래는 템플릿 형식으로 작성한 예시.
<template>
<div id="app">
<p></p>
<button v-on:click="reverseMessage">Reverse Message</button>
</div>
</template>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('');
}
}
});
4-3. React와 Vue의 불변성
React에서 state 는 불변(immutable)의 속성을 가진다. 그래서 직접적으로 변경할 수 없다. 만약 상태를 변경하고 싶다면 아래처럼 setState()
를 사용해야 한다.
this.setState({
message: this.state.message.split('').reverse().join('')
});
React는 현재와 이전 상태를 비교하여 언제, 어떻게 다시 DOM 을 렌더링 할지 결정한다. 그렇기 때문에 불변하는 속성이 필요하다.
반대로, Vue 에서 data 는 변경될 수 있다. 아래는 위의 React 의 message 와 같은 data 속성을 직접 변경하는 모습이다.
// 아래의 message 속성은 Vue 인스턴스에서 접근 할 수 있습니다.
this.message = this.message.split('').reverse().join('');
Vue의 렌더링 시스템이 React보다 효율성이 떨어진다고 결론짓기 전에, Vue가 실제로 어떻게 렌더링을 하는지 더 자세히 살펴보자. state 에 새로운 객체를 추가했을 때, Vue 가 해당 객체의 모든 속성을 확인하고 나서 getter 와 setter 로 변환한다. 그리고 Vue의 reactivity system 이 모든 상태를 모니터링하여 변경이 일어날 때마다 자동으로 DOM 을 다시 렌더링한다.