Spring과 React를 연동하려고 한다!
스프링 프로젝트 기본 세팅이 완료된 상태
작업 환경 : 인텔리제이
리엑트 작업공간 생성을 위해 scr/main
에서 새로 터미널을 연다.
>> npx create-react-app frontend
생성 완료
리엑트 서버 실행을 위해 먼저 터미널에서 frontend
폴더로 이동한다.
cd frontend
실행
npm start
리엑트 기본서버 3000번이 실행되는 것을 볼 수 있다.
서버 종료는 터미널에서
ctrl
+c
서버와 클라이언트가 동일한 IP에서 실행되면 resource 제약 없이 서로 같은 자원을 공유할 수 있겠지만, 리엑트 서버는 localhost:3000
스프링 서버는 localhost:8080
으로 동작하기 때문에 CORS 관련 이슈가 발생한다.
그래서 Proxy설정을 통해 서로 같은 도메인을 사용하도록 설정해야 한다.
src/main/frontend
폴더에서 Proxy 모듈 설치하기
npm install http-proxy-middleware --save
프록시를 설정하는 방법은 package.json
에 추가하는 방법과 src/main/frontend/src
폴더에 setProxy.js
파일을 생성하고 추가하는 방법이 있는데 나는 아주 간편한 첫 번째 방법으로 설정하겠다!!
"proxy" : "http://localhost:8080",
내가 위에 올린package.json
사진을 보면 export PORT=4000
부분을 볼 수 있다.
"scripts": {
"start": "export PORT=4000 && react-scripts start",
},
리엑트 서버는 기본 3000번으로 세팅되어있다.
이번 프로젝트에서는 프론트 팀 요구사항에 맞게 4000번으로 지정해 주었다.
application.properties
에 원하는 포트번호를 적어주면 된다.
server.port = 8080
App.js
파일을 전체 지우고 붙여넣기 한다.
// src/main/frontend/src/App.js
import React, {useEffect, useState} from 'react';
import axios from 'axios';
function App() {
const [hello, setHello] = useState('')
useEffect(() => {
axios.get('/hello')
.then(response => setHello(response.data))
.catch(error => console.log(error))
}, []);
return (
<div>
백엔드에서 가져온 데이터입니다 : {hello}
</div>
);
}
export default App;
서버에 요청이 들어왔을 때, 컨트롤러에서 해당 매핑을 찾아 실행시킨다.
정상 연결이 되었다면 {hello}부분에 Spring에서 return한 값이 들어올 것이다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MainController {
@GetMapping("/hello")
public String test(){
return "Hello, World!";
}
}
리엑트 실행 + 스프링 실행
먼저 8080/hello
로 스프링 서버에 요청하면 Hello, World! 가 나오는 것을 볼 수 있을거다.
정상적으로 리엑트와 연동이 됐다면 3000번(내 경우엔 4000번) 포트에서도 저 Hello, World!가 보여야 할 것이다.
스프링에서 Hello, World!를 가져오기 성공!!
그럼 매번 npm start하고 Spring서버를 켜고 해야할까?
번거로운 작업 없이 Spring과 React 프로젝트가 하나의 패키지가 될 수 있도록 빌드를 진행해보자!
Spring이 빌드될 때 React 프로젝트가 먼저 빌드되고, 그 결과를 Spring에 포함시킨다는 내용을 추가해주자
def frontendDir = "$projectDir/src/main/frontend"
sourceSets {
main {
resources { srcDirs = ["$projectDir/src/main/resources"]
}
}
}
processResources { dependsOn "copyReactBuildFiles" }
task installReact(type: Exec) {
workingDir "$frontendDir"
inputs.dir "$frontendDir"
group = BasePlugin.BUILD_GROUP
if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
commandLine "npm.cmd", "audit", "fix"
commandLine 'npm.cmd', 'install' }
else {
commandLine "npm", "audit", "fix" commandLine 'npm', 'install'
}
}
task buildReact(type: Exec) {
dependsOn "installReact"
workingDir "$frontendDir"
inputs.dir "$frontendDir"
group = BasePlugin.BUILD_GROUP
if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
commandLine "npm.cmd", "run-script", "build"
} else {
commandLine "npm", "run-script", "build"
}
}
task copyReactBuildFiles(type: Copy) {
dependsOn "buildReact"
from "$frontendDir/build"
into "$projectDir/src/main/resources/static"
}
> Task :buildReact
> frontend@0.1.0 build
> react-scripts build
Creating an optimized production build...
리엑트 서버, 스프링 서버 따로 따로 실행했을 때랑 다르게 8080에서 리엑트를 빌드해 가져오는 것을 볼 수 있다!!