본문 바로가기
Nginx

Docker(CentOS 7) + Nginx + Spring Boot + Vue.js 배포하기 - ③

by WangTak 2021. 12. 27.
반응형

③ 편에서는 ② 편에서 만든 API를 호출하고 결과를 확인할 수 있는 Vue.js 애플리케이션을 만들어보도록 하겠습니다. 

 

History

①: Docker + CentOS 7 +Nginx 패키지 설치

[Nginx] - Docker(CentOS 7) + Nginx + Spring Boot + Vue.js 배포하기 - ①

 

②: Spring Boot + Spring Data JPA + RESTful API

[Nginx] - Docker(CentOS 7) + Nginx + Spring Boot + Vue.js 배포하기 - ②

 

Vue.js를 공부하면서 설치된 라이브러리의 버전에 따라서 설정이 달랐기 때문에 좀 더 유의하면서 프로젝트를 진행해야겠구나 생각했습니다. vue 프로젝트를 생성하는 모든 내용을 다루기에는 주객전도가 될 거 같아서 프로젝트 구조를 보여드리고 코드를 보여드리는 식으로 정리하겠습니다.

 

프로젝트 버전

  • 개발 도구: IntelliJ Ultimate
  • node: v16.13.1
  • npm: 8.1.2
  • @vue/cli: 4.5.15
  • vue: ^2.6.11
  • axios: ^0.24.0
  • vue-router: ^3.5.3

 

프론트 개발할 때 에디터로 Visual Studio Code를 많이 사용하시지만 IntelliJ를 주력으로 사용하는 저에게는 VS code가 생소해서 IntelliJ로 개발했습니다. (Ultimate을 사용하시면 VS code와 마찬가지로 많은 기능을 지원합니다.) IntelliJ를 사용하시면 JetBrains 사에서 제공하는 Vue 관련 Plugin을 사용하면 Code Assistant와 같은 다양한 기능을 지원받을 수 있습니다.

 

요구사항

  • vue-router 적용하기
  • axios를 사용하여 데이터 전송하기
  • 회원 가입된 Member 조회하기

 

프로젝트 구조

프로젝트 구조

 

