🌐 웹개발

Vue.js

점진적 JavaScript 프레임워크. 양방향 바인딩. 학습 곡선 낮음.

📖 상세 설명

Vue.js는 Evan You가 2014년 만든 점진적 JavaScript 프레임워크입니다. '점진적'이란 단순한 인터랙션부터 복잡한 SPA까지 필요에 따라 기능을 확장할 수 있다는 의미입니다. HTML 템플릿 문법, 양방향 바인딩, 직관적인 API로 학습 곡선이 낮습니다.

Vue 3는 Composition API를 도입했습니다. Options API(data, methods, computed)와 달리 setup() 함수 안에서 ref, reactive, computed, watch 등을 사용해 로직을 기능 단위로 구성합니다. 코드 재사용성과 TypeScript 지원이 크게 향상되었습니다.

Vue의 반응형 시스템은 Proxy 기반입니다. 데이터가 변경되면 자동으로 관련 DOM이 업데이트됩니다. ref()는 원시 값을, reactive()는 객체를 반응형으로 만듭니다. computed()는 의존성 기반 캐싱을, watch()는 부수 효과 처리를 담당합니다.

Vue 생태계는 Pinia(상태 관리), Vue Router(라우팅), Nuxt(SSR/SSG 프레임워크)로 구성됩니다. SFC(Single File Component)로 템플릿, 스크립트, 스타일을 하나의 .vue 파일에 작성하며, Vite와 완벽히 통합됩니다.

💻 코드 예제

<!-- Vue 3 Composition API 예제 (SFC) -->
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'

// 반응형 상태
const count = ref(0)
const name = ref('Vue')

// 계산된 속성
const doubleCount = computed(() => count.value * 2)

// 메서드
const increment = () => count.value++

// 감시자
watch(count, (newVal, oldVal) => {
  console.log(`count: ${oldVal} → ${newVal}`)
})

// 라이프사이클
onMounted(() => {
  console.log('컴포넌트 마운트됨')
})
</script>

<template>
  <div class="counter">
    <h1>Hello, {{ name }}!</h1>
    <p>Count: {{ count }} (Double: {{ doubleCount }})</p>
    <button @click="increment">+1</button>
    <input v-model="name" placeholder="이름 입력" />
  </div>
</template>

<style scoped>
.counter { padding: 20px; }
button { margin: 10px 0; }
</style>

🗣️ 실무에서 이렇게 말하세요

💬 프레임워크 선택에서
"Vue는 학습 곡선이 완만해서 팀 온보딩이 빠릅니다. HTML 템플릿이 익숙하고, 공식 문서가 한국어로 잘 되어 있어요. React보다 보일러플레이트가 적고, Angular보다 가볍습니다."
💬 면접에서
"Vue 3의 Composition API는 로직 재사용을 위해 도입되었습니다. Options API에서는 같은 기능의 코드가 data, methods, computed에 흩어졌는데, Composition API는 기능별로 모아서 composable 함수로 추출할 수 있습니다."
💬 코드 리뷰에서
"ref로 선언한 값은 스크립트에서 .value로 접근해야 하는데, 템플릿에서는 자동 언래핑돼서 .value 없이 써도 돼요. 그리고 reactive() 객체를 구조 분해하면 반응성이 끊기니까 toRefs()를 사용하세요."

⚠️ 흔한 실수 & 주의사항

reactive() 구조 분해로 반응성 손실

const { name } = reactive({ name: 'Vue' })로 하면 name은 더 이상 반응형이 아닙니다. toRefs()로 래핑하거나 ref()를 사용하세요.

v-if와 v-for를 같은 요소에 사용

v-if가 v-for보다 우선순위가 높아서 의도대로 동작하지 않습니다. template 태그로 분리하거나 computed로 필터링하세요.

올바른 패턴

script setup + TypeScript + Composition API 조합을 권장합니다. 상태 관리는 Pinia, 라우팅은 Vue Router, SSR이 필요하면 Nuxt를 사용하세요.

🔗 관련 용어

📚 더 배우기