지금은 리액트 프로젝트와 스프링 프로젝트를 별도로 만들어서 연동했지만 실제 배포할때는 그렇게 하지 않는다. 그럼 어떻게 하는지?
테스트용이라 종속성은 Spring Web만 추가해준다.
package com.bitc.springserver.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class TestController {
@RequestMapping("test")
public List<String> test() throws Exception {
List<String> result = new ArrayList<>();
result.add("안녕하세요");
result.add("리액트 연동 테스트 입니다.");
return result;
}
}
여기까지 기본 서버 생성 완료.
여기서 frontend는 새로 생성될 리액트 프로젝트명임
(터미널에서 안쓰고 인텔리제이에서 [파일 - 새 프로젝트 생성] 해줘도 됨)
리액트 폴더 생성됨!
콘솔창에 cd frontend
-> cd start
리액트 서버 실행 완료
리액트에 Test.jsx 생성
Test.jsx
// Test.jsx
import React from "react";
function Test(props) {
return (
<div>
<h3>스프링 프로젝트 안에서 동작하는 리액트</h3>
</div>
);
}
export default Test;
확인완료
axios 설치
Test.jsx
// Test.jsx
import React, {useEffect, useState} from "react";
import axios from "axios";
function Test(props) {
// state data
const [data, setData] = useState([]);
useEffect(() => {
axios.get('http://localhost:8080/test')
.then((req) => {
// 지역변수 data
const {data} = req;
console.log(data);
})
.catch((err) => {
console.log('통신 시 오류가 발생했습니다.')
});
}, []);
return (
<div>
<h3>스프링 프로젝트 안에서 동작하는 리액트</h3>
<ul>
{
data.map((item, index) => {
return <li key={index}>{item}</li>
})
}
</ul>
</div>
);
}
export default Test;
이대로 실행하면 CORS 에러 발생한다.
pakage.json -> "proxy": "http://localhost:8080"
코드 추가
axios.get('/test')
만 남겨놓음
에러 사라지고 정상적으로 배열이 반환됨
Test 컨트롤러
package com.bitc.springserver.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class TestController {
@RequestMapping("test")
public List<String> test() throws Exception {
List<String> result = new ArrayList<>();
result.add("안녕하세요");
result.add("리액트 연동 테스트 입니다.");
return result;
}
}
useEffect
에 setData(data);
추가
useEffect(() => {
axios.get('/test')
.then((req) => {
// 지역변수 data
const {data} = req;
setData(data);
})
.catch((err) => {
console.log('통신 시 오류가 발생했습니다.')
});
}, []);
하지만 이렇게 하면 cmd 창에서도 실행 해줘야하고, 스프링 프로젝트에서도 실행 해줘야해서 불편함
////////////////// 추가된 내용 ///////////////////////
// 리액트 프로젝트 폴더를 변수에 저장
def frontendDir = "$projectDir/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 "$buildDir/resources/main/static"
}
tasks.bootJar {
dependsOn "copyReactBuildFiles"
코드 추가 후 bootJar 더블클릭 -> jar 파일 업데이트 됨(생성시간 확인)
build.gradle 에서 해당부분 0.0.2 로 이름 바꾼후 다시 더블클릭 하면 0.0.2 버전 새로 생김
cmd창에서 새로 만든 0.0.2 버전 실행(gradle 적용 후 버전)
기존에 돌아가던 localhost:3000
에서는 안돌아가고 localhost:8080
에서 리액트가 동작이 됨
axios 방식 쓰고싶으면 스프링 프로젝트의 컨트롤러에 @RestController 붙여줘야함