본문으로 바로가기

728x90

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 with Vue.js

 

부가 설정

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를 사용하여 비동기로 데이터를 얻어오는 방식으로 프로젝트를 변경하였습니다.

소스코드

소스코드는 여기에서 다운로드 가능합니다.

 

 

참고사이트

 

 

728x90