Implementing Course Management Front - TheOpenCloudEngine/uEngine-cloud GitHub Wiki

μ΄λ²ˆμ‹œκ°„μ€ VueJS λ₯Ό μ‚¬μš©ν•˜μ—¬ MSA μ˜ˆμ œμ—μ„œ μ‚¬μš©ν•˜μ˜€λ˜ Course μ„œλΉ„μŠ€λ₯Ό UI 둜 κ΅¬μ„±ν•œλ‹€.
λ‹¨μˆœνžˆ microservice 에 ν•΄λ‹Ήν•˜λŠ” UI λ₯Ό κ΅¬μ„±ν•˜λŠ” 것은 기쑴의 jquery와 HTML만 가지고
μΆ©λΆ„νžˆ ꡬ성이 κ°€λŠ₯ ν•  것이닀. ν•˜μ§€λ§Œ μ—¬κΈ°μ„œλŠ” MVVM (Model-View-ViewModel νŒ¨ν„΄) 을 μ‚¬μš©ν•˜μ—¬,
hybind λΌλŠ” ajax program 을 μ‚¬μš©ν•˜μ—¬ back-end 의 객체가 κ³§λ°”λ‘œ ν™”λ©΄κ³Ό 맀핑이 λ˜λ„λ‘ ꡬ성을 ν•  것이닀.

μ΄λ ‡κ²Œ κ΅¬μ„±ν•˜μ˜€μ„λ•Œ λ‚˜νƒ€λ‚˜λŠ” νš¨κ³ΌλŠ” ν™”λ©΄μ—μ„œ Course λΌλŠ” back-end 객체λ₯Ό loading ν•˜μ—¬ 화면에 λ‚˜νƒ€λ‚΄κ³ ,
Course 의 데이터λ₯Ό μ§€μš°κ±°λ‚˜ μž…λ ₯ν•˜λŠ” λ²„νŠΌμ„ HTML에 λ§Œλ“€κ³  ν˜ΈμΆœν•˜μ˜€μ„λ•Œ, 별닀λ₯Έ 코딩없이
데이터 μ‚­μ œλ‚˜ μž…λ ₯이 μ„±κ³΅ν•˜λ©΄ 화면에 λ°”λ‘œ μ‚­μ œλ˜κ±°λ‚˜ ν‘œμ‹œλ˜λ„λ‘ ꡬ성 ν•  μˆ˜μžˆλ‹€.

μ‹œμž‘ν•˜κΈ°μ „μ— λ§Œλ“€λ €λŠ” λΌλŠ” μ»€μŠ€ν…€ νƒœκ·Έμ˜ 결과물을 보자.

<course v-model="courses[index]" v-for='(course, index) in courses' 
   @change="updateCourse" 
   @remove="removeCourse" 
   @classes="jumpToClasses">
</course>
<script>
      var courses= [];
      var me = this;
      backend.$bind("courses", courses);
      courses.$load().then(function(courses){
         me.courses = courses; // set the view's data with the loaded data obtained from backend.
      });
</script>

마이크둜 μ„œλΉ„μŠ€μ™€ UI μ—°κ²°

μ²˜μŒλΆ€ν„° νŒŒμΌμ„ μƒμ„±ν•˜μ—¬ λ§Œλ“€μˆ˜λ„ μžˆμ§€λ§Œ, template ν”„λ‘œμ νŠΈλ₯Ό λ‹€μš΄λ°›μ€ ν›„ μ‘°κΈˆμ”© λ³€ν™˜ν•˜λ©΄μ„œ
μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜κ² λ‹€.

msa-tutorial-class-management-frontend λ‹€μš΄λ‘œλ“œ

$ git clone https://github.com/uengine-oss/msa-tutorial-class-management-frontend.git
$ cd msa-tutorial-class-management-frontend
$ npm install
$ npm run dev
> Listening at http://localhost:8082

λΈŒλΌμš°μ €λ₯Ό μ—΄μ–΄μ„œ http://localhost:8082 둜 접근을 ν•˜λ©΄ iam 둜그인 화면이 λ‚˜μ˜¨λ‹€.
test 계정인 [email protected] / test1234 둜 λ‘œκ·ΈμΈμ„ ν•œλ‹€.

마이크둜 μ„œλΉ„μŠ€λ“€κ³Όμ˜ 연결확인을 μœ„ν•˜μ—¬ clazz, coures, zuul, eureka μ„œλΉ„μŠ€λ“€μ„ λ„μš΄λ‹€.
port 좩돌이 μ•ˆλ‚˜λ„λ‘ μ„œλ‘œ λ‹€λ₯Έ port둜 κΈ°λ™ν•œλ‹€.

