Menu

React vs Vue: 코드를 나란히 놓고 보는 차이점

React와 Vue는 모두 컴포넌트로 사용자 인터페이스를 만드는 자바스크립트 도구입니다. 마크업(JSX와 템플릿), 변경에 반응하는 방식(불변 state와 리렌더링, 변경 가능한 반응형 ref), 그리고 생태계에서 공식 도구가 차지하는 비중이 다릅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

React와 Vue는 모두 컴포넌트로 사용자 인터페이스를 만드는 자바스크립트 도구이며(React는 자신을 라이브러리, Vue는 프로그레시브 프레임워크라고 부릅니다), 대부분의 개념을 공유합니다. props는 아래로, 이벤트는 위로, 반응형 state, 가상 DOM입니다. 실질적인 차이는 React가 JSX로 마크업을 쓰고 state를 setter로 교체하기를 기대하는 반면, Vue는 싱글 파일 컴포넌트 안의 HTML 템플릿으로 마크업을 쓰고 반응형 값을 직접 바꾸게 해 준다는 것입니다. 다음은 React로 만든 카운터입니다.

그리고 같은 카운터를 Vue 싱글 파일 컴포넌트(Counter.vue)로 만든 것입니다.

<script setup>
import { ref } from 'vue';

const count = ref(0);
</script>

<template>
    <button @click="count++">Clicked {{ count }} times</button>
</template>

useState(0)은 ref(0)이 되고, onClick은 @click이 되며, {count}는 {{ count }}가 됩니다. 눈에 보이는 차이는 count++입니다. Vue는 값을 그 자리에서 바꾸게 해 주고 반응성 시스템이 그것을 알아챕니다. React는 새 값을 건네받을 때만 다시 렌더링하므로 setCount가 필요합니다.

JSX와 싱글 파일 컴포넌트

React 컴포넌트는 JSX를 반환하는 자바스크립트 함수입니다. 조건은 &&나 삼항 연산자이고, 목록은 .map()이며, 스타일은 직접 고른 것(CSS 파일, CSS Modules, 유틸리티 프레임워크)에서 옵니다.

Vue 컴포넌트는 보통 블록 세 개를 가진 .vue 파일입니다. 로직을 위한 <script setup>, 마크업을 위한 <template>, 그리고 그 컴포넌트에만 CSS가 적용되는 선택적인 <style scoped>입니다. 템플릿은 디렉티브를 씁니다. v-if, v-for, 양방향 input 바인딩을 위한 v-model, 값을 바인딩하는 :prop, 이벤트를 듣는 @event입니다. 템플릿은 HTML을 아는 누구에게나 마크업을 읽기 쉽게 해 주고, JSX는 마크업 안에서 자바스크립트 전체를 쓰게 해 줍니다. Vue도 JSX를 쓸 수 있지만 React는 템플릿을 쓸 수 없으며, 각각의 코드 대부분은 기본 방식을 따릅니다.

다음은 비교할 두 번째 기능인 필터링된 목록입니다.

xyz를 입력해서 빈 메시지를 확인한 다음 지워 보세요. Vue 버전입니다.

<script setup>
import { ref, computed } from 'vue';

const fruits = ['Apple', 'Banana', 'Cherry', 'Grape', 'Mango', 'Peach'];
const query = ref('');

const visible = computed(() =>
    fruits.filter((f) => f.toLowerCase().includes(query.value.toLowerCase()))
);
</script>

<template>
    <input v-model="query" placeholder="Filter fruit" />
    <ul>
        <li v-for="fruit in visible" :key="fruit">{{ fruit }}</li>
        <li v-if="visible.length === 0">No match</li>
    </ul>
</template>

v-model은 value와 onChange 짝을 대체하고, computed는 일반 변수를 대체합니다. React에서는 컴포넌트 함수가 다시 실행되므로 visible이 렌더링마다 다시 계산되고, Vue에서는 computed가 그것을 캐시하고 query가 바뀔 때만 다시 계산합니다. 둘 다 key로 목록 항목을 구별합니다.

반응성 모델

둘 사이의 가장 깊은 차이입니다.

React: 불변 state와 리렌더링. state는 스냅샷입니다. 새 값으로 setter를 호출하면 React가 컴포넌트 함수를 다시 실행하고, 새 JSX를 이전 것과 비교하고, DOM을 업데이트합니다. React는 Object.is로 값을 비교하므로, 객체나 배열을 그 자리에서 바꾸고 같은 것을 다시 넘기면 아무 변화가 없는 것처럼 보입니다.

