CH7 큰 규모의 애플리케이션 개발하기
COLUMN 추상화는 왜 필요할까?
해당 칼럼의 추가적인 내용입니다.
- 코드를 따로 빼기:
어느 정도 코드를 뭉칠 수 있다고 판단되는 경우, 따로 빼서 관리하는 것이 유지보수하기 편리합니다(사용자 정보, 상품 정보 등). - 코드는 공통화하기:
같은 처리를 하는 경우, 함수 등으로 만들면 유지보수하기 편리합니다(산출 처리 등). - 의존성이 적은 코드 작성하기:
예를 들어서 '강아지가 사료를 먹는 처리'라는 형태로 코드를 작성하면, 다른 동물이 등장했을 때 또는 다른 먹이가 등장했을 때 별도의 처리를 또 만들어줘야 합니다. 따라서 범용성이 높은 형태로 코드를 작성하는 것이 좋습니다.
S35 단일 파일 컴포넌트
215~219페이지
<template>
<div class="example">
<span class="title">{{ text }}</span>
</div>
</template>
<script>
export default {
name: 'Example',
data() {
return {
text: 'example'
}
}
}
</script>
<!-- scoped CSS -->
<style scoped>
.title {
color: #ffbb00;
}
</style>
S37 Node.js
S38 Vue CLI
224~230페이지
Vue CLI 설치하기
npm install -g vue-cli
새 프로젝트 만들기
vue init webpack my-app
모듈들이 자동으로 설치되지 않는 경우, 다음 명령어로 my-app
디렉터리로 이동하고 모듈을 따로 설치해 주세요.
cd my-app
npm install
폴더와 파일 구성
227페이지
다음과 같이 루트 생성자의 템플릿을 렌더링 함수로 변경하고, 이외의 모든 것을 '.vue' 파일을 사용하는 형태로 만들면, 런타임 한정 빌드에서 사용할 수 있습니다.
템플릿 옵션을 사용하면 컴파일이 필요하므로 런타임 전용 빌드로는 코드를 실행할 수 없게 됩니다.
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
new Vue({
el: '#app',
render: h => h(App)
})
런타임이란?
런타임 전용 빌드의 '런타임'이란 애플리케이션을 동작시키기 위해서 필요한 코드를 의미합니다. 컴파일을 포함하지 않으므로 조금 크기가 작아집니다. 완전 빌드는 템플릿을 렌더링 함수로 변환하는 '컴파일러'도 포함한 코드입니다. 참고로 webpack 등을 사용해서 미리 컴파일을 해 두면, 이러한 컴파일러를 포함하지 않아도 괜찮습니다.
[추가] Vue CLI 버전3
여기부터는 Vue CLI3 설명입니다.
Vue CLI3 설치하기
npm install -g vue-cli
가 아니라 다음 명령어를 사용해서 버전3의 Vue CLI를 설치할 수 있습니다.
npm install -g @vue/cli
# or yarn를 사용하는 경우
yarn global add @vue/cli
프로젝트 생성 방법
프로젝트 생성은 vue init webpack my-app
이 아니라, 다음 명령어로 합니다.
# 프로젝트 생성
vue create my-app
Vue CLI3에서는 질문의 내용이 좀 많이 다릅니다. 추가로 템플릿을 지정하는 것이 아니라, 질문에 답해서 필요한 패키지를 선택하는 형태로 사용합니다. 공부를 하는 과정에서는 처음에 나오는 'simple'을 선택하거나 'Manually select features' 이후 'Babel', 'CSS Pre-processors'만 선택해서 사용하는 것을 추천합니다. 방향키를 사용해서 항목을 이동하고, 스페이스 키를 이용해서 체크할 수 있습니다.
Vues와 Vue Router는 이 시점에 설치하지 않아도 괜찮습니다. 질문 답변이 끝나면 곧바로 모듈 설치가 진행됩니다.
Vue CLI3는 빌드 도구 전용 파일이 모두 은닉되므로, 폴더 구조가 굉장히 깔끔합니다.
빌드 설정을 변경할 때는 프로젝트 루트에 있는 vue.config.js
라는 파일을 편집합니다.
디렉터리 구조
'src' 디렉터리의 내용은 버전2와 같습니다. 'public' 폴더에는 처음 실행되는 인덱스 HTML 템플릿인 'index.html' 파일이 들어 있으며, 정적 파일들이 들어갑니다(즉 버전2의 'static' 폴더와 같습니다).
.git/ 3에서는 기본적으로 생성됩니다
public/ 정적 파일
src/
├ assets/
├ components/
├ App.vue
└ main.js
.git/
public/
src/
├ assets/
├ components/
├ store/ Vuex 모듈
├ views/ 페이지 전용 컴포넌트
├ App.vue
├ main.js
├ router.js
└ store.js
개발 서버 실행 명령어도 다음과 같이 바뀌었습니다.
npm run serve
# or
yarn serve
S39 Vue.js플러그인
231페이지
사용자 정의 플러그인 만들기
232페이지
var windowPlugin = {
install: function(Vue) {
// 플러그인 데이터 전용으로 Vue 인스턴스 사용하기
var store = new Vue({
data: {
scrollY: 0
}
})
// 윈도우 스크롤 이벤트 핸들하기
var timer = null
window.addEventListener('scroll', function() {
if (timer === null) {
timer = setTimeout(function() {
// 200ms 간격으로 scrollY 속성에 할당하기
store.scrollY = window.scrollY
clearTimeout(timer)
timer = null
}, 200)
}
})
// 인스턴스 속성에 등록하기
Vue.prototype.$window = store.$data
}
}
Vue.use(windowPlugin)
Vue.component('my-component', {
template: '<div>{{ scrollY }}</div>',
computed: {
scrollY: function() {
return this.$window.scrollY
}
}
})
S40 ES2015로 작성해 보기
235~243페이지
변수 생성 방법
let x = 0
console.log(x++) // -> 1
const x = 0
console.log(x++) // -> Identifier 'x' has already been declared
{
let x = 1
}
console.log(x) // -> x is not defined
const array = [1, 2]
array.push(3)
console.log(array) // -> (3) [1, 2, 3]
array.length = 0
console.log(array) // -> []
함수와 메소드 생성 방법
함수 생략
new Vue({
methods: {
handleClick() { ... }
}
})
화살표 함수
const newArray = array.map(el => {
return el * 2
})
const newArray = array.map(el => el * 2)
const newArray = array.map((el, index) => el * 2)
const newArray = array.map(el => ({ value: el * 2 }))
템플릿 리터럴
const name = '구름'
const template = `
<div class="template">
<strong>${ name }</strong>
</div>`
console.log(template)
객체 속성 생략 지정
const a = 'foo'
const b = 'bar'
const newObject = { a, b }
비구조화 할당
// 배열 요소 1, 2를 각각 변수 a, b에 할당
const [a, b] = [1, 2]
console.log(a) // -> 1
// name 속성만 추출하기
const { name } = { id: 1, name: '사과' }
console.log(name) // -> 사과
function myFunction({ id, name }) {
console.log(name) // -> 사과
}
myFunction({ id: 1, name: '사과' })
전개 연산자
const array = [1, 2, 3]
// 각각 매개변수로 전달됨
myFunction(...array)
// array를 전개하고, 뒤에 새로운 요소 4 추가하기
const newArray = [...array, 4] // -> (4) [1, 2, 3, 4]
배열 메소드
find
const array = [
{ id: 1, name: '사과' },
{ id: 2, name: '바나나' }
]
const result = array.find(el => el.id === 2)
console.log(result) // -> { id: 2, name: '바나나' }
findIndex
const array = [
{ id: 1, name: '사과' },
{ id: 2, name: '바나나' }
]
const result = array.findIndex(el => el.id === 2)
console.log(result) // -> 1
Promise
function myFunction() {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 성공한 경우 통지
resolve('성공!')
}, 1000)
})
}
// 1초 후에 myFunction이 종료되면 , then 처리가 실행됨
myFunction().then(value => {
console.log(value) // -> 성공!
})
function myFunction(num) {
return new Promise((resolve, reject) => {
if (num < 10) {
resolve('success!')
} else {
reject('error!')
}
})
}
myFunction(100).catch(value => {
console.log(value) // -> 에러!
})
myFunction().then().catch().finally(() => {
// 성공/실패와 상관 없이 호출
})