Java 기반 프로젝트에서 Vue를 적용하는데 각각의 프로젝트의 개발환경이 달라 빠른 개발을 진행하기에 어려운 부분이 있습니다. 본 포스트에서는 Spring의 backend 개발의 장점과 Vue의 frontend 개발의 장점을 결합하는 방법에 대해서 알아봅니다.
SpringBoot 프로젝트 생성 및 실행
SpringBoot 프로젝트 생성
신규 SpringBoot 프로젝트를 생성하고 추가 라이브러리를 pom.xml에 추가합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Controller, View 생성
controller 패키지를 만들고 HomeController.java를 아래와 같이 생성합니다.
package kr.ejsoft.spring.with.vuejs.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HomeController {
@RequestMapping(value="/", method=RequestMethod.GET)
public ModelAndView home() {
ModelAndView mav = new ModelAndView();
mav.addObject("message", "Home...");
mav.setViewName("index");
return mav;
}
}
/src/main/resources/templates 에 index.html을 생성합니다.
<!doctype html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" type="text/css" href="./css/style.css">
</head>
<body>
<div th:text="${message}"></div>
</body>
</html>
/src/main/resources/static 에 css 디렉토리를 생성하고 style.css 파일을 생성합니다.
*, body {
font-size:10pt;
}
실행 테스트
지금까지 작업한 내용을 확인합니다.
Vue.js 프로젝트 생성 및 실행
node.js와 vue-cli 가 미리 설치되어 있어야 합니다.
Vue.js 프로젝트 생성
Terminal 또는 Command 창에서 SpringBoot 프로젝트의 /src 경로로 이동한 후 아래의 명령을 수행합니다.
프로젝트 옵션은 각기 개발 환경에 따라서 적절하게 선택 또는 수정합니다.
vue create front
cd front
vue create front
Vue CLI v4.1.1
? Please pick a preset:
default (babel, eslint)
> Manually select features
Vue CLI v4.1.1
? Please pick a preset: Manually select features
? Check the features needed for your project:
(*) Babel
( ) TypeScript
>( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
( ) CSS Pre-processors
( ) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
Vue CLI v4.1.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) n
Vue CLI v4.1.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Use history mode for router? (Requires proper server setup for index fallback in production) No
? Where do you prefer placing config for Babel, ESLint, etc.?
In dedicated config files
> In package.json
Vue CLI v4.1.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Use history mode for router? (Requires proper server setup for index fallback in production) No
? Where do you prefer placing config for Babel, ESLint, etc.? In package.json
? Save this as a preset for future projects? (y/N) N
Vue CLI v4.1.1
Creating project in \kr.ejsoft.spring.with.vuejs\src\front.
Initializing git repository...
Installing CLI plugins. This might take a while...
......
Successfully created project front.
Get started with the following commands:
$ cd front
$ yarn serve
WARN Skipped git commit due to missing username and email in git config.
You will need to perform the initial commit yourself.
cd front
실행테스트
npm run serve 명령을 수행하여 vue를 실행합니다.
npm run serve
DONE Compiled successfully in 2947ms 13:52:04
App running at:
- Local: http://localhost:8081/
- Network: http://192.168.1.85:8081/
Note that the development build is not optimized.
To create a production build, run yarn build.
실행 화면
프로젝트 병합
SpringBoot thymeleaf 사용을 위한 public/index.html 수정
<!-- <html lang="en"> -->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
Spring 데이터 바인딩
Axios 모듈 추가
axios을 추가합니다.
npm install --save axios
Axios Redirect 설정
vue.config.js 파일을 추가하고 내용을 아래와 같이 추가합니다. /data 및 target을 적절하게 수정하십시오. pathRewrite 옵션은 호출하는 경로를 변경합니다. 이 설정은 개발시에만 유효합니다.
module.exports = {
devServer: {
proxy: {
'/data': {
target: 'http://localhost:8080',
changeOrigin: true,
// pathRewrite: {
// '^/data': ''
// }
}
}
}
}
App.vue 수정
<template>
<div id="app">
<div>{{ message }}</div>
<div id="nav">
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<script>
const axios = require('axios');
export default {
data : function() {
return {
message : ""
}
},
methods : {
load: function() {
axios.get("/data", {
params: {
msg: "Index..."
},
timeout: 1000
})
.then( res => {
// console.log(res.data)
this.message = res.data.message;
})
.catch(
error => {
console.log("Data가 없습니다.");
}
);
}
},
mounted : function() {
this.load();
}
}
</script>
Axios 요청 처리
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
......
@RequestMapping(value="/data", method=RequestMethod.GET)
@ResponseBody
public Map<String, Object> data(@RequestParam(name="msg") String msg) {
logger.debug("Message : {}", msg);
Map<String, Object> map = new HashMap<String, Object>();
map.put("message", "Server message with " + msg);
return map;
}
}
프로젝트 자동 빌드
pom.xml에 아래의 설정 내용을 참고하여 적절한 위치에 복사한 한 설정에 맞게 값들을 적절하게 수정합니다.
<properties>
<frontend-maven-plugin.version>1.8.0</frontend-maven-plugin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<workingDirectory>src/front</workingDirectory>
</configuration>
<executions>
<!-- Install our node and npm version to run npm/node scripts-->
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v12.12.0</nodeVersion>
</configuration>
</execution>
<!-- Install all project dependencies -->
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<!-- Build and minify static files -->
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
<!-- Run Unit tests with Jest -->
<!--
<execution>
<id>npm run test:unit</id>
<goals>
<goal>npm</goal>
</goals>
<phase>test</phase>
<configuration>
<arguments>run test:unit</arguments>
</configuration>
</execution>
-->
<!-- Run End2End tests with Nightwatch -->
<!--
<execution>
<id>npm run test:e2e</id>
<goals>
<goal>npm</goal>
</goals>
<phase>test</phase>
<configuration>
<arguments>run test:e2e</arguments>
</configuration>
</execution>
-->
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>Copy App Content, Templates ${project.basedir}</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/src/main/resources/templates</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>${project.basedir}/src/front/dist</directory>
<includes>
<include>*.html</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>Copy App Content, Static</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/src/main/resources/static</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>${project.basedir}/src/front/dist</directory>
<includes>
<include>css/</include>
<include>js/</include>
<include>img/</include>
<include>favicon.ico</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
프로젝트 빌드
maven install 명령을 수행하여 프로젝트를 빌드합니다. 빌드시 npm을 자동으로 설치하고 node.js 관련 모듈을 자동으로 다운로드 한 후에 vue를 빌드합니다. vue의 빌드가 완료된 이후 리소스를 SpringBoot에 자동으로 복사합니다.
실행화면
부가 설정
SpringBoot의 .gitignore 수정
아래와 같이 vue 프로젝트의 .gitignore 파일 내용을 복사하여 SpringBoot 프로젝트의 .gitignore 파일에 붙여넣은 뒤 src/front/ 경로를 앞에 붙여 vue 프로젝트에서 git로 관리되지 않도록 합니다.
### Vue ###
src/front/.DS_Store
src/front/node
src/front/node_modules
src/front/dist
# local env files
src/front/.env.local
src/front/.env.*.local
# Log files
src/front/npm-debug.log*
src/front/yarn-debug.log*
src/front/yarn-error.log*
# Editor directories and files
src/front/.idea
src/front/.vscode
src/front/*.suo
src/front/*.ntvs*
src/front/*.njsproj
src/front/*.sln
src/front/*.sw?
글을 마치며
초기에 vue에서 작업한 파일과 thymeleaf 를 통하여 데이터를 연동하려 하였습니다. 하지만, 저희 예상과는 다르게 vue에서 빌드하면서 모든 html 노드들을 분리하여 자바스크립트로 생성하는 관계로 thymeleaf에서는 데이터를 바인딩할 수 없었습니다. 생성된 index.html 에서는 <div th:text=""></div> 자체가 없어졌습니다. 따라서, axios를 사용하여 비동기로 데이터를 얻어오는 방식으로 프로젝트를 변경하였습니다.
소스코드
소스코드는 여기에서 다운로드 가능합니다.
참고사이트
- frontend-maven-plugin
https://github.com/eirslett/frontend-maven-plugin - Vue.js 프로젝트에 axios 설치하기
https://ux.stories.pe.kr/138
'Development > Node.js, Vue.js, Electron.js' 카테고리의 다른 글
[TCP Socket Router #03] Implements TCP Router Communication (0) | 2020.02.25 |
---|---|
[TCP Socket Router #02] Electron Architecture, IPC Main/IPC Renderer (0) | 2020.02.24 |
[TCP Socket Router #01] Create Electron Project (0) | 2020.02.22 |
TCP Socket Server & Client by Node.js (0) | 2020.02.21 |
Vue.js 다중 페이지 작업 설정 (0) | 2019.12.09 |