"push() in place"를 클릭하면 배열이 같은 객체이므로 화면에는 아무 변화가 없습니다. 그다음 "New array"를 클릭하면 렌더링에 pushed도 보입니다. 앞선 변경은 실제로 일어났고, React가 볼 이유가 없었을 뿐입니다. useState 페이지에서 이 패턴을 깊이 다룹니다.

Vue: 변경 가능한 반응형 값. ref나 reactive 객체는 누가 자기를 읽는지 기록합니다(ref는 .value getter로, reactive 객체는 프록시로). 거기에 값을 쓰면 Vue는 어떤 computed 값, watcher, 템플릿 부분이 그것에 의존하는지 정확히 알고 그것들만 업데이트합니다. Vue에서는 items.value.push('pushed')가 화면을 업데이트합니다. 형식적인 코드가 줄어드는 대신, 값이 모르는 사이에 바뀌지 않는다는 보장을 포기합니다.

일반적인 앱에서 의미 있을 만큼 어느 한 모델이 더 빠르지는 않습니다. React는 변경마다 더 많은 컴포넌트 코드를 실행할 수 있고, 작업을 건너뛰려면 메모이제이션(직접 쓰거나 React Compiler를 통해)에 의존합니다. Vue는 런타임에 의존성을 추적하므로 기본적으로 그 작업을 건너뜁니다.

Composition API와 훅

Vue 3의 Composition API와 React 훅은 같은 문제를 해결합니다. 관련된 state와 로직을 한데 모으고 컴포넌트 사이에서 재사용하는 것입니다. Vue는 재사용 가능한 함수를 컴포저블(useMouse())이라고 부르고, React는 커스텀 훅(useMouse())이라고 부릅니다. 코드가 언제 실행되는지 때문에 규칙이 다릅니다.

  • 실행 시점. Vue의 setup은 컴포넌트가 만들어질 때 한 번 실행됩니다. React 컴포넌트 함수는 렌더링마다 실행되고, 그 안의 훅도 함께 실행됩니다.
  • 순서 규칙. React는 호출 순서로 훅을 짝지으므로 조건문이나 반복문 안에서 호출할 수 없습니다. Vue에는 ref와 computed에 대해 그런 규칙이 없습니다. setup이 한 번만 실행되기 때문입니다.
  • 의존성. React의 이펙트와 메모는 직접 관리하는 배열에 의존성을 나열합니다. Vue의 watchEffect와 computed는 자기가 읽는 것을 자동으로 추적합니다.
  • 낡은 값. React 콜백은 이전 렌더링의 오래된 state 값을 붙잡을 수 있습니다(전형적인 setInterval 버그). Vue 콜백은 호출 시점에 count.value를 읽으므로 항상 현재 값을 봅니다.

React의 모델은 모든 렌더링을 props와 state의 순수 함수로 만들어서 테스트하고 이해하기 쉽습니다. Vue의 모델은 의존성 배열을 둘러싼 버그 한 종류를 없앱니다. 하나를 아는 개발자는 보통 다른 하나도 빠르게 익힙니다.

생태계

ReactVue
마크업JSX.vue 파일 안의 HTML 템플릿(JSX는 선택)
state 업데이트setter로 교체한 뒤 리렌더링반응형 값을 바꾸면 의존하는 것이 업데이트
로직 재사용커스텀 훅컴포저블
파생 값렌더링 중에 계산, useMemocomputed(캐시됨)
양방향 input 바인딩value와 onChangev-model
범위 지정 CSS내장 아님(CSS Modules, 라이브러리)<style scoped> 내장
라우팅React Router, TanStack Router, 프레임워크Vue Router(공식)
전역 state컨텍스트, Zustand, Redux ToolkitPinia(공식)
풀스택 프레임워크Next.js, React Router 프레임워크 모드Nuxt
모바일 앱React Native공식 선택지 없음(Capacitor, NativeScript-Vue)
빌드 도구Vite 또는 프레임워크Vite
관리 주체Meta와 커뮤니티독립적인 코어 팀과 커뮤니티

이 표의 패턴은 이렇습니다. Vue의 코어 팀은 라우터, 스토어, 개발자 도구를 함께 관리하므로 Vue 프로젝트에는 각각에 대한 뻔한 기본값이 있습니다. React는 그것들을 커뮤니티에 맡기므로 선택지도 결정할 것도 더 많습니다. 두 쪽 모두에서 새 프로젝트의 일반적인 빌드 도구인 Vite는 Vue의 창시자가 시작했습니다.

