해당 라이브러리는 말이 필요 없다.

적용 방법은 아래와 같으며, 간단하게 날짜에 관한 문제를 거의 모든걸 해결해준다.

document.addEventListener("DOMContentLoaded", function(){
	var nowMoment = moment(new Data());
	nowMoment.format('YYYY-MM-DD hh:mm:ss');       // 2020-06-09 16:43:22

	// Add day 
	nowMoment.add(1, 'days').format('YYYY-MM-DD');   // 2020-06-10
  // Add Month 
	nowMoment.add(1, 'months').format('YYYY-MM-DD');  // 2020-07-10
  // Add Year
	nowMoment.add(1, 'years').format('YYYY-MM-DD');  // 2021-07-10

  // first Month Date
	nowMoment.startOf('month').format('YYYY-MM-DD');  // 2021-07-01
  // end Month Date
	nowMoment.endOf('month').format('YYYY-MM-DD');  // 2021-07-31

});

 

 

IDE에 Spring Boot 설치 및 설정 관련 사항은 별도 설명 없이 프로젝트 생성 부터 설명이 진행한다.

 

1. Spring Boot 프로젝트 생성하여 아래와 같은 Dependencies를 추가 한다.

* JDBC API
* Spring Data JPA
* Spring Data JDBC
* Rest Repositories
* Rest Repositories HAL Browser

2. Depdependency 내용

Gradle - Build.gradle 

plugins {
	id 'org.springframework.boot' version '2.2.4.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'com.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-data-rest'
	implementation 'org.springframework.data:spring-data-rest-hal-browser'
	compile 'mysql:mysql-connector-java'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}

maven - Pom.xml

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-rest-hal-explorer</artifactId>
		</dependency>

		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

3. 기본 게시판 Entity 내용

/* com.demo.back.entity>Board.java */ 
package com.demo.back.entity;

import java.time.LocalDate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Board {
	
	@Id
	@GeneratedValue
	private Long seq;
	
	@Column
	private String title;
	
	@Column
	private String context;
	
	@Column
	private LocalDate uptDt;
	
	@Column
	private LocalDate regDt;

	.... getter & setter ...
}

4. 레파지토리 연계 리소스

/* com.demo.back.repository > BoardRepository.java */

package com.demo.back.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

import com.demo.back.entity.Board;

@RepositoryRestResource(collectionResourceRel = "board", path = "board")
public interface BoardRepository extends JpaRepository<Board, Long>{
}

5. application 설정 파일

/* src/main/resources/application.properties */

server.port=8000

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/simpleBoard?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=simpleBoard
spring.datasource.password=simple

spring.data.rest.base-path=/api
spring.data.rest.default-page-size=10

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true

6. 외부에서 접근 가능 하게 Header 정보 변경

/* com.demo.back.common > CORSFilter.java */
package com.demo.back.common;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;

@Component
public class CORSFilter implements Filter {
	
	@Override
	public void init(FilterConfig fileterConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        filterChain.doFilter(servletRequest, servletResponse);
    }
	
	@Override
	public void destroy() {
		
	}
}

7. 구동 후 http://localhost:8000/api/ 접속 하면 위 Dependencies 했던 Rest Repositories HAL Browser 가 실행하여 테스트 할 수 있습니다.

IDE 도구는 Visual Studio Code 로 작업 진행하고 IDE에 사용 되는 Vue 관련 플로그 인은 별도 설명은 생략 한다.

1. Vue Js 앱 생성 과정

# vue-cli 설치
$ npm install -g @vue/cli
# vue 앱 생성
$ vue create simple-board
$ cd simple-board
# vuetify 추가 설치
$ vue add vuetify
# 설치 진행중 질문 사항
✔  Successfully installed plugin: vue-cli-plugin-vuetify

? Choose a preset: Configure (advanced)
? Use a pre-made template? (will replace App.vue and HelloWorld.vue) Yes
? Use custom theme? No
? Use custom properties (CSS variables)? No
? Select icon font Material Icons
? Use fonts as a dependency (for Electron or offline)? Yes
? Use a-la-carte components? No
? Use babel/polyfill? Yes
? Select locale Korean
# 기본 vueJS 앱 서버 실행
$ npm run serve
# 성공시 아래와 같은 메시지 확인과 주소 접근시 페이지 확인 가능.
DONE  Compiled successfully in 5252ms                                                                                                                                                       10:45:31 AM

  App running at:
  - Local:   http://localhost:8080/
  - Network: http://192.168.1.179:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

2. 앱 생성 후 기본 주요 디렉토리 구조

├─node_modules             
├─public    
├─src
│  ├─App.vue
│  ├─main.js 
│  ├─assets
│  ├─components
│  │  └─HelloWorld.vue
│  └─plugins
│	  └─vuetify.js
├─babel.config.js
├─package-lock.json
├─package.json
└─README.md

3. Router 설치

# vuex 및 vue-router 설치
$ npm install --save-dev vue-router vuex

4. Router 적용

/* ## -- src/main.js 변경 사항 */
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import router from './router'
import '@babel/polyfill'
import 'roboto-fontface/css/roboto/roboto-fontface.css'
import 'material-design-icons-iconfont/dist/material-design-icons.css'

Vue.config.productionTip = false

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


/* ## -- src/router 폴더 생성 후 index.js 내용 */
import Vue from 'vue'
import Router from 'vue-router'
import BoardList from '@/components/BoardList'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'BoardList',
      component: BoardList
    }
  ]
})

