Spring boot와 React 연계
✒️ 2025-06-23 13:58 내용 수정
둘을 연계하게 된 계기
- 몇 번의 프로젝트 아이디어를 갈아 엎고, 취업 준비를 하면서 프로젝트 진행에 너무 소홀해서 아예 다시 처음부터 프로젝트를 진행하기로 결정했다.
- 프레임워크를 고민하던 중 Spring boot와 React를 연계한 프로젝트들이 보여 이를 사용해보기로 결정했다.
- 설정을 진행할 때 아래 참고자료의 순서대로 진행했다.
환경 설정
- 먼저 https://start.spring.io/ 에서 Spring boot 프로젝트를 생성한다.
- 압축된 프로젝트 파일을 압축 해제한 뒤, 프로젝트의
src디렉터리로 이동한다. main디렉터리에Shift+우클릭을 누른 후 powershell을 눌러 powershell을 연다.
npx create-react-app 디렉터리이름으로 React 프로젝트를 생성한다.- React 디렉터리의 이름은 구분하기 쉽도록
frontend로 설정했다. - 프로젝트 구조가
src/main/frontend가 된다.
- React 디렉터리의 이름은 구분하기 쉽도록
- 이제 Eclips나 IntelliJ를 사용하여 프로젝트를 열고,
src/main/resources/에 있는 application.properties 파일을 프로젝트 환경에 맞게 수정한다.- 포트 설정 시 React의 기본 포트인 3000번을 제외한 포트로 설정한다.
# Server config
server:
port: 9000
src/main/java/내의 프로젝트 패키지 안에 있는 Application 파일에 우클릭 - Run을 선택해 실행을 한다.- 의존성 패키지를 설치할 때 JPA를 미리 등록해두고, 서버 설정에서 Datasource를 제대로 설정하지 않으면 적절한 DB 드라이버를 찾을 수 없다는 에러가 뜬다.
- 이 때
build.gradle에서implementation의jpa항목을 제거하고 다시 실행하면 정상적으로 작동한다.
- 웹 브라우저에서
http://localhost:port를 입력하여 잘 작동하는지 확인한다.- 렌더링할 리소스가 없어 기본 에러 화면이 뜬다.
- Spring boot가 잘 가동되었다면 이번엔 터미널에서
cd src/main/react디렉터리로 이동한 후,npm start를 입력해 React 프로젝트를 실행하여 잘 돌아가는지 확인한다.
통신을 위한 설정(CORS 포함)
- 서버와 클라이언트 간의 통신을 위해서 먼저 클라이언트에 Proxy 설정을 진행한다. 먼저 터미널에서 경로를
cd src/main/react디렉터리로 이동한 다음,npm install http-proxy-middleware --save로 package.json에 의존성을 추가하면서http-proxy-middleware를 설치한다.http-proxy-middleware설치 위치는 클라이언트(React) 프로젝트의 root 경로다.- CORS(Cross-Origin Resource Sharing), React Proxy 설정 참고.
src/main/react디렉터리/src/setupProxy.js파일을 생성하고, 파일에 미들웨어 설정을 작성한다.
- React Proxy 설정#Proxy 직접 설정하기 내용 참고.
// src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api', // proxy가 필요한 요청 경로, /api/test와 같이 /api로 시작하는 요청들 포함
createProxyMiddleware({
target: `http://localhost:9000`, // 타겟이 되는 api url
changeOrigin: true, // 대상 서버 구성에 따라 host header 변경 설정
})
);
};
- 통신 테스트를 위해
npm install axios --save로axios를 설치한다.
- 설치 후에 React 프로젝트의 App.js에 axios로 통신하는 코드를 추가한다.
- 여담으로 IntelliJ에서 Javascript 수정이 개인적으론 불편해서 React 프로젝트를 VSC(Visual Studio Code 설치)로 열어 수정했다.
import axios from 'axios';
import './App.css';
import { useEffect, useState } from 'react';
function App() {
const [hello, setHello] = useState('');
useEffect(()=>{
async function axiosTest() {
const { data } = await axios.get('http://localhost:9000/api/hello');
setHello(data);
}
axiosTest();
}, []);
return (
<div className="App">
<p>
axios result : {hello}
</p>
</div>
);
}
export default App;
- 이번엔 Spring boot에서
src/main/java/projectpackage/controller디렉터리를 생성하고,controller디렉터리에 테스트용 Controller 클래스를 생성한 후 아래 내용을 작성한다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/api/hello")
public String hello() {
return "Springboot<->React";
}
}
- 웹 브라우저에
http://localhost:serverport/api/hello를 입력하여 먼저 서버에서 GET 요청을 잘 받는지 확인한다.
- 서버에서 CORS 설정을 진행하기 위해
src/main/java/projectpackage/경로에WebMvcConfig클래스를 만들고,WebMvcConfigurer인터페이스를 구현하여 메소드 오버라이딩을 진행한다.WebMvcConfigurer공식 문서 : Spring Interface WebMvcConfigurerWebMvcConfigurer인터페이스는@EnableWebMvc를 통해 활성화된 Java 기반의 Spring MVC를 커스텀하는 callback 메소드를 정의한다.- 참고 자료 : jake seo dev's 스프링 WebMvcConfigurer 인터페이스란
- Spring boot CORS 설정 참고 자료는 자료 1과 자료 2를 사용했다.
- 이 설정으로 클라이언트에 대해 접근할 수 있는 권한을 설정할 수 있다.
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true) // 쿠키 허용
.allowedOrigins("http://localhost:3000") // 요청 origin
.allowedMethods("OPTIONS", "GET", "POST", "PUT", "DELETE"); // 요청method
}
}
- 웹 브라우저에서
http://localhost:3000으로 접속하여 서버와의 통신이 제대로 이루어졌는지 확인한다.
- 여담으로 몇몇 자료들에서
axios주소를/api내용만 적었을 때 통신이 되는 경우는axios의 인스턴스 설정에서 서버 url이 이미 있는 경우로 보였다. 그냥 App.js에서 axios에 url을 작성할 경우엔http://localhost:3000/api로 클라이언트쪽의 통신으로 이루어진다. - 그리고 Spring boot에서
WebMvcConfig설정을 진행하지 않으면 클라이언트의 요청 주소가 일치하고 클라이언트에 setupProxy.js 파일 설정으로http-proxy-middleware을 적용했어도 아래 사진과 같이 CORS 에러가 발생한다.- "Access to XMLHttpRequest at 'http://localhost:9000/api/hello' from origin 'http://localhost:3000' has been blocked by CORS policy"라는 경고가 뜬다.
- 즉 클라이언트(React)쪽과 서버(Spring boot)쪽 모두 CORS 관련 설정을 해야 한다.
빌드 테스트
- 참고 자료에 따르면 개발 환경과 배포 환경이 달라 배포 시 정상적으로 작동하지 못해 갈아엎는 경우가 발생할 수 있어 미리 배포 테스트를 진행한다고 한다.
- 빌드 테스트를 위해
build.gradle에 React 프로젝트 빌드 후 Spring boot 프로젝트에 포함 시키는 코드를 추가한다.
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"
}
build.gradle에서tasks.named('test')구문 바로 아래에 추가했다.
- 코드를 추가했다면 터미널에서
./gradlew build를 입력하여 빌드를 수행한다.
- BUILD SUCCESSFUL이 뜨면 빌드가 성공적으로 끝난 것이다.
- 다음으로 터미널에
java -jar build/libs/패키지스냅샷을 입력해서 jar 파일을 실행한다.
- build된 파일은
projectRoot/build/libs디렉터리에 있다.
- 웹 브라우저를 열어
http://localhost:serverport/를 입력하면 React의 App.js 파일이 화면에 뜬다.