이 디스크에 Windows를 설치할 수 없습니다. 선택한 디스크가 GPT 파티션 스타일입니다.


윈도우 설치시 디스크 포맷후 해당 디스크에 윈도우를 설치할때 위의 에러가 발생할 수 있다.

당황하지 말고 아래의 방법대로 따라하면 설치 가능함!


1) Shift + F10 을 눌러 CMD창을 실행한다.


2) 이제부터는 아래의 명령어를 타이핑한다.


[1] c:

[2] diskpart

[3] list disk

 - 위 명령어를 치면 현제 disk들의 목록이 나온다. 포맷하고자하는 디스크의 번호를 선택한다.

[4] select disk 번호

[5] clean

 - DiskPart에서 디스크를 정리했습니다. <- 출력되면 성공

[6] exit (두번 쳐서 cmd창까지 종료)


3) 위의 명령어를 다 수행했으면 컴퓨터를 리부팅시키고 다시 포맷을 진행하면 된다.





IntelliJ 스프링부트 그래들로 생성하기

이번에는 IntelliJ IDE에서 Spring Boot Project를 Gradle로 생성하는 방법을 설명해보겠습니다. IntelliJ가 처음이신 분들에게 도움이 되실꺼라 생각이 되면서 저도 잊어먹지 않기 위해(정말 간단하지만..) 글로 남겨 놓을려고 합니다.





1) Create New Project 클릭





2) Spring Initializr 클릭




3) Project Metadata 설정 (Type에서 Gralde Project 선택)





4) Gradle에 추가할 디펜던시 선택







5) 임포트 설정 Gradle 




6) Gradle Build 중..



끝~

Vuex란?

Vuex는 Vue.js 애플리케이션에서 상태 관리 패턴을 지원하는 라이브러리이다. 애플리케이션 내부의 모든 컴포넌트들이 공유하는 집중화된 상태 정보 저장소 역할을 하며 상태 변경을 투명하게 할 수 있다. 각 컴포넌트가 공유하는 상태 데이터는 전역에서 저장소(store)객체를 통해서 관리한다. 이와 같은 방식으로 자식으로 또 그 자식으로 props를 이용해 속성을 계속해서 전달하지 않아도 되고 상태 데이터를 변경하기 위해 부모 콤포넌트로 이벤트를 발생시키지 않아도 된다. 


Vuex를 사용하는 이유

1. 중앙 집중화된 상태 정보 관리가 필요할때

2. 상태 정보가 변경되는 상황과 시간을 추적하고 싶을때

3. 컴포넌트에서 상태 정보를 안전하게 접근하고 싶을때

위의 그림을 보면 화살표가 한방향으로만 흘러간다. "단방향 데이터 흐름"이라는 용어를 쓰는데 전체적인 처리 흐름은 다음과 같다.


1) 컴포넌트가 액션을 일으킨다.(버튼 클릭 이벤트 같은)

2) 액션에서는 외부 API를 호출한 뒤 그 결과를 이용해 변이(mutation)을 일으킨다.

3) 변이에서는 액션의 결과를 받아 상태를 설정한다. 이단계는 추적할 수 있기 때문에 vue.js Dev Tool을 이용하면 상태 변경의 내역을 모두 확인할 수 있다.

4) 변이에 의해 변경된 상태는 다시 컴포넌트에 바인딩되어 화면을 갱신한다.


위의 그림에서 점선으로 표시된 영역이 Vuex 저장소(store) 객체 영역이다. 저장소가 상태(State:데이터), 변이(Mutation), 액션(Action)을 모두 관리한다. 저장소는 애플리케이션의 상태를 중앙집중화하여 관리한는 컨테이너이며 일반적인 전역 객체와는 달리 저장소의 상태를 직접 변경하지 않는다. 반드시 변이를 통해서반 변경한다.


