Vue Axios는 Vue.js에서 Promise 기반 HTTP 비동기 통신 라이브러리로 많이 사용합니다.
Vue Axios 설치하기
Vue 프로젝트에 Vue Axios를 설치하기 위해 콘솔에서 npm install 명령어를 실행합니다.
npm install --save axios
npm install에 옵션으로 --save를 추가하면 자동으로 package.json 파일의 "dependencies"에 "axios" 항목이 추가됩니다.
설치가 진행됩니다.
설치가 완료됩니다.
Vue 프로젝트의 node_modules 폴더(C:\workspaces\nodeserver\testvue\node_modules)에 axios 폴더가 추가됩니다. 그리고 package.json 파일의 "dependencies"에 "axios" 항목이 추가됩니다.
package.json 파일의 "dependencies"입니다.
"dependencies": {
"axios": "^0.21.1", --> 추가
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
}
Vue Axios 설정하기
C:\workspaces\nodeserver\testvue\src 폴더에 있는 main.js에 Vue Axios를 import 합니다.
import axios from 'axios'
그리고 전역으로 사용하기 위해 app.config.globalProperties에 추가합니다.
app.config는 Vue 프로젝트에서 전역으로 사용되는 설정 객체입니다.
config에 있는 globalProperties는 Vue 프로젝트에서 전역으로 사용되는 속성 객체입니다.
Vue 2에서는 Vue.prototype입니다.
app.config는 mount 하기 전에 설정해야 합니다.
createApp(App).use(router).mount('#app');
그래서 Vue 생성인 createApp() 메서드와 mount() 메서드를 분리합니다.
const app = createApp(App).use(router);
app.mount('#app');
그리고 mount() 메서드전에app.config.globalProperties를 추가합니다.
app.config.globalProperties.axios = axios;
전체 main.js입니다.
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
const app = createApp(App).use(router);
app.config.globalProperties.axios = axios;
app.mount('#app');
참고로
세미콜론(;)은 필수는 아닙니다.
그렇지만 저는 명확한 구분을 위해 세미콜론(;)을 사용하겠습니다.
세미콜론(;)을 사용하지 않으면 에러나 경고로 처리되게 설정하기 위해서는 C:\workspaces\nodeserver\testvue 폴더에 있는 package.json 파일에서 eslintConfig의 rules에 설정을 추가해야 합니다.
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
}
rules에서 "semi"는 ASI(Automatic Semicolon Insertion - 자동 세미콜론 사입) 대신 세미콜론을 요구하거나 허용하지 않습니다.
"off" 또는 0은 규칙을 사용하지 않습니다.
"warn" 또는 1은 경고로 규칙을 사용합니다.
"error" 또는 2는 오류로 규칙을 사용합니다.
"always"는 명령문 끝에 세미콜론(;)이 항상 필요합니다.
"never"는 명령문의 끝으로 세미콜론(;)을 허용하지 않습니다. ([, (, /, +, or -으로 시작하는 것은 제외)
"rules": {
"semi" : ["error", "always"]
}
다양한 ESLint의 rules에 대해서는 https://eslint.org/docs/rules/를 참고하시기 바랍니다.
rules를 설정하지 않고 세미콜론(;)을 사용해도 됩니다.
Vue Axios로 REST API 연동하기
HTTP GET 메서드로 REST API 서버에서 전체 게시판 내용 가져오기
1. C:\workspaces\nodeserver\testvue\src\views 폴더에서 BoardList.vue 파일을 생성합니다.
BoardList.vue 파일을 오픈하여 기본적인 Vue 컴포넌트로 코딩합니다.
<template>
<div class="board">
<h1>This is an board list page</h1>
</div>
</template>
<script>
export default {
name : 'BoardList'
};
</script>
<style scoped>
.board { width:800px; margin: 20px auto; }
</style>
2. C:\workspaces\nodeserver\testvue\src\router 폴더에서 index.js 파일을 오픈하여 const routes에 추가합니다.
{
path: '/board',
name: 'BoardList',
component: () => import('../views/BoardList.vue')
}
3. C:\workspaces\nodeserver\testvue\src 폴더에서 App.vue 파일을 오픈하여 <router-link>를 추가합니다.
<router-link :to="{name: 'BoardList'}">Board</router-link>
4. 콘솔을 실행하고 Vue 프로젝트가 있는 C:\workspaces\nodeserver\testvue 폴더로 이동합니다. 그리고 콘솔에서 npm run 명령어를 실행합니다.
npm run serve
5. 웹 브라우저에서 "http://localhost:8080"를 입력합니다.
상단에 내비게이션으로 새로 추가된 Board 링크가 생성되는 것을 확인할 수 있습니다. Board 링크를 클릭합니다.
정상적으로 생성된 BoardList 컴포넌트가 나타났습니다.
콘솔을 종료하지 않고 유지하면서 작업을 하겠습니다.
6. BoardList.vue 파일을 오픈하여 REST API 서버로부터 게시판 리스트를 가져와 사용하기 위해 <script>의 data에 배열 객체를 추가합니다.
data : function() {
return {
boardList : []
};
}
REST API 서버로부터 게시판 리스트를 가져오기 위해 axios의 get() 메서드로 호출하는 메서드를 <script>의 methods에 추가합니다. 리턴되는 응답 결과를 확인하기 위해 브라우저 콘솔로 출력합니다.
methods : {
getBoardList() {
this.axios.get("http://localhost:9000/boards").then((res)=>{
console.log(res);
}).catch((err) => {
console.log(err);
});
}
}
위에서 axios를 전역 사용하기 위해 app.config.globalProperties에 axios로 추가하였습니다. 그래서 this.axios로 사용할 수 있습니다.
get() 메서드는 HTTP GET 메서드로 요청합니다.
then() 메서드는 요청(HTTP Request)에 대한 응답(HTTP Response)이 성공하면 들어오는 메서드로 callback function를 호출합니다. 파라미터는 응답 객체입니다. "response"이나 "res"로 사용하시면 됩니다.
catch() 메서드는 요청(HTTP Request)에 대한 응답(HTTP Response)이 실패하면 들어오는 메서드로 callback function를 호출합니다. 파라미터는 에러 객체입니다. "error"이나 "err"로 사용하시면 됩니다.
then() 메서드와 catch() 메서드에서 function를 직접 사용해서 처리하면 됩니다. 그리고 화살표 함수(arrow function)로 사용할 수 있습니다.
then(function(res) {
})
또는 화살표 함수(arrow function)를 사용할 수 있습니다.
then((res) => {
})
BoardList 컴포넌트가 로딩이 완료된 후 게시판 리스트를 가져오기는 메서드를 호출하기 위해 <script>의 mounted() 메서드에 추가합니다.
mounted() {
this.getBoardList();
}
브라우저를 새로고침(F5) 하면 콘솔에 "Network Error"가 나타나고 GET 메서드로 연결할 수 없다는 에러가 나타납니다. axios가 정상 동작하고 있는 것을 확인할 수 있습니다.
브라우저에서 콘솔(Console)을 보기 위해서는 F12 키를 누르고 "Console"를 클릭하면 됩니다.
에러는 접속할 REST API 서버가 없기 때문입니다. 그래서 이전 "Node.js 레스트 API 서버 생성 및 실행"에 만든 REST API 서버를 실행하겠습니다.
7. 콘솔을 실행하고 Vue 프로젝트가 있는 C:\workspaces\nodeserver\testrestapi 폴더로 이동합니다. 그리고 콘솔에서 npm run 명령어를 실행합니다.
npm run start
8. 브라우저를 새로고침(F5) 하면 콘솔에 응답 객체가 출력되는 것을 확인할 수 있습니다.
콘솔에 응답 객체를 보면 "data"에 "success"가 true이고 "data"에 배열로 게시판 내용이 있는 것을 확인할 수 있습니다.
{
"data": {
"success": true,
"data": [
{
"no": 1,
"subject": "테스트 제목1",
"content": "테스트 내용1",
"writer": "testid1",
"writedate": "2021-08-09 13:00:00"
},
{
"no": 2,
"subject": "테스트 제목2",
"content": "테스트 내용2",
"writer": "testid2",
"writedate": "2021-08-09 13:10:00"
},
{
"no": 3,
"subject": "테스트 제목3",
"content": "테스트 내용3",
"writer": "testid3",
"writedate": "2021-08-09 13:20:00"
}
]
},
"status": 200,
"statusText": "OK",
"headers": {
"content-length": "391",
"content-type": "application/json; charset=utf-8"
},
"config": {
"url": "http://localhost:9000/boards",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*"
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1
},
"request": {}
}
9. BoardList.vue 파일을 오픈하여 <script>의 methods에 있는 getBoardList() 메서드의 then() 메서드에서 응답 객체에서 전달받은 데이터를 <script>의 data에 선언된 배열 객체(boardList)에 할당합니다.
methods : {
getBoardList() {
this.axios.get("http://localhost:9000/boards").then((res)=>{
console.log(res);
this.boardList = res.data.data;
}).catch((err) => {
console.log(err);
});
}
}
그리고 <template>에서 <script>의 data에 선언된 배열 객체(boardList)를 이용하여 테이블을 생성합니다.
<template>
<div class="board">
<h1>This is an board list page</h1>
<table>
<colgroup>
<col style="width:10%">
<col style="width:*">
<col style="width:15%">
<col style="width:25%">
</colgroup>
<thead>
<tr>
<th scope="col">번호</th>
<th scope="col">제목</th>
<th scope="col">작성자</th>
<th scope="col">작성일</th>
</tr>
</thead>
<tbody>
<tr v-for="boardItem in boardList" v-bind:key="boardItem.no">
<td>{{boardItem.no}}</td>
<td>{{boardItem.subject}}</td>
<td>{{boardItem.writer}}</td>
<td>{{boardItem.writedate}}</td>
</tr>
</tbody>
</table>
</div>
</template>
Vue 리스트 렌더링
v-for는 배열을 기반으로 블록을 렌더링 합니다.
<tr v-for="boardItem in boardList" v-bind:key="boardItem.no">
<td>{{boardItem.no}}</td>
<td>{{boardItem.subject}}</td>
<td>{{boardItem.writer}}</td>
<td>{{boardItem.writedate}}</td>
</tr>
v-for는 item in items의 형태로 items는 데이터 배열이고 item은 반복되는 배열 엘리먼트의 별칭입니다.
v-bind:key는 v-for는 각각의 배열 엘리먼트에 대해 고유한 key 속성을 제공해야 합니다. key는 각각의 배열 엘리먼트를 식별할 수 있는 고유한 값이어야 합니다.
v-for에 v-bind:key가 없으면 "Elements in iteration expect to have 'v-bind:key' directives - 반복되는 요소에는 'v-bind:key' 지시문이 있어야 합니다."라는 에러가 발생합니다.
error : Elements in iteration expect to have 'v-bind:key' directives
브라우저를 새로고침(F5) 하면 테이블로 게시판 리스트가 화면에 나타납니다.
테이블에 스타일을 적용하기 위하여 <style>에 CSS를 추가합니다.
<style scoped>
.board { width:800px; margin: 20px auto; }
.board table { width:100%; border-top:2px solid #1d4281; border-spacing:0; }
.board table th { padding:8px 10px 10px 10px; vertical-align:middle; color:#1d4281; font-size:14px; border-bottom:1px solid #ccc; background:#f8f8f8; }
.board table td { padding:7px 10px 9px 10px; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc; font-size:14px; line-heighT:150%; }
</style>
<style>에서 scoped를 설정하면 컴포넌트에서만 적용되는 스타일이 됩니다.
브라우저를 새로고침(F5) 하면 스타일이 적용된 게시판 리스트 테이블이 화면에 나타납니다.
이어서 게시판 개별 내용 보기에 대해 알아보겠습니다.