이번에 개인적으로 홈페이지를 만들고 싶어져서
홈페이지를 만들때 사용할 프론트와 백단을 고민을 좀 했다

tenor.gif

프론트같은 경우 항상 새롭게 공부하면서 하는게 좋아 Vue로 하기로 했다.

백단 같은 경우에는

  1. PHP + Laravel (학생때 전국대회준비로 썼다)
  2. Node.js + Koa (가장 편한 javascript)
  3. Spring Boot (최근 회사에 입사해서 쓰게된 스프링)

중에 내가 직접 백단을 구성해본적이 없는 Spring으로 하기로 했다.

스프링 설정

스프링은 Spring initializr 이곳에서 설정했다.
image.png
대충 이런식으로 했던거 같다

개발환경 및 배포환경 설정

원래 Vue를 쓰려고 할때는 front서버를 따로 두려고 따로 설정했지만
나중에 실 서버에 올릴때 따로따로 패치하고 키는게 귀찮아 져서 스프링에서 패키징할때 같이 빌드되도록 설정했다.

이 웹을 올리려고 리눅스 서버도 하나 새로 팠다

실서버에 기본적인 Java, Maven, Node.js, Yarn등 기본적인 설정 해주고
Vue는 vue-cli 3버전을 사용해서 만들꺼기 때문에

[root@localhost ~]# yarn global add @vue/cli @vue/cli-service-global

로 vue-cli를 설치 해준다

아까 Spring initializr로 만든 스프링 프로젝트의 루트경로로 가서

[root@localhost ~]# vue create vue

로 vue 프로젝트를 생성해준다

생성 하면 프로젝트 구조가

image.png
다음과 같이 된다.

원래 계획은 스프링 서버 실행 시 resource폴더 안에 index.html를 넣어 api 경로를 제외한 모든 경로에 접근시 index.html를 띄우기로 했지만 생각보다 쉽지 않았다.

PHP였으면 RewriteRule로 했겠지만 스프링부트는 RewriteRule를 지원 안하는거 같아
404에러 핸들링으로 404 발생시 /경로로 forward 시켜주기로 했다

지금 코드를 확인해보니 그런 코드가 없다
뭐지

vue에서 다른경로에 있다가 새로고침시 콘솔에서 warn에러가 발생하긴 하지만 세상과 타협하기로 했다

@Controller
public class RootController {

    @RequestMapping(value={"", "/", "/error", "/*"}, method = RequestMethod.GET)
    public String index() {
        return "index";
    }

}

요런식으로 작업했다. 되는거에 만족하고 넘어갔다

더 좋은 방법을 알고계시면 알려주세요
이거 한다고 3일을..

나는 Gradle대신 Maven을 사용해서 빌드 할꺼기 때문에 pom.xml을 손봐서 package할때 resource폴더에 vue프로젝트가 들어가게 해보자

Maven 설정

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <id>build vue files</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <executable>yarn</executable>
                            <arguments>
                                <argument>build</argument>
                            </arguments>
                            <workingDirectory>${basedir}/vue</workingDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

pom.xml 파일을 다음과 같이 수정하자
exec-maven-plugin은 빌드시 phase설정에 따라서 특정 명령어를 실행할 수 있다

이제 vue 프로젝트에서 vue.config.js파일을 생성한 후 내용을 수정하자

module.exports = {
  assetsDir: "static",
  outputDir: "../src/main/resources/static",
  indexPath: "../templates/index.html",
  devServer: {
    proxy: "http://localhost"
  },
  chainWebpack: config => {
    const svgRule = config.module.rule("svg");

    svgRule.uses.clear();

    svgRule.use("vue-svg-loader").loader("vue-svg-loader");
  }
};

다음과 같이 설정했다.

assetDir은 빌드시 assetDir이름으로된 폴더를 만들고 모든 경로에 prefix로 추가된다. assetDir은 굳이 안해도 되는데 이유는 밑에 적어놨다
outputDir로 배포 후 파일을 생성할 경로를 지정해준다
indexPath는 outputDir기준으로 설정해준다. thymeleaf를 사용했기 때문에 templates폴더에 따로 생성해준다.

나머지는 svg설정이나 프록시 설정이니 사용할때 작성해주면 된다.

이제 package.json파일을 보자.

"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"

다음과 같이 되어있다.
assetDir을 설정해준 이유는 build시 outputDir의 부모 폴더부터 전부 날려버려서 resource/static폴더만 지우도록 설정해줬다.
resource/static/static과 같은 경로로 설정이 되는데 다음과 같은 구조가 싫다면

"build": "vue-cli-service build --no-clean"

을 해주면 빌드시 outputDir이 삭제가 안된다

이제 나중에 빌드시 vue파일이 먼저 빌드된 후 스프링이 빌드된다.

이제 설정은 다 끝났으니 개발만 하면 된다

나는 빌드를 2가지 방식으로 한다.

  1. 로컬환경에서 빌드시
    나는 에디터로 Intellij와 vscode를 사용중인데
    Intellij에 Maven툴에는 Lifecycle안에 package를 할 수 있게 GUI툴이 있다.
    image.png
    요기서 원하는 profile 체크 후 package를 눌러 빌드해준다.

  2. 실 서버에서 빌드시
    실서버에서는
    [root@localhost ~]# mvn package -P 프로필명으로 빌드한다.

이렇게 하면 Spring Boot + Vue.js로 홈페이지를 구성할 수 있을것이다.

마치며

개인적으로 프로젝트를 구성한 방법을 기록하려고 한 내용이기도 하고
처음 포스트를 작성하는 것이다 보니 문장이 어색하거나
비효율적인 방법이나 틀린방법을 사용했을 수도 있습니다.

제가 작성한 방법외에 다른 방법은 많을 수 있으니 다른 방식으로 한 경험이 있다면 알려주세요.
지적 좀 해주세요