글 작성자: 개발섭

이글을 읽어보기전에!! 한번 고려해볼 점을 제가 적어뒀습니다 한번 참고 해보고 프로젝트를 진행해주세요!

 

[Java/Spring] - Spring Boot와 React를 통한 개발환경을 구성할때 고민해볼점

 

Spring Boot와 React를 통한 개발환경을 구성할때 고민해볼점

[Java/Spring] - Spring Boot와 React를 연동하여 개발환경을 만들어보자 Spring Boot와 React를 연동하여 개발환경을 만들어보자 이번에는 Spring Boot와 React를 연동하여 개발 환경을 만드는 과정을 이야기해보

sundries-in-myidea.tistory.com

 

 

이번에는 Spring Boot와 React를 연동하여 개발 환경을 만드는 과정을 이야기해보겠습니다.

 

 

Spring Boot와 React를 연동하는 과정들

 

Spring Boot로 백엔드를 만들고, 프론트엔드까지 다 만들었을때 프론트엔드에서 좀 아쉬운 점이 많았던 나는 프론트엔드를 따로 구성해서 만드는 게 더 좋다고 생각했었다.

그래서 아예 프론트엔드를 뭘로 구성하는게 좋을까? React를 아예 프론트 부분을 설정하고 Spring Boot를 백엔드를 설정하는 걸로 했습니다.

 

문제는 그걸 찾는 과정이 상당히 험난했는데... 자료들이 실제로 해보면 안되는 경우가 많았고, 그래서 되는 걸 찾아서 열심히 깃허브를 돌아다녔는데..

 

으아ㅏ아아아ㅏㅏㅏ

그중에서 가장 괜찮은 레포지토리를 찾았는데, 실제로 이 레포지토리가 설명도 잘되어있었고, 그 설명대로 따라했을때 문제점을 찾기가 쉬웠다.  아래는 그 레포지토리이다.  

아래는 그 레포지토리이다. 

https://github.com/kantega/react-and-spring

 

kantega/react-and-spring

Example of a Spring Boot project with a React frontend - kantega/react-and-spring

github.com

여기에 나와있는 가이드라인을 참고하여 내가 했었던 일련의 과정들을 설명 해보고자 한다

React SpringBoot 연동하여 개발환경 세팅하기

1. Spring Boot 기본 설정하기

 

스프링부트를 설정하기 위해서는 intellj에서 설정하거나 https://start.spring.io/에서 설정해서 프로젝트를 다운로드 받는 방식이 있다

기본설정에 Dependency Web 추가해주자

 

2. 스프링으로 간단한 Rest API 서버 만들기

 

일단 간단한 Rest API 서버를 만들어서 아래의 코드를 추가해준다.

 

package com.example.demo;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
public class HelloController {

    @GetMapping("/api/hello")
    public String hello(){
        return "안녕하세요. 현재 서버시간은 "+new Date() +"입니다. \n";
    }
}

스프링 부트를 실행시키면  아래의 주소 http://localhost:8080/api/hello 에는  다음과 같이 출력됩니다.

안녕하세요. 현재 서버시간은 Mon Mar 02 14:33:57 KST 2020입니다.

 

3. React 설치

 

리엑트를 설치하는 것은  create-react-app 활용해서 설치합니다

$ npx create-react-app frontend

이런식으로 설치를 완료를 하게된다면  다음과 같은 코드가 나옵니다.

We suggest that you begin by typing:

  cd frontend
  yarn start

해당 디렉토리로 이동하여, yarn start 혹은 npm  start 통해서 실행을 하게되면

다음과 같이 실행이 됩니다.

 

4.리액트와 스프링부트의 CORS 문제 해결하기

 

스프링부트의 백엔드 서버는 localhost:8080에서 실행되고 있고, React 프론트엔드 서버는 localhost:3000번으로 실행됩니다. 그러다보니까 CORS( cross-origin requests) 발생하게되는데, 그런 문제를 해결 하기위해서는 Proxy 프론트쪽에서 잡아주어야합니다.

 

Package.json 파일을 아래와 같이 변경합니다. 

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-scripts": "^3.3.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },

  "proxy": "http://localhost:8080",

  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

"proxy": "http://localhost:8080”,  추가 해줘야합니다.

추가 후 Spring boot와 React 서버를 켜고, 명령어를 통해서 값을 확인해보면,

curl http://localhost:3000/api/hello

안녕하세요. 현재 서버시간은 Mon Mar 02 14:33:57 KST 2020입니다.

다른 포트로도 동일한 응답이 나옴을 확인 할 수 있습니다.

 

5. React의 App.js를 변경해서 Rest API의  값을 받고 출력해내기

 

React를 완벽하게 숙지 한 상태가 아니기때문에, 위의 링크의 예제를 그대로 이용해보겠습니다.

