개발 환경
SpringBoot 3.3.1 |
java 17.0.10 |
Gradle |
MacOS |
Java SE 17 다운로드 : https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
1. Spring Boot 프로젝트 생성
GroupId 와 AritifactId 는 자유롭게 설정하고 나머지는 위와 같이 설정합니다. + Dependencies로 Spring Web 추가 (Spring Web 의존성을 추가하면 내장된 Tomcat 서버가 포함됨)
톰캣이란?
톰캣은 서블릿을 실행하고 관리하는 서블릿 컨테이너다. 서블릿은 Java 애플리케이션에서 HTTP 요청을 처리하고 동적인 웹 페이지를 생성하는 역할을 한다. Spring Boot와 같은 프레임워크와 함께 사용할 때, 내장된 톰캣 서버를 통해 애플리케이션을 쉽게 배포하고 실행 가능
스프링부트 프로젝트를 다운로드 했다면 이제 IntelliJ IDE로 프로젝트를 열어보자.
프로젝트 우측의 Gradle에서 Tomcat이 추가된 것을 확인할 수 있다.
스프링을 실행하면 나오는 화면이다. 문제가 없다면 웹 브라우저에서 http://localhost:8080 으로 접속해보자.
이렇게 에러 페이지가 뜨면 성공이다. 위와 같은 화면이 뜨는 이유는 스프링부트에서 기본설정된 오류페이지가 'Whitelable' 페이지라 그렇다.
2. React.js 프로젝트 생성
React 프로젝트를 생성하기 전에 먼저 Node.js를 설치해야 한다. React 프로젝트에서 필요한 개발 도구와 패키지 관리 시스템 (npm 또는 yarn)을 제공하기 때문이다.
https://nodejs.org/en/download/package-manager
이미 설치가 되어있을 수 있으니 터미널에 node -v 와 npm -v 를 먼저 쳐보고 설치가 되어있다면 바로 리액트 프로젝트를 생성하면 된다.
리액트 프로젝트는 스프링 프로젝트에서 src/main 경로에 설치한다.
cd src/main
npx create-react-app frontend
main 아래에 frontend 라는 이름의 리액트 프로젝트가 생성되었다.
cd frontend
npm start
frontend로 이동하고 프로젝트를 실행시켜보자 http://localhost:3000 에 접속해서 확인하면 된다.
3. 스프링부트 + React 연동
연동을 하기 전에 우리는 CORS라고 불리는 보안 정책으로 인한 오류를 피하기 위해 몇가지 설정을 해야한다.
CORS란 Cross-Origin Resource Sharing, 출처가 다른 자원들을 공유한다는 뜻이다. (만약 서로 다른 출처의 어플리케이션이 서로 통신하는 것에 제약이 없다면 사용자 공격에 매우 취약할 것이다.)
프로토콜, 도메인, 포트 번호중 하나라도 다를 경우 교차 출처가 되는데,
- http://localhost:8080
- http://localhost:3000
현재 스프링 부트가 실행되는 포트번호 8080과 리액트가 실행되는 포트번호 3000이 서로 다르기 때문에 교차 출처가 되어 브라우저는 보안 상의 이유로 HTTP 요청을 제한하게 된다.
해결 방법은 2가지가 있다. (지금은 로컬 환경이니 2번 프론트엔드에서의 프록시 설정으로 진행하자.)
1. 백엔드에서 CORS 설정
@CrossOrigin 어노테이션을 사용하거나 관련 클래스를 직접 구현하여 CORS 설정을 구성하는 방법
// @CrossOrigin 어노테이션으로 localhost:3000에 대해 교차 출처 허용
@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class HelloController {
@GetMapping("/api/test")
public String hello() {
return "테스트입니다.";
}
}
// WebConfig 클래스 생성 후 CORS 정책 구성
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE");
}
};
}
}
2. 프론트엔드에서 프록시 설정 (https://create-react-app.dev/docs/proxying-api-requests-in-development/)
React 개발 환경에서 프록시를 설정하여 CORS 문제를 우회하는 방법
프록시 설정을 위해 필요한 모듈 설치 (frontend 폴더에서 설치)
npm install http-proxy-middleware --save
setupProxy.js 파일을 생성
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:8080',
changeOrigin: true,
})
);
};
이 설정을 통해 프론트엔드 개발 서버가 /api 경로로 들어오는 요청을 백엔드 서버로 프록시하여 CORS 문제를 해결한다.
단, 프론트에서는 주로 로콜 환경에서의 CORS 문제 해결만 가능하고 배포 후 발생하는 CORS 문제들은 백엔드에서 처리해야 안전하고 일관된 CORS 정책을 적용할 수 있다.
설정이 끝났다면 이제 연동을 진행해보자.
Axios 라이브러리
백엔드와 프론트엔드 사이의 통신을 할 때 사용하는 라이브러리로 Axios를 사용하면 간단한 API 요청이 가능하다.
Axios 라이브러리 설치 (frontend 폴더에서 설치)
npm install axios --save
src/main/frontend/src/App.js 파일의 내용을 지우고 api요청 코드를 작성
import {useEffect, useState} from "react";
import axios from "axios";
function App() {
const [hello, setHello] = useState('');
const [error, setError] = useState('');
useEffect(() => {
axios.get('http://localhost:8080/api/test')
.then((res) => {
setHello(res.data);
})
.catch((err) => {
setError(err.message);
});
}, []);
return (
<div className="App">
백엔드에서 받은 데이터: {hello}
{error && <p>Error: {error}</p>}
</div>
);
}
export default App;
스프링 부트에서 Controller 패키지 생성 후 자바파일을 만들고 코드 작성
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/api/test")
public String hello() {
return "안녕하세요 백엔드입니다.";
}
}
패키지 구조 참고
이제 각 프로젝트를 실행해보자
http://localhost:8080/api/test 실행결과
http://localhost:3000 실행결과
localhost:3000이 localhost:8080/api/test로부터 데이터를 요청하고 받아와서 출력되는 것을 확인할 수 있다.
4. 프로젝트 빌드하기
build.gradle 파일에 아래 코드를 추가
React 프로젝트가 먼저 build되고, 후에 SpringBoot 프로젝트 build 결과물에 포함시킨다는 내용이다.
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"
}
프로젝트의 홈 디렉토리에서 빌드를 진행한다. 필자의 경우 SR-Test 폴더에서 진행
./gradlew build //MacOS 기준
아래 코드에서 SR-Test 부분은 본인의 프로젝트 명으로 바꾸고 실행
java -jar build/libs/SR-Test-0.0.1-SNAPSHOT.jar
localhost:8080 에 접속하면 바뀐 8080 포트번호 에서도 결과물이 잘 올라온 것을 확인할 수 있다.
이제 개발을 마무리해서 다시 빌드를 하고 애플리케이션을 배포하면 된다.
끗
'Spring' 카테고리의 다른 글
[Spring] BeanFactory와 ApplicationContext(스프링 컨테이너) (1) | 2024.07.20 |
---|---|
[Spring] Dependency Injection (의존성 주입) 이란? (0) | 2024.07.07 |
[Spring] 스프링 빈(Bean) 의 개념 (0) | 2024.07.02 |
[Spring] spring-boot-devtools로 소스코드 수정 후 바로 적용하기 (0) | 2024.06.26 |