## 각 μ„œλΉ„μŠ€ 경둜둜 이동 
## clazz μ„œλΉ„μŠ€
$ mvn spring-boot:run -Dserver.port=8088 
## course μ„œλΉ„μŠ€
$ mvn spring-boot:run -Dserver.port=8081 
## zuul μ„œλΉ„μŠ€ 8080 port
$ mvn spring-boot:run 
## eureka μ„œλΉ„μŠ€ 8761 port
$ mvn spring-boot:run 

λΈŒλΌμš°μ €μ˜ http://localhost:8761/ 둜 접근을 ν•˜μ—¬ 3개의 μ„œλΉ„μŠ€κ°€ μ •μƒμ μœΌλ‘œ registered λ˜μ—ˆλŠ”μ§€ ν™•μΈν•œλ‹€.
λΈŒλΌμš°μ €μ˜ http://localhost:8082 μ ‘κ·Όν•˜μ—¬ ν™”λ©΄μƒμ˜ add , update , remove 등을 ν†΅ν•˜μ—¬
데이터λ₯Ό λ„£κ³  λΊΌ 수 μžˆλŠ” 것을 확인 ν•  수 μžˆλ‹€.

Vue Framework Process

이제 template ν”„λ‘œμ νŠΈμ˜ μ‹€ν–‰ ꡬ쑰λ₯Ό νŒŒμ•…ν•΄ 보겠닀.
파일의 ꡬ쑰가 λ³΅μž‘ν•˜λ‹€κ³  μƒκ°λ˜μ§€λ§Œ, μ‹€μ œλ‘œ VueJS project setting μ—μ„œ μƒμ„±ν•œ ν”„λ‘œμ νŠΈμ—,
src 폴더에 μ•½κ°„μ˜ μ½”λ“œλ§Œ λ„£μ—ˆμ„λΏ λ‚˜λ¨Έμ§€ κ΅¬μ‘°λŠ” λ˜‘κ°™λ‹€.

  1. μœ„μ—μ„œ ν”„λ‘œμ νŠΈλ₯Ό 싀행할적에 npm run dev λΌλŠ” CLIλͺ…λ Ήμ–΄λ₯Ό λ„£μ—ˆλ‹€.
    이것을 ν•΄μ„ν•˜μžλ©΄, package.json 파일의 dev λΌλŠ” scriptλ₯Ό μ‹€ν–‰μ‹œν‚€λΌλŠ” 말이닀.
    package.json 의 dev script λŠ” node build/dev-server.js λ₯Ό μ‹€ν–‰ν•˜λŠ” λͺ…λ Ήμ–΄ 이닀.

  2. build/dev-server.js νŒŒμΌμ„ 보면 require('./webpack.prod.conf') λΆ€λΆ„μ—μ„œ μ„€μ •νŒŒμΌμ„ κ°€μ Έμ˜€κ³ ,
    webpack.prod.conf νŒŒμΌμ€ webpack.base.conf νŒŒμΌμ„ merge ν•˜λ„λ‘ λ˜μ–΄μžˆλ‹€.
    webpack.base.conf μ—μ„œλŠ” ./src/main.js λ₯Ό entry μ‹œμž‘μ μœΌλ‘œ 바라보고 μžˆλ‹€.

  3. ./src/main.js 파일이 ν•΄λ‹Ή ν”„λ‘œμ νŠΈμ˜ 졜초 μ§„μž…μ μ΄κ³  μ•„λž˜ μ½”λ“œ 처럼 id κ°€ app인 elementλ₯Ό μ°Ύμ•„μ„œ Vue둜 맀핑을 ν•˜κ³  μžˆλ‹€.
    그리고 App μ΄λΌλŠ” components λ₯Ό 찾아가라 라고 λͺ…μ‹œν•˜κ³  μžˆλ‹€.
    import App from './App' 처럼 쓰인 것은 App.vue νŒŒμΌμ„ μƒλŒ€κ²½λ‘œλ‘œ μ°Ύμ•„μ„œ App μ΄λΌλŠ” μ΄λ¦„μœΌλ‘œ
    μ‚¬μš© ν•˜κ² λ‹€λŠ” μ˜λ―Έμ΄λ‹€.

