Vue.js 시작하기
Vue.js에 대한 처음 시작에 대한 강좌를 진행합니다.
Vue.js는 자바스크립트 라이브러리이자 프레임워크입니다.
이 강좌는 Vue.js 3.0 버전을 기준으로 진행되고, 시작 강좌는 순수 HTML 레벨에서 script 태그를 포함하여 바로 특정 웹앱에 바로 Vue.js를 적용하는 방법을 기준으로 시작합니다.
선수 학습
- HTML
- CSS
- JavaScript
- Bootstrap
Vue.js 소개
이 강의에서 사용되는 모든 내용은 Vue.js 공식 사이트의 자료를 바탕으로 합니다.
- Vue.js 공식 사이트: https://www.vuejs.org
Vue.js(Vue로 줄여서 말함)는 2014년 2월 처음 공개가되었고 Evan You가 만들었습니다.
Vue.js의 목적은 이미 있는 사이트에 손쉽게 Vue.js를 포함하여 사용할 수 있도록하는 것입니다.
아예, 처음부터 Vue.js 기반으로 하나의 웹앱을 만들 수도 있지만, 이미 있는 수많은 사이트에 손쉽게 Vue.js를 적용할 수 있다는 점이 가장 좋은 장점입니다.
Vue vs React vs Angular
현재 가장 많이 사용되는 자바스크립트 프레임워크(라이브러리)는 Vue.js, React.js, Angular가 있습니다.
이 중에서 어떤 것을 사용해도 모두 웹앱을 만드는데 문제가 없습니다.
이 강의는 Vue.js에 포커스를 맞춥니다.
참고로, 이 세 개의 기술에 대한 강의를 모두 해 본 입장에서는 Vue.js가 가장 쉽습니다.
여기서 쉽다라는 것은 기존에 웹을 해왔던 입장이라면 가장 빠르게 Vue.js를 적용해서 사용할 수 있는 장점이 있다는 것입니다.
HTML 문서에 Vue.js 추가
다음 링크를 사용하여 Vue.js CDN을 사용하여 모든 HTML 페이지에 간단히 Vue를 추가할 수 있습니다.
Vue.js CDN
<script src="https://unpkg.com/vue@next"></script>
Axios
Vue.js를 사용할 때 항상 함께 사용되는 또 다른 자바스크립트 라이브러리는 Axios입니다.
Axios를 사용하면 Vue.js에서 Ajax 기능을 편리하게 사용할 수 있습니다.
참고로, Axios가 아닌 Fetch API를 사용해도 충분하긴 합니다.
Vue 앱 만들기
Vue 앱을 생성하려면 Vue 오브젝트의 createApp() 메서드를 호출합니다.
const App = Vue.createApp({
// 속성과 메서드 그리고 이벤트 처리기가 들어오는 곳...
});
data() 메서드로 속성들 추가
Vue 앱에 data() 메서드를 사용하여 하나 이상의 속성들을 만들어 사용할 수 있습니다.
다음 코드를 사용하여 title과 message 속성을 만들 수 있습니다.
// Vue 앱 만들기
const App = Vue.createApp({
data() {
return {
title: 'Vue.js 학습 시작하기',
message: 'Vue.js를 사용하여 손쉽게 웹 애플리케이션을 만들 수 있습니다.'
};
}
});
mount() 메서드로 Vue 앱 탑재
HTML 요소의 id를 지정하여 Vue 앱을 HTML 페이지에 탑재할 수 있습니다.
<!-- Vue 앱이 실행될 영역: id를 달리하여 하나 이상의 앱을 탑재할 수 있음 -->
<div id='app'>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const App = Vue.createApp({
data() {
return {
title: 'Vue.js 학습 시작하기',
message: 'Vue.js를 사용하여 손쉽게 웹 애플리케이션을 만들 수 있습니다.'
};
}
});
// app id를 갖는 HTML 요소에 Vue 앱 탑재
App.mount('#app');
</script>
data 속성
Vue 앱의 data
메서드에는 속성을 만들 수 있는 영역입니다.
데이터 출력
핸들바 또는 Interpolation으로 불리는 {{}}
구문을 사용하여 Vue 앱의 데이터를 출력할 수 있습니다.
{{ title }}
코드로 title 속성을 출력합니다.
<!-- Vue 앱이 실행될 영역: id를 달리하여 하나 이상의 앱을 탑재할 수 있음 -->
<div id='app'>
<h1>{{ title }}</h1>
<p>{{ message }}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const App = Vue.createApp({
data() {
return {
title: 'Vue.js 학습 시작하기',
message: 'Vue.js를 사용하여 손쉽게 웹 애플리케이션을 만들 수 있습니다.'
};
}
});
// app id를 갖는 HTML 요소에 Vue 앱 탑재
App.mount('#app');
</script>
Vue.js 앱 실행하기
라이브 서버 또는 ASP.NET Core 또는 Spring Boot의 정적 HTML 실행 영역에서 코드를 실행합니다.
코드: vue-hello-world.html
<!-- Vue 앱이 실행될 영역: id를 달리하여 하나 이상의 앱을 탑재할 수 있음 -->
<div id='app'>
<h1>{{ title }}</h1>
<p>{{ message }}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const App = Vue.createApp({
data() {
return {
title: 'Vue.js 학습 시작하기',
message: 'Vue.js를 사용하여 손쉽게 웹 애플리케이션을 만들 수 있습니다.'
};
}
});
// app id를 갖는 HTML 요소에 Vue 앱 탑재
App.mount('#app');
</script>
특성 바인딩
v-
로 시작하는 지시문을 사용하여 특성(attribute)에 데이터를 바인딩할 수 있습니다.
v-bind
v-bind 지시문을 사용하여 img 태그의 src에 Vue 오브젝트의 속성 값을 바인딩할 수 있습니다.
<div id="app">
<img v-bind:src="imageSource" />
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data() {
return {
imageSource: './images/product01.jpg'
}
}
}).mount('#app');
</script>
v-bind 지시문은 v-bind:attribute
를 :attribute
로 줄여서 표현할 수 있습니다.
원본 코드는 다음과 같습니다.
<div id="app">
<img v-bind:src="imageSource" />
</div>
줄인 코드는 다음과 같습니다.
<div id="app">
<img :src="imageSource" />
</div>
CSS 클래스와 스타일 적용
CSS 클래스에 대한 Vue 오브젝트 설정은 다음과 같습니다.
<div id="app">
<div :class="classObject">Hello, Vue!</div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data() {
return {
classObject: {
centered: true,
active: true,
'text-center': true
}
}
}
}).mount('#app');
</script>
style 특성에 대한 Vue 오브젝트 설정은 다음과 같습니다.
<div id="app">
<div :style="styleObject">Hello, Vue!</div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
data() {
return {
styleObject: {
'background-color': 'red'
}
}
}
}).mount('#app');
</script>
v-for 지시문으로 컬렉션 출력
배열, 컬렉션 데이터를 반복해서 출력할 때에는 v-for
지시문을 사용합니다.
다음 코드 형태로 v-for
를 사용할 수 있습니다. v-for
는 :key
와 함께 사용해야 합니다.
v-for="항목명 in 컬렉션명"
v-for="항목 in 항목리스트"
v-for="vm in models"
Vue.createApp({
data() {
return {
names: ['RedPlus', 'Taeyo', 'Itist' ]
}
}
}).mount('#app');
<ul id="app">
<li v-for="vm in names">{{ vm }}</div>
</ul>
실행 결과는 다음과 같습니다.
- RedPlus
- Taeyo
- Itist
반복되는 데이터는 유이할 키 값을 주어야 합니다. 다음과 같이 :key
지시문으로 유일한 인덱스로 키 값을 주었습니다.
<ul id="app">
<li v-for="(nm, index) in names" :key="index">{{ nm }}</div>
</ul>
조건부 렌더링
v-show
, v-if
, v-else-if
, v-else
지시문을 사용하여 조건에 따른 데이터 출력이 가능합니다.
<div v-show="new Date().getMonth() >= 2 && new Date().getMonth() <= 4">봄이 왔어요...</div>
<div v-if="new Date().getMonth() < 3">1분기</div>
<div v-else-if="new Date().getMonth() < 6">2분기</div>
<div v-else-if="new Date().getMonth() < 9">3분기</div>
<div v-else>4분기</div>
v-model 지시문으로 form 요소 양방향 바인딩
v-model 지시문을 사용하면 양방향 바인딩을 아주 쉽게 처리할 수 있습니다. 양방향 바인딩은 JavaScript 영역과 HTML 영역간의 데이터가 서로 연결되어 있는 상태입니다.
텍스트박스 바인딩
Vue 오브젝트 속성과 텍스트박스간의 양방향 바인딩은 다음 샘플 코드와 같이 v-model
지시문을 사용합니다.
<input type="text" v-model="name" />
체크박스 바인딩
<input type="checkbox" v-model="active" />
드롭다운 리스트 바인딩
Vue.js에서 드롭다운 리스트는 다음 형태들 중 하나를 사용합니다.
<select v-model="selectedValue">
<option v-for="item in items" :value="item.value">
{{ item.displayProperty }}
</option>
</select>
<select v-model="statusIndex">
<option disabled value="">선택</option>
<option v-for="(status, index) in statusList" :value="index">
{{ status }}
</option>
</select>
<select id="product-cabin" v-model="booking.cabinIndex">
<option v-for="(cabin, index) in product.cabins" :value="index">
{{ cabin.name }} $ {{ cabin.price.toLocaleString('en-US') }}
</option>
</select>
이벤트 처리
Vue.js에서는 v-on
과 @
을 사용하여 이벤트를 처리할 수 있습니다.
v-on:이벤트명 = "메서드명"
이벤트 처리기
Vue 앱의 methods 필드에 function을 추가하여 이벤트 처리기를 만들 수 있습니다.
다음 코드는 handleClick 이름의 이벤트 핸들러를 만들고 methods 필드에 등록하는 방법입니다.
const app = Vue.createApp({
data() {
return {
name: 'RedPlus'
}
},
methods: {
handleClick() {
console.log(this.name);
}
}
});
@click
지시문으로 이벤트 처리기를 클릭 이벤트에 바인딩할 수 있습니다.
<button type="button" @click="handleClick">이름 표시</button>
계산된 속성
Vue 앱에 computed 필드에 메서드를 생성하면 이는 핸들바에서 값으로 가져다 사용할 수 있습니다.
하나 이상의 속성을 묶어서 계산된 속성으로 사용이 가능합니다.
const app = Vue.createApp({
data() {
return {
firstName: 'YJ',
lastName: 'Park'
}
},
computed: {
fullName() {
return `${lastName}, ${firstName}`
}
},
});
코드: index-computed.html
<html>
<head>
<style>
.container {
border: solid 1px #777;
border-radius: 5px;
padding: 5px;
}
.calculator {
padding: 20px;
border: solid 1px gray;
box-shadow: 0 0 5px gray;
margin: 20px;
}
</style>
</head>
<div id="app">
<h2>Shipping</h2>
<div>
<input type="text" placeholder="name" v-model="name">
</div>
<div>
<input type="text" placeholder="address" v-model="address">
</div>
<div>
<input type="text" placeholder="city" v-model="city">
</div>
<div>
<input type="text" placeholder="country" v-model="country">
</div>
<h3>Address sticker</h3>
<div class="container">
{{fullAddress}}
</div>
<div class="calculator">
<h2>Calculator</h2>
<input type="number" v-model="lhs" type="text"> + <input type="number" v-model="rhs" type="text">
Sum {{sum}}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="index-computed.js"></script>
</html>
코드: index-computed.js
var app = new Vue({
el: '#app',
data() {
return {
name: '',
address: '',
city: '',
country: '',
lhs: 0,
rhs: 0
}
},
computed: {
sum() {
return parseInt(this.lhs) + parseInt(this.rhs);
},
fullAddress() {
return `
${this.name}, ${this.address}, ${this.city.toUpperCase()}, ${this.country.toUpperCase()}
`
}
}
})
Key 한정자와 CSS class 바인딩
#keyup.esc = "clearText"
:class="{}"
컴포넌트 라이프 사이클
Vue.js에서는 많은 수의 라이프 사이클 메서드(후크)를 제공합니다.
기초 강의에서는 created()
메서드만 사용합니다.
created()
컴포넌트가 실행되면 처음으로 created() 펑션이 실행됩니다. 이곳에서는 REST Web API로부터 데이터를 가져오는 기능을 주로 담당합니다.
mounted(), updated()
created(), mounted(), updated(), destroyed() 후크 등이 있습니다.
ES module을 사용한 Vue.js 앱 만들기
순수한 HTML 파일 레벨에서 Vue.js 앱을 만드는 두 번째 방법은
ES module을 사용하는 방법입니다.
Vue CLI를 사용하여 Vue.js 앱 만들기
Vue.js 앱을 만드는 가장 막강한 방법은 Vue CLI를 사용하여 전체 스택 중 프런트엔드 영역을 SPA로 만들 수 있는 방법이 있습니다.