주의할점은 변이의 목적은 상태의 변경이라는 것이다. 상태의 변경과 관련이 없는 작업이 변이 내부에서 수행되지 않도록 해야한다. 또한 변이는 동기적인 작업이다. 비동기 처리는 변이를 통해서 수행되지 않는다. 변이 내부에서 비동기적 처리를 수행해도 애플리케이션의 기능은정상적으로 작동될 수 있지만 사후 스냅샷을 캡쳐한 후에 나중에 상태가 변경되기 때문에 변이에 의해 데이터가 어떻게 변경되었는지를 추적할 수 없게 된다.





상태와 변이

상태(state)와 변이(muation)은 Vues 저장소(store) 내부의 핵심 요소이다. 상태는 애플리케이션에서 관리해야 할 중요한 데이터이며, 변이는 상태를 변경하는 함수들을 보유하고 있는 객체이다. 전역에서 Vue.user(Vuex) 코드의 실행으로 애플리케이션 내부의 모든 컴포넌트가 저장소의 상태, 변이 객체에 접근할 수 있다. 반드시 변이를 통해서반 변경되도록 해야한다. 



Vuex 라이브러리 다운로드

yarn add vuex 

OR 

npm install -save vuex



export default {
ADD_TODO: "addTodo",
DONE_TOGGLE: "doneToggle",
DELETE_TODO: "deleteTodo"
}

[src/Constant.js]




import Vue from 'vue';
import Vuex from 'vuex';
import Constant from '../Constant'
Vue.use(Vuex)

const store = new Vuex.Store({
state: {
todolist: [
{ todo: "영화보기", done: false },
{ todo: "주말 산책", done: true },
{ todo: "ES6 학습", done: false },
{ todo: "주말 야구장", done: false },
]
},
mutations: {
[Constant.ADD_TODO]: (state, payload) => {
if (payload.todo !== "") {
state.todolist.push({ todo: payload.todo, done: false })
}
},
[Constant.DONE_TOGGLE]: (state, payload) => {
state.todolist[payload.index].done =
!state.todolist[payload.index].done
},
[Constant.DELETE_TODO]: (state, payload) => {
if (payload.todo !== "") {
state.todolist.splice(payload.index, 1)
}
}
}
})

export default store;

[src/store/index.js]


Vuex를 전역에서 사용할 수 있도록 4행의 Vue.use(Vuex) 코드를 미리 작성해야한다. 또한 state, mutation 정보를 전달하여 Vuex.Store 객체를 생성한다. 이 예제에서는 List 컴포넌트가 보유하던 상태 데이터를 저장소가 관리하도록 했다.


"모든 컴포넌트의 상태 데이터를 Vuex로 관리할 필요는 없다"


하나의 컴포넌트 내부에서만 사용되는 상태이거나 중요하지 않은 상태이면 Vuex 저장소에 관리할 필요는 없다. Vuex가 유용한 경우는 여러 컴포넌트가 상태 데이터를 공유하는 경우이다.


변이(mutation) 객체의 메소드들은 첫번째 인자가 상태(state)이다. 두번째 인자 payload는 변이에 필요로 하는 데이터 타입이다. addTodo 작업의 경우는 todolist 데이터에 새로운 todo를 추가하기 때문에 두번재 인자 payload를 통해서 todo를 전달한다. 만약 변이를 일으킬 때 필요한 인자가 여러 개라면 payload를 객체 형태로 전달하면 된다.


이제 src/main.js를 수정해서 vue인스턴스를 생성할 때 store 객체를 전달한다. 아래의 코드를 작성하면 각 자식 컴포넌트에서 저장소(Store) 객체를 this.$store으로 접근할 수 있게된다.


import Vue from 'vue'
import TodoList from './components/TodoList.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
store,
render: h => h(TodoList)
}).$mount('#app')

[src/main.js]


이렇게 작성하면 Vuex를 사용하는 기본적인 셋팅은 끝났다. 기존에 작성한 todolist 의 list.vue 파일을 vuex를 이용하는 방법을 아래와 같이 수정하겠다.



<script tpye="text/javascript">
import Constant from '../Constant'

