참고자료
https://7942yongdae.tistory.com/136
Spring - 실무에서 사용하는 React + SpringBoot 프로젝트 만들기 with Gradle
이 글에서는 실무에서 사용할 수 있는 React + SpingBoot 프로젝트 구조를 만드는 과정을 알아보겠습니다. 이전에 Vue + SpringBoot 프로젝트를 만드는 방법을 알아보았는데요. 이 방법은 전문가처럼 React
7942yongdae.tistory.com
Spring Boot와 React를 이용해 프론트엔드랑 벡엔드를 둘 다 구축하려는 사람 입장에선 두 프로젝트가 하나의 IDE에서 같이 동작하게 설정하는 게 사실 가장 편리하고 관리하기도 쉬울 것이다. 그래서 이번에 프로젝트를 만들기 위해 두 개의 프레임워크를 Intellij IDEA에서 같이 작동하도록 설정하고 같이 Gradle 빌드하는 방법을 정리해 본다.
Spring Boot 설정하기
스프링 이니셜라이저 웹페이지에서 Spring Boot 설정을 마치고 의존성으로는 Spring Web과 다른 부가적인 라이브러리를 추가한다. 이후 GENERATE를 하고 다운로드한 zip파일을 해제한 후 Intellij IDEA로 열어준다.
React 설정하기
IDE에서 프로젝트가 위의 사진과 같이 열리면 이젠 React 프로젝트를 생성해 준다. React는 다음 커맨드를 터미널로 실행해 프로젝트 폴더 최상단에 위치하도록 생성한다.
npx create-react-app <프로젝트 이름> # 해당 글에선 frontend로 지정했다
이후 프로젝트 구조를 보면 다음과 같이 만들어질 것이다!
아래의 커맨드를 터미널에 입력하여 잘 작동하는지 확인해 보자
cd frontend
npm start
3000번 포트로 React가 잘 작동하는 것을 확인할 수 있다!
이젠 React가 Spring Boot로 만든 API에서 정보를 가져올 수 있도록 Proxy 설정을 해야 한다. frontend/package.json으로 이동해 보자.
{
"name": "frontend",
"version": "0.1.0",
"private": true,
....
"proxy": "http://localhost:8080"
}
package.json 파일 최하단에 다음과 같은 문구를 추가하여, React에서 발생하는 요청이 http://localhost:8080(Spring Boot의 기본 주소)로 흘러가도록 만든다. 이제 React에서 fetch(), axios.get()을 사용할 때 HTTP 요청들이 내부에서 호출할 때 Spring Boot로 들어가게 될 것이다.
Spring Boot에 API 추가하기
이제 React를 종료하고, Spring Boot로 가보자. com.example.demo 하위에 controller 패키지를 생성한다. 그다음, HelloController라는 파일을 추가하고 다음과 같은 코드를 작성한다.
package com.example.demo.controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class HelloController {
@GetMapping("/api/hello")
fun getGreeting() : String = "Hello, Client!"
}
자바일 경우는 다음과 같다.
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public String getGreeting() {
return "Hello, Client!";
}
}
이제 스프링은 /api/hello란 경로가 추가되었다! React에서 이 경로로 Get 요청을 보내보자!
React에서 GET 요청 보내기
React에서 HTTP 요청을 fetch로 보낼 수도 있지만, 여기선 Axios라이브러리를 사용하겠다. 다음과 같은 커맨드로 axios를 설치해 주자.
npm install axios
이제 frontend/src/App.js를 열고 다음과 같이 수정해 주자!
import logo from './logo.svg';
import './App.css';
import {useEffect, useState} from "react";
import axios from "axios";
function App() {
// 메세지를 담기 위한 state
const [message, setMessage] = useState("");
useEffect(() => {
// 우리가 만든 서버로 보내는 GET 요청
axios.get("/api/hello")
.then((response) => {
setMessage(response.data);
console.log(response.data);
})
.catch((error) => {
console.log(error);
})
}, []);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
A message from Spring Boot : <code>{message}</code>
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
npm start로 React를 작동시키면 아마 다음과 같은 오류가 출력될 것이다.
아까 제작한 Spring Boot를 실행하지 않아 정상적으로 정보를 가져올 수 없기 때문인데, Spring Boot를 작동시키면 해결된다. 그럼 Spring Boot를 작동시키기 위해 main() 메서드 옆의 실행 버튼을 눌러보자.
그리고 React를 새로고침하게 되면 Hello, Client! 란 메시지가 잘 전달되는 것을 알 수 있다.
이젠 IDE의 Configuration을 조금 건드려보자.
Configuration 작성
Intellij IDEA 우측상단의 Configuration은 현재 1개(Spring Boot 실행)만 등록이 되어있을 것이다.
Edit Configurations를 들어간 후, 좌측 상단 +버튼으로 NPM 설정을 들어가자.
package.json을 frontend/package.json으로, command를 start로, Node는 프로젝트에 해당하는 Node로 설정한 후, OK로 저장한다.
이젠 SpringBoot와 React를 모두 Intellij IDEA에서 작동시킬 수 있게 되었다!
이제 터미널에서 작동하던 React를 중지시키고, Configuration에서 Spring과 React를 동시에 작동시키면 하단 Run창에서 양측 애플리케이션의 상태를 모두 확인할 수 있게 된다.
패키지로 빌드하기
이젠. jar파일로 React와 SpringBoot를 하나로 묶는 작업이 남았다. 아래의 코드를 build.gradle 하단에 추가 작성해 주자.
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"
}
각 task의 의존성으로 인해, installReact -> buildReact -> copyReactBuildFiles 순으로 실행되게 된다.
installReact에서는 npm으로 필요한 의존성을 설치하고, buildReact에선 React를 build 하여 배포할 수 있게 변환, 마지막으론 copyReactBuildFiles를 통해 해당 빌드파일을 SpringBoot의 resources로 복사해 준다.
원리는 다음과 같다. 톰캣 서버는 API 요청이 들어올 때, 첫 번째로 Spring Controller에서 해당 API를 처리할 수 있는지 검색한다. 없다면 그다음에 resource에 담겨있는 파일을 검색하기 때문에 우리가 "/"에 해당하는 API를 제작하지만 않는다면, http://localhost:8080/이란 요청은 static에 담긴 React 빌드 파일로 향하게 된다.
이젠 Gradle로 빌드를 돌려보자.
터미널에서 프로젝트 최상단으로 이동한 후, 다음 커맨드를 입력해 보자.
./gradlew build
하단과 같이 BUILD SUCCESSFUL이라 출력되면 성공한 것이다.
이젠 생성된 빌드파일을 실행할 차례이다. 실행하기 전 Intellij IDEA에서 돌아가는 React와 Spring Boot 애플리케이션들을 모두 종료하고 실행하여야 한다. Intellij IDEA 애플리케이션들이 3000, 8080 포트를 이미 사용하고 있기 때문에 .jar파일이 돌아가지 않게 된다.
커맨드는 다음과 같다.
cd build/libs # 빌드 파일로 이동
ls # 빌드 파일 확인
java -jar <빌드 파일 이름> # 여기선 demo-0.0.1-SNAPSHOT.jar
이제 http://localhost:8080/으로 접속해 보자!
성공이다! 이제 배포할 때엔 저 jar 파일로만 배포하면 된다 :)
틀린 내용이나 질문은 언제나 환영입니다!
'Programming > Spring(Spring Boot)' 카테고리의 다른 글
[TIL] Spring Boot - 자바 코드로 직접 스프링 빈 제공하기, 의존성 주입 (0) | 2023.06.20 |
---|---|
[TIL] Spring Boot - 스프링 빈, 컴포넌트, Test코드와 JUnit 5 (0) | 2023.06.19 |
[TIL] Spring Boot - OAuth2, Spring Security, Serializable (0) | 2023.05.26 |
[TIL] SpringBoot 4일차 (0) | 2023.05.25 |
[TIL] Spring Boot 3일차 (0) | 2023.05.24 |