import App from './App'
new Vue({
  el: '#app',
  template: '<App/>',
  components: {App},
  1. 이제 src/App.vue νŒŒμΌμ„ μ‚΄νŽ΄λ³΄μž. template 으둜 μ‹œμž‘μ„ ν•˜μ—¬ component라고 λͺ…μ‹œν•œλ‹€.
    <router-view></router-view> λŠ” 여기에 routeμ—μ„œ λ‚˜μ˜€λŠ” url둜 맀핑을 μ‹œμΌœ
    page 듀을 μ„€μ •ν•˜κ² λ‹€λŠ” μ˜λ―Έμ΄λ‹€. route 뢀뢄은 router/index.js νŒŒμΌμ— μžˆλ‹€.
<template>
  <div>
    <router-view></router-view>
  1. Vueλ₯Ό μ‹œμž‘ν• λ•Œ new Vue ν˜•μ‹μœΌλ‘œ μ‹œμž‘μ„ ν•˜λŠ”μ€„ μ•Œμ•˜μ§€λ§Œ, <script> μ½”λ“œ μ•ˆμͺ½μ—
    export default 라고 μ„€μ • 뢀뢄이 μžˆλ‹€.
    μ΄λŠ” default module을 μƒμ„±ν•˜μ—¬ node 에 export λ₯Ό ν•˜λŠ” 것이닀.
    μ΄λ ‡κ²Œ ν•˜μ˜€μ„λ•Œ ν•΄λ‹Ή 파일λͺ…μœΌλ‘œ import App from './App' 이 μ‚¬μš©μ΄ κ°€λŠ₯ν•˜μ—¬ 진닀.
    λ§Œμ•½ default κ°€ μ•„λ‹ˆκ³  named 둜 섀정을 ν•˜κ²Œ λœλ‹€λ©΄, μ•„λž˜μ™€ 같이 μ‚¬μš©κ°€λŠ₯ν•˜λ‹€.
//------ lib.js ------
export function diag(x, y)'
//------ main.js ------
import { diag } from 'lib';
console.log(diag(4, 3));
// or
import * as lib from 'lib';
console.log(lib.diag(4, 3));

parent and child component 톡신방법

이제 μ΄λ²ˆμ‹œκ°„μ˜ 주제인 course 마이크둜 μ„œλΉ„μŠ€μ™€ UIλ₯Ό μ—°κ²°ν•΄ 보자.

src/router/index.js

export default new Router({
  //mode: 'history',
  routes: [
    {
         children: [
             {
          path: 'courses',
          name: 'courses',
          component: CourseManagement,
          beforeEnter: RouterGuard.requireUser,
          meta: {
            breadcrumb: 'Courses'
          }
        },

src/components/CourseManagement.vue

<course v-model="courses[index]" v-for='(course, index) in courses' @change="updateCourse" @remove="removeCourse" @classes="jumpToClasses"></course>

<script>
  export default {
    props: {},
    data() {},
    created() {
      var me = this;
      $.ajax(
        {
          url: 'http://localhost:8080/courses',
          success: function(result){
            me.courses = result._embedded.courses;
          }
        }
      )
    },
    watch: {},
    methods: {
        updateCourse(course){
            // do something
        }
    }
  }
</script>
  1. μš°μ„  index.js μ—μ„œ routeλ₯Ό μ„€μ •ν•˜κ³  μžˆλ‹€.
    /courses λΌλŠ” path 둜 화면이 ν˜ΈμΆœλ˜μ—ˆμ„μ‹œ CourseManagement.vue μ»΄ν¬λ„ŒνŠΈλ₯Ό ν˜ΈμΆœν•˜κ³ ,
    화면에 λ“€μ–΄κ°€κΈ° 전에 RouterGuard μ—μ„œ user 체크λ₯Ό ν•˜λΌλŠ” μ˜λ―Έμ΄λ‹€.
    meta 정보에 breadcrumb μ΄λΌλŠ” λ„€λΉ„κ²Œμ΄μ…˜ μ»΄ν¬λ„ŒνŠΈμ— Courses λΌλŠ” λͺ…칭을 λ„£μ–΄μ£Όμ—ˆλ‹€.

  2. CourseManagement.vue μ—μ„œλŠ” <course> μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈ νƒœκ·Έλ₯Ό μ‚¬μš©ν•˜μ˜€λ‹€.
    μ»€μŠ€ν…€ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ§Œλ“œλŠ” 방법은 μ•„λž˜μ™€ 같이 두가지 방법이 μžˆμ§€λ§Œ,
    μ—¬κΈ° μ˜ˆμ œμ—μ„œλŠ” export default λ₯Ό μ‚¬μš©ν•˜μ—¬ Course.vue νŒŒμΌμ„ λ°”λ‘œ μ»΄ν¬λ„ŒνŠΈλ‘œ λ“±λ‘ν•˜μ˜€λ‹€.

// 1번 방법
// Vue μΈμŠ€ν„΄μŠ€ 생성
new Vue({
  el: '#some-element',
  // μ˜΅μ…˜
})
// μ»΄ν¬λ„ŒνŠΈ 등둝
Vue.component('my-component', {
  // μ˜΅μ…˜
})

// 2λ²ˆλ°©λ²•
// my-component.vue 파일
<template>
   <!-- html code -->
</template>
<script>
  export default {
      // μ˜΅μ…˜
  }
</script>
  1. props , data() , created() , watch λ“± ν•­λͺ©μ€ 맀우 μ€‘μš”ν•œ μ»΄ν¬λ„ŒνŠΈμ˜ μ˜΅μ…˜λ“€μ΄λ‹€.
    μžμ„Έν•œ μ„€λͺ…은 vue kr guide λ₯Ό κΌ­ 보길 λ°”λž€λ‹€.
    μ˜ˆμ œμ½”λ“œμ—μ„œλŠ” jquery 둜 $.ajax( 와 url: 'http://localhost:8080/courses' λ₯Ό μ‚¬μš©ν•˜μ˜€λŠ”λ°,
    μ΄λŠ” 맀우 μ•ˆμ’‹μ€ μ½”λ“œμ΄λ‹€.
    νŠΉνžˆλ‚˜ μ½”λ“œμƒμ—μ„œ url 에 μ§μ μ ‘μœΌλ‘œ ip 와 port λ₯Ό λ§€ν•‘μ‹œν‚€λ©΄ μ•ˆλœλ‹€.
    properties 파일둜 url을 κ΄€λ¦¬ν•˜λŠ” 방법도 쒋은 λ°©λ²•μ΄μ§€λ§Œ, hybind λ₯Ό μ‚¬μš©ν•˜λ©΄ 객체λ₯Ό λ°”λ‘œ λ§€ν•‘μ‹œν‚¬ 수 μžˆλ‹€.

  2. <course> λ₯Ό ν˜ΈμΆœν• λ•Œ @change="updateCourse" @remove="removeCourse" λ“±μœΌλ‘œ ν˜„μž¬ λ©”μ„œλ“œμ™€ child μ—μ„œ μ‚¬μš©ν•  λ©”μ„œλ“œλ₯Ό v-on μ‹œμΌœ λ†“μ•˜λ‹€.
    이 말의 μ˜λ―ΈλŠ” child 인 Course.vue μ—μ„œ change , remove 이벀트λ₯Ό λ°œν–‰ ($emit) ν•˜κ²Œλ˜λ©΄,
    parent 인 CourseManagement.vue 의 updateCourse, removeCourse λ©”μ„œλ“œκ°€ μ‹€ν–‰λœλ‹€.

  3. v-model μ΄λΌλŠ” λ¬Έκ΅¬λŠ” vue의 약속어 이닀. course 에 데이터λ₯Ό μ£Όμž…ν•˜κ³  싢을적에
    v-model="courses[index]" 둜 전달을 ν•˜κ²Œ 되면
    Course.vue μ—μ„œ props: {value: Object} 둜 데이터λ₯Ό 받을 μˆ˜κ°€ μžˆλ‹€.
    v-model 을 μ‚¬μš©ν•˜μ§€ μ•Šκ³ , μ§μ ‘μ μœΌλ‘œ propsλ₯Ό 지정을 ν•  μˆ˜κ°€ μžˆλ‹€.
    μ΄λ•ŒλŠ” <course :datas="courses[index]" > ν˜•μ‹μœΌλ‘œ 데이터λ₯Ό λ„˜κ²¨μ£Όκ³ 
    Course.vue μ—μ„œ props: {datas: Object} 둜 데이터λ₯Ό 받을 μˆ˜κ°€ μžˆλ‹€.

κ·ΈλŸ¬λ‚˜ :datas 처럼 μ‚¬μš©μ„ ν•˜κ²Œ 되면 ν™”λ©΄λ‹¨μ—μ„œ μ•žμœΌλ‘œ 이와 같은 μ‚¬μš©λ°©λ²•μ„ μ‚­μ œ μ‹œν‚¬ μ˜ˆμ •μ΄κ³ ,
μ›μΉ˜ μ•Šμ€ κ²°κ³Όκ°€ λ‚˜μ˜¬μˆ˜ μžˆλ‹€κ³  ν•˜λŠ” warning 이 계속 떨어진닀.

⚠️ **GitHub.com Fallback** ⚠️