export default {
name: 'List',
computed: {
todolist() {
return this.$store,state.todolist
}
},
methods: {
checked: function(done) {
if (done) return {
checked: true
};
else return {
checked: false
}
},
doneToggle: function(id) {
this.$store.commit(Constant.DONE_TOGGLE, {id:id})
},
delete: function(id) {
this.$store.commit(Constant.DELETE_TODO, {id:id})
}
}
}
</script>


위의 소스를보면 List.vue 파일에는 로컬 데이터가 없다. 저장소(store) 객체가 Vue 인스턴스에 주입되었기 때문에 this.$store.state와 같이 저장소의 상태(state)에 접근할 수 있다. 이것을 속성처럼 이용할 수 있도록 하기 위해 계산형 속성(Computed Property)를 사용한다. 


화면에서 일어나는 이벤트를 받아 처리하는 메서드에서 변이(mutation)을 일으키기 위해서 this.$store.commit() 메서드를 호출한다. this.$store.commit() 메서드의 첫 번째 인자는 변이의 이름이다. 변이에 전달할 인자는 payload 인자를 이용하면 된다. 변이의 이름은 단순한 문자열이기 때문에 오타를 내기 쉽다. 그래서 위에 작성한 Constant.js와 같은 상수를 만들어 사용할 것을 권장하는 것이다.




헬퍼 메서드

이전 까지는 계산형 속성으로 this.$store.state를 직접 리턴하는 코드를 작성했고, 메서드에서도 변이를 직접 커밋하는 코드를 작성했는데 이와 같은 방법은 조금 불편한다.


이러한 불편함을 덜어주기 위해 mapState, mapMutations와 같은 컴포넌트 바인딩 헬퍼 메서드를 제공한다. 이 밖에도 mapGetters, mapActions 메서드도 있다.


<template>
<ul id="todolist">
<li v-for="a in todolist" :key="a.id" :class="checked(a.done)"
@click="doneToggle(a.id)">
<span>{{a.todo}}</span>
<span v-if="a.done">(완료)</span>
<span class="close" @click.stop="deleteTodo({id:a.id})">
&#x00D7;</span>
</li>
</ul>
</template>
<script tpye="text/javascript">
import Constant from '../Constant'
import { mapState, mapMuations } from 'vuex'

export default {
name: 'List',
computed: mapState(['todolist']),
methods: {
checked: function(done) {
if (done) return {
checked: true
};
else return {
checked: false
}
},
...mapMuations([
Constant.DELETE_TODO,
Constant.DONE.TOGGLE
])
}
}
</script>



Getter

게터는 저장소 수주느이 계산형 속성이라고 말할 수 있다. 컴포넌트에서 계산형 속성이 필수가 아니듯 게터 또한 저장소 내에서 필수로 사용하는 것ㅇ느 아니다. 하지만 적절하게 사용하면 컴포넌트에서 코드의 작성이 편리해진다. 












Action

'Vue.js' 카테고리의 다른 글

[Vue.js] axios 서버통신  (2) 2018.12.22
[Vue.js] Vue CLI(GUI)  (0) 2018.12.18
[Vue.js] Component  (0) 2018.12.18
[Vue.js] Event 처리  (0) 2018.12.17
[Vue.js] Vue instance (뷰 인스턴스)  (0) 2018.12.16

axios를 이용한 서버통신

서버와 통신하기 위한 라이브러리는 fetch, superagent, axios 등이 있으며 Vue.js 플러그인으로 개발된 vue-resource라는것도 존재하나 Vue.js 창시자인 에반 유는 axios를 사용할 것을 권장하고 있다고 한다.


서비스 API

S네트워크 사용에 제약이 따를 경우 로컬에서 실행할 수 있는 API코드를 다운로드하여 실행하는 연락처 서비스 API이다.


다운로드 >> https://github.com/STEPANOWON/CONTACTSVC



[저수준 API]

axios(config)

axios(url, config]


[각 메서드별 별칭]

axios.get(url[, config])

axios.delete(url[, config])

axios.psot(url[, data[, config])

axios.put(url[, data[, config])

axios.head(url[, config])

axios.options(url[, config])



axios 사용법


yarn add axios 


Or


npm install --save axios






axios 프로젝트 생성



1) vue cli로 프로젝트 생성

vue create contactsapp

2) axios 추가 