학습 곡선

Vue가 더 완만한 출발인 경우가 많습니다. 템플릿은 이미 아는 HTML처럼 읽히고, v-model이 제어 input의 반복 코드를 없애며, 반응형 값을 바꾸면 화면이 업데이트됩니다. React는 처음부터 JSX와 불변 업데이트 습관을 요구하며, 대부분의 사람에게 가장 먼저 필요한 것은 JSX 페이지입니다.

기초를 지나면 차이가 좁혀집니다. Vue에는 자기만의 개념(ref와 reactive 객체, 스크립트에서는 쓰고 템플릿에서는 쓰지 않는 .value, watcher)이 더해지고, React에는 이펙트, 메모이제이션, 훅의 규칙이 더해집니다. 문법보다는 지역의 채용 공고가 더 쓸모 있는 결정 기준입니다.

언제 무엇을 고를까

다음과 같을 때 React를 고르세요.

  • 커뮤니티 라이브러리와 컴포넌트의 폭넓은 선택지를 원하거나, React Native로 네이티브 모바일 앱을 만들 계획일 때.
  • 로직과 마크업을 하나의 자바스크립트 함수에 두는 것을 좋아하고, Next.js 같은 프레임워크를 원할 때.
  • 팀이 렌더링마다 추적하기 쉬운 명시적이고 불변인 업데이트를 중요하게 여길 때.

다음과 같을 때 Vue를 고르세요.

  • 라우팅과 state를 위한 서로 맞춰진 공식 도구와, 내려야 할 결정이 적기를 원할 때.
  • 팀에 HTML 템플릿에 익숙한 디자이너나 백엔드 개발자가 있을 때.
  • 서버에서 렌더링하는 기존 페이지에 상호작용을 더할 때: Vue는 script 태그로 페이지에 넣고 거기서부터 키워 갈 수 있습니다.

둘 다 성숙했고 모든 규모의 회사가 프로덕션에서 쓰며, 하나에서 배운 개념(컴포넌트, props, 파생 state, key를 가진 목록)은 다른 하나로 그대로 이어집니다.

자주 묻는 질문

Vue가 React보다 쉬운가요?

많은 초보자가 처음에는 Vue를 더 쉽게 느낍니다. 템플릿이 일반 HTML처럼 보이고, 반응형 값을 바꾸면(count.value++) setter 없이 화면이 업데이트되기 때문입니다. React는 JSX와, state는 바꾸는 것이 아니라 교체해야 한다는 규칙을 배우라고 요구합니다. 처음 몇 주가 지나면 난이도는 비슷합니다.

React와 Vue 중 무엇이 더 나은가요?

일반적으로 어느 한쪽이 이기지는 않습니다. React는 라우팅과 state를 커뮤니티 라이브러리에 맡기고, 모바일을 위한 React Native가 있습니다. Vue에는 함께 관리되는 공식 라우터, 스토어, 개발자 도구가 있고, 많은 사람이 더 읽기 쉽다고 느끼는 템플릿이 있습니다. 팀이나 구직 시장이 쓰는 쪽을 고르세요.

Vue의 Composition API와 React 훅의 차이는 무엇인가요?

둘 다 상태 로직을 재사용 가능한 함수로 묶습니다. Vue의 setup은 컴포넌트마다 한 번 실행되고 의존성을 자동으로 추적하므로, 의존성 배열도 낡은 클로저도 없습니다. React 컴포넌트 함수는 렌더링마다 실행되므로 훅은 매번 같은 순서로 호출되어야 하고, 이펙트는 의존성을 나열합니다.

Vue는 JSX를 쓰나요?

Vue는 플러그인으로 JSX를 지원하지만, 대부분의 Vue 코드는 싱글 파일 컴포넌트(.vue 파일) 안의 HTML 템플릿을 씁니다. React는 거의 모든 곳에서 JSX를 씁니다.

Next.js에 해당하는 Vue의 도구는 무엇인가요?

Nuxt입니다. React의 Next.js처럼 Vue 위에 파일 기반 라우팅, 서버 렌더링, 정적 생성, 서버 라우트를 더합니다.

Coddy 프로그래밍 언어 일러스트

Coddy로 코딩 배우기

시작하기