빨간 테두리에 있는 파일들은 직접 만들거나, 기존에 있던 코드를 입맛대로 수정한 파일들입니다.

  • api/index.js: vue.js에서 axios를 사용하여 API를 호출할 때 설정을 공통화하기 위한 파일
  • components/*.vue: 페이지에 사용될 컴포넌트를 모아둔 곳
  • routes/index.js: vue-router를 직접적으로 사용하는 곳으로, 페이지의 path를 등록해둠
  • views/*.vue: 페이지를 모아 둔 곳 (ex. /signup)
  • App.vue: 핵심 vue 파일로 public/index.js의 div#app에 뿌려짐
  • main.js: App.vue의 인스턴스를 만드는 파일
  • vue.config.js: 로컬에서 개발 시 API의 주소나 CORS를 방지하기 위한 설정 파일(webpack)

 

코드를 확인하고 싶으시면 "더 보기" 버튼을 눌러 확인해주시기 바랍니다. 빨간 테두리의 코드가 정리되어 있습니다.

 

더보기

api / index.js

import axios from "axios";

const instance = axios.create({
    baseURL: "/api/"
})

function getMembers() {
    return instance.get("members")
}

function registerUser(userData) {
    return instance.post("members", userData);
}

export { getMembers, registerUser }

 

components / common / AppHeader.vue

<template>
  <header>
    <router-link to="/signup">Signup</router-link>
  </header>
</template>

<script>
export default {

}
</script>

<style scoped>

</style>

 

components / MemberListButton.vue

<template>
  <div>
    <button v-on:click="getMemberList">member list</button>
    <ul>
      <li v-for="member in members" v-bind:key="member.email">
        {{ member }}
      </li>
    </ul>
  </div>
</template>

<script>
import { getMembers } from '@/api';

export default {
  data() {
    return {
      members: ''
    }
  },
  methods: {
    async getMemberList() {
      const { data } = await getMembers();
      this.members = data.data;
    }
  }
}
</script>

<style scoped>

</style>

 

components / SignupForm.vue

<template>
  <form @submit.prevent="submitForm"> <!-- 제출하고 페이지 이동 새로고침을 막음 -->
    <div>
      <label for="email">email: </label>
      <input id="email" type="text" v-model="email">
    </div>
    <div>
      <label for="password">password: </label>
      <input id="password" type="text" v-model="password">
    </div>
    <div>
      <label for="name">name: </label>
      <input id="name" type="text" v-model="name">
    </div>
    <p>{{ logMessage }}</p>
    <button type="submit">signup</button>
  </form>
</template>

<script>
import {registerUser} from "@/api";

export default {
  data() {
    return {
      email: '',
      password: '',
      name: '',
      logMessage: '',
    }
  },
  methods: {
    async submitForm() {
      const userData = {
        email: this.email,
        password: this.password,
        name: this.name
      };
      const { data } = await registerUser(userData);
      this.logMessage = `${ data.name } 님이 가입되었습니다.`;
      this.initForm();
    },
    initForm() {
      this.email = '';
      this.password = '';
      this.name = '';
    },
  },
}
</script>

<style scoped>

</style>

 

routes / index.js

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter); // Vue.use Plugin 을 사용하기 위한 초기화 코드

export default new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/',
        },
        {
            path: '/signup',
            component: () => import('@/views/SignupPage.vue'),
        },
        {
            path: '*',
            component: () => import('@/views/NotFoundPage.vue')
        }
    ],
});

 

views / NotFoundPage.vue

<template>
  <div>
    Page is not found
  </div>
</template>

<script>
export default {

}
</script>

<style scoped>

</style>

 

views / SignupPage.vue

<template>
  <div>
    <h1>회원 가입 페이지</h1>
    <SignupForm></SignupForm>
    <MemberListButton></MemberListButton>
  </div>
</template>

<script>
import SignupForm from '@/components/SignupForm.vue';
import MemberListButton from '@/components/MemberListButton.vue';

export default {
  components: {
    SignupForm,
    MemberListButton
  }
}
</script>

<style scoped>

</style>

 

App.vue

<template>
  <div id="app">
    <AppHeader></AppHeader>
    <router-view></router-view>
  </div>
</template>

<script>
import AppHeader from '@/components/common/AppHeader.vue';

export default {
  name: 'App',
  components: {
    AppHeader
  }
}
</script>

<style>
</style>

 

main.js

import Vue from 'vue'
import App from './App.vue'
import router from '@/routes/index'

Vue.config.productionTip = false

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

 

vue.config.js

module.exports = {
    devServer: {
        proxy: {
            "^/api": {
                target: "http://localhost:9000", // 개발서버
                changeOrigin: true
            }
        },
    }
};

 

② 편에서 작성한 Spring 애플리케이션을 실행시키고, 위에서 작성한 Vue 애플리케이션을 실행시켜서 작동을 확인해보도록 하겠습니다.

 

※ ② 편에서 작성한 Spring의 port는 9000번입니다. vue.config.js의 port가 9000번인 이유입니다.

※ npm run serve를 통해 실행하면 8080 포트로 접속할 수 있습니다.

 

메인 화면

Vue 메인 화면

 

회원가입 화면

Vue 회원 가입 화면

 

메인 화면에서 Signup 하이퍼 링크를 클릭하면 회원 가입 화면으로 이동합니다. 먼저, member list 버튼을 클릭합니다. 그러면 당연하게도 저장되어 있는 회원이 없기 때문에 아무것도 출력되지 않습니다. 그럼, Input Box에 데이터를 입력하고 signup 버튼을 누릅니다. Input Box에 입력한 이름으로 회원 가입이 정상적으로 이루어졌다는 text가 출력 됩니다. 그 이후에 member list 버튼을 누르면 이전에 입력한 회원의 내용이 출력되는 것을 확인할 수 있습니다.

 

회원 가입 완료, 회원 목록 출력

 

③ 편에서는 ② 편에서 만든 API를 사용하여 회원 가입 페이지와 회원 목록을 확인하는 Vue 애플리케이션을 만들어봤습니다. ④ 편에서는 ①, ②, ③ 편을 토대로 CentOS 7 + Nginx + Vue.js + Spring의 배포를 정리하도록 하겠습니다.

 

 

반응형