티스토리 뷰

Backend 프레임워크인 Spring Boot와 Frontend 프레임워크인 Vue.js의 연동방법에 대해 살펴보겠습니다.

프로젝트 구조

.
├── src/                        # Spring 소스코드 디렉터리
│   └── main/
│       ├── java/
│       └── resources/
│           ├── static/
│           ├── templates/
│           └── application.properties
├── target/                     # Spring 빌드 디렉터리
│   └── ...
├── frontend/                   # Vue.js 루트 디렉터리
│   ├── src/                    
│   └── ...
└── pom.xml                  

Vue.js 파일들을 관리의 편의성을 위해 frontend 디렉터리 하위에 두어 Spring 파일들과 분리시켜 줍니다. Vue.js를 신규 셋팅을 하는 상황이라면, vue-cli를 이용하여 vue init webpack frontend와 같이 명령어를 입력하시면 됩니다. Vue.js 개발환경 셋팅에 대한 자세한 내용은 [vue-cli] Webpack 템플릿으로 vue.js 개발환경 구축하기를 참조하세요.

스프링 부트에서 View를 위해 Thymeleaf, JSP, Groovy, Velocity 등 여러가지의 템플릿 엔진을 지원합니다. 여기에서는 스프링 부트에서 기본으로 지원하는 엔진인 Thymeleaf를 사용하여 진행할 것 입니다. 다른 템플릿 엔진을 사용하시더라도 설정과 확장자 등만 바꿔주시면 됩니다.

우선 maven 환경이라면 pom.xml에 spring boot stater 킷의 thymeleaf 모듈을 디펜던시에 추가해 줍시다.

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

다음으로는 HTTP 요청을 처리할 샘플 web controller를 생성합니다. Webpack 빌드를 통해 index.html 파일을 생성할 것이기 때문에 return "index"를 반환합니다.

src/main/com/example/demo/GreetingController.java

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class GreetingController {

    @RequestMapping("/greeting")
    public String greeting() {
        return "index";
    }

}

이제 Webpack 빌드 시 생성되는 index.html 파일이 Thymeleaf 템플릿의 디렉터리에 위치하도록 vuejs conf 파일의 build 속성을 다음과 같이 수정합니다.

frontend/config/index.js

build: {
    // Template for index.html
    index: path.resolve(__dirname, '../../src/main/resources/templates/index.html'),

    // Assets Paths
    assetsRoot: path.resolve(__dirname, '../../src/main/resources/static'),
}

추가적인 설정 방법은 Backend 프레임워크와 통합하기에서 확인하실 수 있습니다.

이제 npm run build를 실행하면 Webpack의 빌드 결과물들이 Spring Boot의 src/main/resources/templatessrc/main/resources/static 하위에 생성될 것 입니다.

cd frontend
npm run build

빌드를 실행하면 다음과 같은 화면이 나오면 정상적으로 빌드가 이루어진 것 입니다.

Hash: fa1c05ca567f976f2bb4
Version: webpack 3.10.0
Time: 9372ms
                                                  Asset       Size  Chunks             Chunk Names
               static/js/vendor.5973cf24864eecc78c48.js     112 kB       0  [emitted]  vendor
                  static/js/app.e3f37e373a7b0be800ee.js    11.4 kB       1  [emitted]  app
             static/js/manifest.8c2c40900403ccd0117f.js    1.49 kB       2  [emitted]  manifest
    static/css/app.40074a31a2d49e73485cdf8ca0ded531.css  432 bytes       1  [emitted]  app
static/css/app.40074a31a2d49e73485cdf8ca0ded531.css.map  828 bytes          [emitted]
           static/js/vendor.5973cf24864eecc78c48.js.map     548 kB       0  [emitted]  vendor
              static/js/app.e3f37e373a7b0be800ee.js.map    21.3 kB       1  [emitted]  app
         static/js/manifest.8c2c40900403ccd0117f.js.map     7.8 kB       2  [emitted]  manifest
                                ../templates/index.html  510 bytes          [emitted]

  Build complete.

  Tip: built files are meant to be served over an HTTP server.
  Opening index.html over file:// won't work.

이제 Spring Boot를 띄워 localhost:8080/greeting에 접속하여 봅시다.

org.xml.sax.SAXParseException: 요소 유형 "meta"과(와) 연관된 "charset" 속성에는 여는 따옴표가 필요합니다.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) ~[na:1.8.0_102]
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError
    ...

그러면 위의 에러화면을 만나실 수 있습니다. Webpack이 빌드한 index.html 파일을 확인해보면 <meta charset=utf-8> 처럼 meta 태그를 닫지 않고 있는데, Thymeleaf 템플릿 엔진은 기본 설정으로 HTML5 모드로 설정되어 있기 때문에 파싱 중에 에러가 발생한 것 입니다. 간단하게 해결하시려면 Thymeleaf를 legacy html5 모드로 변경하시면 됩니다.

이제 다시 접속하시면 정상적으로 Vue.js 화면이 나오는 것을 확인하실 수 있습니다. 예제 소스 코드는 GitHub에서 확인하실 수 있습니다.


댓글