*/ ## -- src/App.vue 변경 내용 */
<template>
  <div id="app">
    <v-app-bar>
        Simple Board
    </v-app-bar>
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>

5. 게시판 목록 / 상세 / 작성 라우터 설정

/* axios 설치 */
$ npm install --save-dev axios

/* ## src/router/index.js 내용 변경 */
import Vue from 'vue'
import Router from 'vue-router'
import BoardList from '@/components/BoardList'
import BoardView from '@/components/BoardView'
import BoardWriter from '@/components/BoardWriter'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'BoardList',
      component: BoardList
    },
    {
      path: '/view/:seq',
      name: 'BoardView',
      component: BoardView
    },
    {
      path: '/writer',
      name: 'BoardWriter',
      component: BoardWriter
    }
  ]
})

6. 각 게시판 목록 / 상세 / 작성 컨포넌트 파일 생성 및 내용

/* ## BoardList.vue 내용 */
<template>
  <v-container>
    <v-data-table
      :headers="headers"
      :items="desserts"
      :items-per-page="5"
      class="elevation-1"
      @click:row="rowClick"
    >
    </v-data-table>
    <v-row>
      <v-btn outlined color="blue" @click="writeClick" > 작성 </v-btn>
    </v-row>
  </v-container>
</template>

<script>
import axios from 'axios'

export default {
  name: 'BoardList',
  created() {
    this.fetch()
  },
  methods: {
    fetch() {
      console.log('fetch list')
      axios.get('http://localhost:8000/api/board/list')
      .then((response) => {
        console.log(response)
      })
      .catch((error) => {
        console.log(error)
      })
    },
    writeClick() {
      this.$router.push('/writer')
    },
    rowClick(item) {
      this.$router.push('/view/' + item.seq)
    }
  },
  data () {
      return {
        headers: [
          {
            text: 'Number',
            align: 'left',
            sortable: false,
            value: 'number',
          },
          { text: 'Title', value: 'title' },
          { text: 'Reg Date', value: 'regDt' }
        ],
        desserts: [],
      }
    }
};
</script>

/* ## BoardWrite.vue 파일 내용 */
<template>
  <v-form>
    <v-container>
      <v-row>
        제목
      </v-row>
      <v-row>
        <v-text-field
          :counter="50"
          label="제목"
          name="title"
          required
          v-model="title"
          maxlength="50"
        ></v-text-field>
      </v-row>
      <v-row>
        내용 
      </v-row>
      <v-row>
        <v-textarea
          filled
          name="context"
          hint="내용을 입력해주세요."
          v-model="context"
          :counter="1000"
          maxlength="1000"
        ></v-textarea>
      </v-row>
      <v-row>
        <v-btn block outlined color="blue" @click="writeClick"> 등록 </v-btn>
      </v-row>
    </v-container>
  </v-form>    
</template>

<script>
import axios from 'axios'

export default {
  name: 'BoardWriter',
  methods: {
    writeClick() {
      if(this.$route.params.seq) {
        axios.put('http://localhost:8000/api/board', this.$data)
        .then((response) => {
          console.log(response)
          this.$router.push('/')
        })
        .catch((error) => {
          console.log(error)
        })
      } else {
        this.$data.regDt = this.getNowDate()
        this.$data.uptDt = this.getNowDate()
        axios.post('http://localhost:8000/api/board', this.$data)
        .then((response) => {
          console.log(response)
          this.$router.push('/')
        })
        .catch((error) => {
          console.log(error)
        })
      }
    },
    getNowDate() {
      var nowDate = new Date()
      var year = nowDate.getFullYear().toString()
      var month = (nowDate.getMonth() + 1).toString()
      var day = nowDate.getDate().toString()

      return year + "-" + (month[1] ? month : "0" + month[0]) + "-" + (day[1] ? day : "0" + day[0])
    }
  },
  data () {
    return {
      title : '',
      context: '',
      uptDt: '',
      regDt: ''
    }
  }
}
</script>


/* ## BoardView.vue 파일 내용 */
<template>
  <v-form>
    <v-container>
      <v-row>
        제목
      </v-row>
      <v-row>
        {{ title }}
      </v-row>
      <v-row>
        내용 
      </v-row>
      <v-row>
        {{ context }}
      </v-row>
      <v-row>
        <v-btn block outlined color="blue" @click="listClick"> 목록 </v-btn>
      </v-row>
    </v-container>
  </v-form>    
</template>

<script>
import axios from 'axios'

export default {
  name: 'BoardView',
  created() {
    this.fetch()
  },
  methods: {
    fetch() {
      axios.get('http://localhost:8000/api/board/' + this.$$router.params.seq)
      .then((response) => {
        console.log(response)
      })
      .catch((error) => {
        console.log(error)
      })
    },
    listClick() {
      this.$router.push('/')
    },
    deleteClick() {
      if(this.$data.seq) {
        axios.delete('http://localhost:8000/api/board/' + this.$data.seq)
        .then((response) => {
          console.log(response)
          this.$router.push('/')
        })
        .catch((error) => {
          console.log(error)
        })
      }
    }
  },
  data () {
    return {
      title : "",
      context: ""
    }
  }
}
</script>

'Javascript' 카테고리의 다른 글

날짜 라이브러리 moment JS  (1) 2020.06.10
Vue Js 설치  (0) 2019.10.01
자바스크립트(Javascript)에서 GET 파라메타 함수  (0) 2018.09.10
jQuery 웹 페이지 로드 테스트  (0) 2018.09.06
jQuery Template 사용.  (0) 2018.09.04

+ Recent posts