yarn add axios OR npm install --save -axios

3) http proxy 설정

Vue CLI가 생성하는 프로젝트 템플릿 코드에서는 약간의 설정 파일만 작성하면 웹팩 개발서버를 이용해 프로시 서버 기능을 사용할 수 있다. 프로젝트 최상위 디렉토리에 vue.config.js파일을 생성하고 아래의 코드를 작성한다.

module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localshot:3000',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}


이렇게 하면 개발용 서버에 /api/contacts를 요청하게되면 http://localshot:3000/contacts로 요청일 전달 도니다.  만약 위의 서비스 API 서버를 로컬에서 실행하지 않는다면 위의 target 값을 http://sample.bmaster.kro.kr 으로 지정하면 된다.




<template>
<div id="app">
<div class="container">
<div class="form-group">
<button @click="fetchContacts">1페이지 연락처 조회</button>
</div>
<div class="form-group">
<input type="text" v-model="name"
placeholder="이름을 입력합니다"/>
<input type="text" v-model="tel"
placeholder="전화번호를 입력합니다"/>
<input type="text" v-model="address"
placeholder="주소 입력합니다"/>
<button @click="addContact">연락처 1건 추가</button>
</div>
<div class="form-group">
<input type="text" v-model="no"/>
<button @click="fetchContactOne">연락처 1건 조회</button>
</div>
<div class="form-group">
<input type="text" v-model="no"/>
<input type="text" v-model="name"
placeholder="이름을 입력합니다"/>
<input type="text" v-model="tel"
placeholder="전화번호를 입력합니다"/>
<input type="text" v-model="address"
placeholder="주소 입력합니다"/>
<button @click="updateContact">수정</button>
</div>
<div class="form-group">
<input type="text" v-model="no"/>
<input type="file" ref="photofile" name="photo"/>
<button @click="changePhoto">파일 변경</button>
</div>
</div>
<span>JSON 출력</span>
<div id="result" class="container">
<xmp> {{ result }} </xmp>
</div>
</div>
</template>

<script>
import axios from 'axios';

export default {
name : "app",
data() {
return {
no: 0,
name: '',
tel: '',
address: '',
result: null
}
},
methods : {
fetchContacts : function() {

},

addContact : function() {

},

fetchContactOne : function() {

},

updateContact : function() {

},

deleteContact : function() {

},

changePhoto : function() {

}
}
}
</script>

<style>
@import url("http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.css");
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osz-font-smoothing: grayscale;
text-align: center;
color : #2c3e50;
margin-top : 60px;
}

.container {
border: solid 1px gray;
padding: 10px;
margin-bottom: 10px;
text-align: left;
}

#result {
text-align: left;
padding: 20px;
border: solid 1px black;
}

.form-group {
border: dashed 1px gray;
padding: 5px 5px 5px 20px;
}
</style>

[src/AppAxiosTest.vue]




import Vue from 'vue'
//import App from './App.vue'
import App from './AppAxiosTest.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App),
}).$mount('#app')

[src/main.js]




axios 요청 방법

axios 저수준 API를 이용하는 예제이다. 아래의 코드를 fetchContact메서드에 작성한다.


fetchContacts : function() {
axios({
method: 'GET',
url : '/api/contacts',
params : {
page : 1,
pagesize : 5
}
}).then((response) => {
console.log(response);
this.result = response.data;
}).catch((ex)=> {
console.log("ERR!!!!! : ", ex)
})
},

[ 저수준 axios 메소드 작성법 ]



axios 저수준 메서드의 특징은 모든 전달값을 config 객체로 전달한다는 특징이 있다. Promise 객체는 요청이 성공적이라면 then이 호출되며 요청이 실패하면 catch가 호출된다. 저수준 메서드가 아닌 별칭 메서드 get을 이용하여 fetchContactOne을 작성하겠다.



fetchContactOne : function() {
axios.get('/api/contacts/' + this.no)
.then((response) => {
console.warn(response);
this.result = response.data
})
},

