2016-07-13 추가:
Vue.js 포럼에 한국어 사용자 카테고리가 추가되었고 해당 포럼에서 문서 한국어화를 진행한다고 한다. 이 문서 외 Vue.js에 관심이 있다면 해당 포럼을 확인해보자.
Vue.js 문서를 살펴보던 중에 Comparison with Other Frameworks 내용이 괜찮아서 짧게 번역했다. Vue.js의 문서답게 기승전vue.js 이긴 하지만 각각의 프레임워크가 어떤 특징이 있고 어떤 주요 이슈가 있는지 잘 정리되었다.
다른 프레임워크와 vue.js 비교
Angular
모두에게 적용될 만한 항목은 아니지만 Angular 대신에 Vue를 선택해야 할 이유가 몇 가지 있다.
- Vue.js는 API나 디자인 측면에서 Angular에 비해 훨씬 단순하다. 대부분의 내용을 빠르게 배울 수 있어서 생산성이 좋다.
- Vue.js는 더 유연하면서도 덜 의견지향적인 해결책을 제시한다. 이 특징은 모든 개발의 흐름을 Angular 방식에 맞춰 개발하는 접근 방식과 다르게 자신 스스로가 원하는 애플리케이션 구조를 사용할 수 있다. 이 라이브러리는 인터페이스 레이어(interface layer)에 해당하기 때문에 풍성한 SPA 기능 대신에 각 페이지에서 사용할 수 있는 가벼운 기능을 제공한다. 이러한 접근 방식은 다른 라이브러리와 조합해서 사용하는데 넉넉한 공간을 제공한다. 물론 구조적 결정에 대한 책임도 생긴다. 예를 들면 Vue.js 코어에서는 기본적으로 라우팅이나 ajax 기능이 포함되지 않는다. 그리고 애플리케이션을 만드는 대부분의 경우에 외부 모듈 번들러를 사용한다고 가정하고 있다. 이런 특징을 가장 중요한 차이로 볼 수 있다.
- Angular는 각 스코프(scope) 사이에서 양방향 바인딩(two-way binding)을 사용한다. Vue도 명시적 양방향 바인딩을 지원하긴 하지만, 기본 설정은 컴포넌트(component) 간, 부모에서 자식으로 단방향 바인딩(one-way)으로 구성되어 있다. 대형 앱에서는 단방향 바인딩을 사용하면 데이터의 흐름을 만들기 더 쉽기 때문이다.
- Vue.js는 디렉티브와 컴포넌트를 명확하게 분리한다. 디렉티브는 DOM 조작을 캡슐화한 기능이고 컴포넌트는 뷰 자신과 데이터 로직을 포함한 독립 단위를 뜻한다. Angular에서는 이 둘의 차이가 상당히 혼란스럽다.
- Vue.js는 변경 확인(dirty checking)을 수행하지 않기 때문에 좋은 성능을 제공하고 매우 매우 쉽게 최적화 할 수 있다. Angular는 감시자(watcher)가 늘어날 때마다 느려진다. 매번 스코프가 변경될 때마다 모든 감시자가 평가를 다시 수행하기 때문이다. 게다가 이 평가 흐름(digest cycle)에서 감시자가 다른 갱신을 수행하게 되면 모든 데이터가 “안정화(stabilize)” 될 때까지 반복하게 된다. Angular 사용자는 이런 상황을 해결하기 위해서 종종 난해한 기법을 사용하기도 하고 어떤 상황에서는 너무 많은 감시자가 있다보니 아예 간단하게 최적화 할 방법이 존재하지 않을 때도 있다. Vue.js를 사용한다면 이런 상황으로 고통 받을 필요가 없다. 비동기 큐 형태의 옵저버 시스템을 구현해서 의존성을 투명하게 관리하기 때문이다. 의존 관계가 명시적으로 기록되지 않았다면 모든 변경에 대해 독립적으로 이벤트를 호출한다. 앞으로 필요하게 될 최적화에 대한 힌트를 준다면
v-for
목록의 track-by
파라미터를 확인해보자.
Angular 1의 문제를 해결하기 위해서 Angular2 와 Vue가 접근한 방식이 다소 비슷하다는 점은 흥미로운 사실이다.
React
React와 Vue.js는 반응형 & 조합 가능한 뷰 컴포넌트를 제공한다는 점에서 유사점을 공유한다. 물론 많은 차이점도 존재한다.
먼저 내부 구현이 근본적으로 다르다. 리액트의 렌더링은 가상 DOM에 의해 이뤄진다. 가상 DOM은 메모리에서 실제 DOM이 어떤 형태로 존재하는지 저장하는 방식이다. 상태가 변경되면 React는 가상 DOM 전체를 다시 생성한 다음에 DOM을 비교하고 변경된 정보를 실제 DOM에 반영한다.
가상 DOM 접근은 뷰가 어떤 상황에서든 값에 따라 동일하게 동작하는 함수적 접근 방식을 제공하고 있으며 정말 좋은 방법이라 할 수 있다. 전체 앱을 매 차례 다시 생성한다면 관찰자를 만들 필요도 없고 뷰는 항상 데이터와 동기화 되어 있다는 점을 명확하게 보증하기 때문이다. 게다가 이 접근 방식은 동형(isomorphic) 자바스크립트 애플리케이션에 대한 가능성도 열었다.
Vue.js는 실제 DOM을 템플릿으로 사용하고 데이터를 실제 노드에 참조해서 사용하고 있다. 즉, Vue.js의 환경은 DOM에서 표현하는 방식으로만 사용 가능하다는 제약이 있다. React가 가상 DOM을 사용해서 다른 것에 비해 빠르다고 생각할 수 있지만 이 일반적인 오해와는 반대로 직접 갱신(hot update)에 있어서는 Vue.js가 React에 비해 손수 최적화하지 않고도 훨씬 빠르게 동작한다. React를 사용하는 경우에는 shouldComponentUpdate
을 모든 위치에 구현해야 하며 불변 데이터 구조를 사용해야 다시 렌더링하게 되는 경우에 완벽한 최적화를 수행할 수 있다.
API 단위에서 React(또는 JSX)의 문제는 함수를 렌더링하는데 종종 많은 로직이 동반되는 경우가 많고 결과적으로 인터페이스의 시각적인 표현보다는 그 자체로 작은 프로그램 조각이 되고 만다. 개발자 일부에게는 이런 특징이 이익으로 느껴지겠지만 나처럼 디자이너/개발자를 겸하는 사람에게는 템플릿을 만들어서 디자인과 CSS를 더 시각적으로 생각하는 방식이 훨씬 쉽게 느껴진다. JavaScript 로직이 섞인 JSX는 디자인에 코드를 적용하기 전까지 확인이 쉽지 않은 방식이다. Vue.js는 대조적으로 경량의 데이터 바인딩을 비용으로 지불하는 대신에 시각적으로 확인 가능한 템플릿을 제공하고 로직은 디렉티브와 필터를 사용해서 캡슐화 하는 방식을 사용한다.
React의 다른 문제는 DOM 갱신이 전적으로 가상 DOM에서 이뤄지기 때문에 DOM을 직접 제어하고 싶은 경우에 다소 까다롭다. (이론적으로 가능하긴 하지만 라이브러리의 방식에 반해서 작업 해야한다.) 애플리케이션에서 DOM 조작에 부차적인 제어가 필요한 경우에는 이런 제한적인 특성으로 인해 짜증나는 작업이 되고 만다. 특히 요구사항이 시간적 흐름에 따라 변화하는 애니메이션이 그렇다. 반면 이런 문제에서 Vue.js는 더 유연하기 때문에 큰 문제가 되질 않는다. FWA/Awwwards에서 수상한 사이트 다수가 Vue.js로 만들어진 이유가 거기에 있다.
아래는 몇 가지 살펴볼 만한 내용이다.
- React 팀은 React를 모든 플랫폼 UI 개발에서 사용하려고 하는 야망을 갖고 있는 반면에 Vue는 웹을 위한 실용적인 해결책을 제공하는데 촛점을 두고 있다.
- React는 함수적인 환경을 제공하고 있어서 함수형 프로그래밍 패턴과 아주 잘 맞는다. 이런 특징은 초보자나 주니어 개발자에게 큰 학습 장벽이 된다. Vue는 훨씬 간단하게 바로 사용할 수 있어서 더 효율적이다.
- 대형 애플리케이션을 개발하는 경우에 React 커뮤니티에서는 상태 관리를 위한 해결책으로 Flux, Redux와 같은 혁신이 있었다. Vue 자체는 이런 문제를 크게 괘념치 않는데 (React 코어도 동일하다.) 비슷한 아키텍쳐라면 상태 관리 패턴은 쉽게 이식할 수 있는 개념이다. Vue 자체에서 사용할 수 있는 상태 관리 솔루션으로 Vuex가 있고, Redux를 Vue와 사용하는 것도 가능하다.
- React 개발의 트랜드는 CSS까지 모든 것을 JavaScript에 집어넣는 분위기다. JS에 CSS를 넣는 많은 해결책이 존재하지만 각각 크고 작은 문제를 갖고 있다. 가장 중요한 문제는 표준 CSS 저작 경험을 벗어나고 있는데다 기존 CSS 커뮤니티가 일궈 놓은 작업을 이상하게 만드는데 지렛대 역할을 하고 있다. Vue의 단일 파일 컴포넌트는 컴포넌트 단위로 캡슐화된 CSS를 작성할 수 있고 선택에 따라서 전처리기를 선택하는 것도 가능하다.
Ember
Ember는 모든 기능을 제공하는 프레임워크로 아주 의견지향적으로 디자인되었다. 이 프레임워크는 많은 양의 컨벤션을 제공한다. 제공하는 모든 문법에 충분히 익숙해지면 아주 생산적으로 활용할 수 있다. 하지만 학습 곡선이 높은 데다 유연함이 고통을 준다. 의견지향적 프레임워크와 느슨한 의존성으로 묶인 여러 라이브러리 중 어느 것을 선택하느냐에 따라 얻거나 잃을 수 있는 부분이다. 후자를 선택하면 더 자유롭긴 하지만 구조적 결정을 내려야 하는 상황에 놓인다.
Vue.js 코어와 Ember의 템플릿, 개체 모델 레이어를 비교하는 것이 더 나을 것이다.
- Vue는 눈에 거슬리지 않는 반응성을 일반 JavaScript 개체를 통해 제공하며 모든 프로퍼티가 자동으로 연산된다. Ember에서는 모든 Ember 개체로 감싸야 하며 연산 프로퍼티를 사용하려면 수동으로 의존성을 선언해야 한다.
- Vue의 템플릿 문법은 JavaScript 표현식 전체를 사용할 수 있는 반면에 Handlebar 표현식과 헬퍼 문법은 다소 제한적이다.
- 성능에 있어서 Ember가 2.0에서 Glimmer 엔진으로 변경했는데도 여전히 Vue가 빠르다. Vue는 자동으로 일괄 갱신을 수행하는 반면 Ember는 성능에 민감한 상황에서 실행 순환을 수동으로 관리해야 할 필요가 있다.
Polymer
Polymer는 Google이 지원하는 또 다른 프로젝트다. 사실 Vue.js도 이 라이브러리에서 영감을 받고 만들었다. Vue.js의 컴포넌트는 Polymer의 커스텀 엘리먼트와 느슨하게 비교되는데 이 두 기능은 아주 비슷한 개발 스타일을 제공한다. 가장 큰 차이점은 Polymer가 최신 웹컴포넌트 기능 위에서 개발되었고 기능이 제공되지 않는 브라우저에서 사용하기 위해서는 폴리필이 필수적으로 필요하다. (폴리필이라서 성능도 떨어진다.) 이 특징과 대조적으로 Vue.js는 IE9까지 어떤 기술 의존 없이도 잘 동작한다.
또한 polymer 1.0 팀은 성능을 챙기기 위해서 데이터 바인딩을 매우 제한적으로 가능하게 만들었다. 예를 들면, Polymer 템플릿의 표현식은 불린 부정(boolean negation)과 단일 메소드 호출만 지원한다. 또한 연산 프로퍼티의 구현이 아주 경직되어 있다.
마지막으로 프로덕션에 배포할 때는 Polymer 엘리먼트를 Polymer에 특화된 도구인 vulcanizer를 사용해서 번들링 해야한다. 이와 대조적으로 Vue 컴포넌트는 단일 파일로 Webpack 생태계가 제공하는 모든 기능을 사용할 수 있다. 이 특징 덕분에 Vue 컴포넌트에 ES6도 쉽게 적용할 수 있고 CSS 전처리기도 필요하다면 바로 사용할 수 있다.
Riot
Riot 2.0은 유사한 컴포넌트 기반 개발 모델을 제공한다. (Riot에서는 “tag”라고 부른다.) 이 모델은 작고 아름답게 디자인된 API를 제공한다. 내 생각에는 Riot과 Vue는 디자인 철학을 많이 공유하고 있다. Vue는 Riot에 비해 조금 무겁지만 Riot에 비해 중요한 잇점을 제공한다.
- 참 조건부 렌더링 (Riot 렌더링은 브랜치에 있다면 모든 내용을 렌더링하고 단순히 보여주고 숨기는 기능만 수행한다.)
- 더 강력한 라우터 (Riot의 라우팅 API는 지나치게 단순하다.)
- 더 성숙한 도구 지원 (webpack + vue-loader를 확인한다.)
- 트렌지션 효과 시스템 지원 (Riot에는 없다.)
- 더 나은 성능 (Riot은 사실 가상 DOM보다 변경 확인(dirty checking)을 사용하고 있어서 Angular와 동일한 성능 이슈가 발생한다.)