4주차 — Vue(상세)
2026. 7. 22. 21:59ㆍJavascript
목표: React에서 배운 개념을 Vue 문법으로 다시 구현하며 비교 학습하고, 실무에 쓸 화면을 직접 만들어본다.
10회차 (2시간): Vue 시작
0:00~0:20 | 프로젝트 생성
npm create vite@latest my-vue-app -- --template vue
cd my-vue-app
npm install
npm run dev
0:20~0:50 | 템플릿 문법
- v-bind(속성 연결, :로 축약) / v-on(이벤트 연결, @로 축약)
<template>
<img :src="imageUrl" />
<button @click="handleClick">클릭</button>
</template>
- Composition API(<script setup>) 기준으로 진행 (Options API는 간단히 언급만)
0:50~1:20 | 반응형 데이터 (ref, reactive)
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
count.value++;
}
</script>
<template>
<button @click="increment">{{ count }}</button>
</template>
템플릿에서는 .value 생략, script에서는 .value로 접근
1:20~2:00 | 실습: Todo 앱 (React 8회차와 동일 예제)
<script setup>
import { ref } from 'vue';
const todos = ref([]);
const input = ref('');
function addTodo() {
if (!input.value) return;
todos.value.push({ id: Date.now(), text: input.value, done: false });
input.value = '';
}
function toggleTodo(id) {
const todo = todos.value.find((t) => t.id === id);
if (todo) todo.done = !todo.done;
}
</script>
<template>
<div>
<input v-model="input" />
<button @click="addTodo">추가</button>
<ul>
<li
v-for="todo in todos"
:key="todo.id"
:style="{ textDecoration: todo.done ? 'line-through' : 'none' }"
@click="toggleTodo(todo.id)"
>
{{ todo.text }}
</li>
</ul>
</div>
</template>
React vs Vue 비교
개념 React Vue
| 상태 선언 | const [x, setX] = useState() | const x = ref() |
| 상태 읽기 | x | x.value (템플릿에서는 생략) |
| 상태 변경 | setX(newValue) | x.value = newValue |
| 양방향 바인딩 | onChange + value 직접 구현 | v-model 한 줄 |
과제
- input에 v-model 적용해서 실시간 글자 수 표시
11회차 (2시간): 디렉티브 & computed/watch
0:00~0:25 | v-if/v-show, v-for
<p v-if="isLoggedIn">환영합니다</p>
<p v-show="isVisible">보임/숨김만 전환</p>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
0:25~0:55 | computed
<script setup>
import { ref, computed } from 'vue';
const todos = ref([{ done: true }, { done: false }]);
const doneCount = computed(() => todos.value.filter((t) => t.done).length);
</script>
<template>
<p>완료: {{ doneCount }}개</p>
</template>
0:55~1:15 | watch
<script setup>
import { ref, watch } from 'vue';
const keyword = ref('');
watch(keyword, (newVal) => {
console.log('검색어 변경:', newVal);
});
</script>
1:15~1:40 | props/emit
<!-- Child.vue -->
<script setup>
defineProps(['count']);
const emit = defineEmits(['increment']);
</script>
<template>
<button @click="emit('increment')">+1 ({{ count }})</button>
</template>
<!-- Parent.vue -->
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const count = ref(0);
</script>
<template>
<Child :count="count" @increment="count++" />
</template>
1:40~2:00 | 실습
- 부모-자식 컴포넌트 간 이벤트 주고받기
- Todo 앱에 완료/미완료 개수 computed로 추가
과제
- 부모-자식 구조로 상품 목록/상품 상세 화면 나눠서 구현
12회차 (2시간): Vue 실전 + 전체 마무리
0:00~0:30 | onMounted + fetch
import { ref, onMounted } from 'vue';
const posts = ref([]);
const loading = ref(true);
onMounted(async () => {
const res = await fetch('<a href=https://jsonplaceholder.typicode.com/posts?_limit=5');>https://jsonplaceholder.typicode.com/posts?_limit=5');</a>
posts.value = await res.json();
loading.value = false;
});
로딩 중...
- {{ post.title }}
0:30~0:50 | Vue Router
npm install vue-router
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
],
});
0:50~1:20 | React vs Vue 종합 비교
항목 React Vue
| 문법 | JSX (JS 안에 HTML) | 템플릿 (HTML 안에 JS) |
| 상태 관리 | useState, useReducer | ref, reactive |
| 생명주기 | useEffect | onMounted, watch |
| 양방향 바인딩 | 직접 구현 | v-model 기본 제공 |
| 스타일 | 다양한 방식(CSS-in-JS 등) | <style scoped> 기본 제공 |
1:20~2:00 | 실습
- 실무에서 쓸 화면 하나(목록 조회 + 상세 보기)를 미니 버전으로 구현
- 강사와 코드리뷰
과제
- 없음 (최종 실습으로 마무리)
4주차 마무리 체크리스트
- [ ] ref와 reactive의 차이를 설명할 수 있다
- [ ] v-model, v-for, v-if를 자유롭게 사용할 수 있다
- [ ] props/emit으로 부모-자식 컴포넌트 통신을 구현할 수 있다
- [ ] onMounted로 API 데이터를 가져와 화면에 표시할 수 있다
- [ ] React와 Vue의 핵심 차이를 남에게 설명할 수 있다
'Javascript' 카테고리의 다른 글
| 3주차 — React(상세) (1) | 2026.07.22 |
|---|---|
| 2주차 — JavaScript 심화(상세) (0) | 2026.07.22 |
| 1주차 — JavaScript 기초(상세) (0) | 2026.07.22 |
| 4주차 — Vue (0) | 2026.07.20 |
| 3주차 — React (0) | 2026.07.20 |