[GET]



POST 메서드에서는 주로 axios.post(url, data, config) 형태를 주로 사용한다. 다음은 addContact 에 POST를 이용해 작성해본 코드이다.



addContact : function() {
axios.post('/api/contacts',
{ name:this.name, tel:this.tel, address:this.address }
).then(response => {
console.warn(response)
this.result = response.data
this.no = response.data.no
}).catch((ex) => {
console.warn("ERROR!!!!! : ",ex)
})
},

[POST]



updateContact : function() {
axios.put('/api/contacts/' + this.no,
{ name:this.name, tel:this.tel, address:this.address }
).then(response => {
console.warn(response)
this.name = '';
this.tel = '';
this.address = '';
this.result = response.data
}).catch((ex) => {
console.warn("ERROR!!!!! : ",ex)
})
},

[PUT]



deleteContact : function() {
axios.delete('/api/contacts/' + this.no)
.then(response => {
console.warn(response)
this.result = response.data
}).catch((ex) => {
console.warn("ERROR!!!!! : ",ex)
})
},

[DELETE]



파일 업로드 기능도 axios로 구현하기 위해서는 위에 작성한 <input tpye="file" ../> 필드를 직접 참조해야한다. 해당 태그에 보면 ref="photofile" 이라고 ref 옵션을 사용한걸 볼 수 있다. 


changePhoto : function() {
var data = new FormData();
var file = this.$ref.photofile.files[0]
data.append('photo', file)

axios.post('/api/contacts' + this.no + '/photo', data)
.then(response => {
console.warn(response)
this.result = response.data
this.no = response.data.no
}).catch((ex) => {
console.warn("ERROR!!!!! : ", ex)
})
}

[File 전송]



FormData 객체를 생성하고 this.$ref.photofile과 같이 ref 옵션을 이용해 파일 필드를 직접 참조할 수 있다. 이 필드의 값을 FormData 객체에 추가한뒤 서버로 요청하게 된다.




Vue Instance 내부에서 axios 이용하기

Vue 인스턴스 내부에서 axios를 이용하기 위해 Vue.prototype에 axios를 추가하면 간단하게 사용 할 수있다. main.js에 아래의 내용을 추가한다.


import Vue from 'vue'
//import App from './App.vue'
import App from './AppAxiosTest.vue'
import axios from '.axios'

Vue.prototype.$axios = axios;
Vue.config.productionTip = false

new Vue({
render: h => h(App),
}).$mount('#app')

[src/main.js]


이렇게 작상하면 Vue 인스턴스 내부에서는 axios를 따로 improt하지 않아도 this.$axios를 이용해서 사용할 수 있다. AppAxiosTest.vue 파일의 fetchContactone 메서드는 아래와 같이 변경할 수 있다.


fetchContactOne : function() {
this.$axios.get('/api/contacts/' + this.no)
.then((response) => {
this.result = response.data
})
},




axios 사용 시 주의 사항

axios를 사용하면서 then() 처리를 할 때는 ECMAScript6의 화살표 함수를 사용할 것을 권장한다. 데이터를 수신한 후에 Vue 인스턴스 내부의 데이터를 변경해야 하는 경우가 있는데 데이터 옵션을 액세스하기 위해서는 this 객체가 Vue인스턴스를 참조할 수 있어야 한다. then() 내부에서 화살표 함수를 하용하지 않으면 this가 vue 인스턴스를 참조하지 않기 때문에 밖에서 별도의 변수에 this를 할당한 후에 클로저 방식으로 접근해야 하는 불편함이 발생한다. 

















'Vue.js' 카테고리의 다른 글

[Vue.js] Vuex를 이용한 상태 관리 (store, mutation, getter)  (0) 2018.12.23
[Vue.js] Vue CLI(GUI)  (0) 2018.12.18
[Vue.js] Component  (0) 2018.12.18
[Vue.js] Event 처리  (0) 2018.12.17
[Vue.js] Vue instance (뷰 인스턴스)  (0) 2018.12.16

+ Recent posts