위의 링크에서 코드를 사용하면 에러가 있기 때문에, 코드중에서 필요없는 부분을 약간 제거하고  아래 코드를 사용하면,

import React, {useState, useEffect} from 'react';
import logo from './logo.svg';
import './App.css';

function App () {
    const [message, setMessage] = useState("");

    useEffect(() => {
        fetch('/api/hello')
            .then(response => response.text())
            .then(message => {
                setMessage(message);
            });
    },[])
    return (
        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo"/>
                <h1 className="App-title">{message}</h1>
            </header>
            <p className="App-intro">
                To get started, edit <code>src/App.js</code> and save to reload.
            </p>
        </div>
    )
}

export default App;

http://localhost:3030/  이용하면, 아까 받아온 응답값과 같은 화면이 출력됩니다.

여기까지는 실행까지는 완료됩니다

아제는 실행을 하는 과정이 React 서버를 키고, Spring Boot 서버도 켜야지만 되기때문에스프링 부트를 통해서만 실행되게끔하려면 패키징을 해줘야합니다.

 

스프링부트와 React APP을 함께 패키징하기

1. Maven으로 NPM 실행시키기

 

React와 스프링 부트를 동시에 빌드시키기위해서는 maven을 통해서 빌드되는 도중에 npm이 실행되야하는데요. Maven에 새로운 Plugin을 추가해줘야합니다.

<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>1.9.1</version>
    <configuration>
        <workingDirectory>frontend</workingDirectory>
        <installDirectory>target</installDirectory>
    </configuration>
    <executions>
        <execution>
            <id>install node and npm</id>
            <goals>
                <goal>install-node-and-npm</goal>
            </goals>
            <configuration>
                <nodeVersion>v10.16.3</nodeVersion>
                <npmVersion>6.9.0</npmVersion>
            </configuration>
        </execution>
        <execution>
            <id>npm install</id>
            <goals>
                <goal>npm</goal>
            </goals>
            <configuration>
                <arguments>install</arguments>
            </configuration>
        </execution>
        <execution>
            <id>npm run build</id>
            <goals>
                <goal>npm</goal>
            </goals>
            <configuration>
                <arguments>run build</arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

다음과 같은 구문을 <plugins> 안에 추가시켜줘야합니다.

단 조건이 있습니다. 빌드시 로컬 npm, node를 사용해서 빌드를 하기때문에 로컬의 npm과 node의 버젼을 일치시켜야합니다.

 

그리고 frontend-maven-plugin의 버젼도 맞춰줘야합니다. 

https://github.com/eirslett/frontend-maven-plugin

 

eirslett/frontend-maven-plugin

"Maven-node-grunt-gulp-npm-node-plugin to end all maven-node-grunt-gulp-npm-plugins." A Maven plugin that downloads/installs Node and NPM locally, runs NPM install, Grunt, Gulp and/or Kar...

github.com

현재 저의 npm, node 버젼은 6.9.0, v10.16.3이고 플러그인의 버젼은 1.9.1입니다.

확인해보시고 자신에게 맞는 버젼을 넣어야합니다 플러그인이 최신버젼인지도 확인해보셔야합니다.

그리고 이 Maven을 업데이트 한후에  아래 명령어를 쳐야합니다.

 

./mvnw clean install

 

약간의 빌드 과정을 거쳐서 

 

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  03:22 min
[INFO] Finished at: 2020-03-02T15:27:52+09:00
[INFO] ------------------------------------------------------------------------

 

빌드 완료 구문이 뜨게되고, 이때 FrontEnd 폴더안의 Build 폴더에는 여러가지 파일들이 생겨있을 겁니다. 

 

 

2. Spring Boot JAR 파일 안에 프론트엔드 Build파일 포함 시키기

 

동일한 Plugins안에 

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <configuration>
                <target>
                    <copy todir="${project.build.directory}/classes/public">
                        <fileset dir="${project.basedir}/frontend/build"/>
                    </copy>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>

를 추가시켜준 뒤에 아까와 동일하게 

./mvnw clean install

를 실행시켜주면 아까와 동일하게 빌드를 거쳐서 빌드가 완료된 뒤에, 

target폴더를 확인해보면, 이전의 frontend/build 안에 포함되어있는 파일들이 target/classes/public 안에 들어가 있는걸 확인 할 수 있습니다. 

demo-0.0.1-SNAPSHOT.jar를 생성하게되고 이파일을 실행시키려면

java -jar target/demo-0.0.1-SNAPSHOT.jar 

로 실행시켜주면, 스프링부트의 실행화면이 터미널에 뜨며, 

http://localhost:8080/에서 아까 React서버에서 뜨던 화면이 뜨는 것을 볼 수 있습니다. 

 

 

마무리

그러면 React는 React대로 따로 개발하면되며, Spring Boot는 Spring Boot대로 따로 개발하면 되기때문에 훨씬 빠르게 만들 수 있습니다.