[React + Spring] 프로젝트 연동

Inung_92·2023년 7월 5일
10

Spring

목록 보기
10/15
post-thumbnail

포스팅 목적

이전에 다루었던 React + Spring Legacy 프로젝트 연동에서 버전을 업그레이드하여 연동 후 배포까지 수행하는 것을 알아보기 위함.

개발환경

  • OS : Windows
  • IDE : Intellij
  • FrameWork : Spring Boot 2.7 / React 18.2
  • language : Java 11(Spring Boot 3버전 이상은 자바 17만 지원)
  • Build : Gradle
  • DB : Postgresql

프로젝트 생성

⚡️ Spring Boot

🖥️ Intellij Spring Boot 프로젝트 생성

File > New > Project

동일하게 설정할 필요는 없으며 Spring Boot 버전에 호환되는 Java 버전을 선택하면 된다.
참고로 Spring Boot 3 버전 이상부터는 Java 17 버전 이상으로 지원한다고 한다.

Type은 Build 도구이니 본인이 편한 도구를 선택하여 주고 다음으로 넘어가자.

🖥️ Spring Boot 버전선택 및 의존성 추가

위의 세가지가 가장 기본적으로 추가되는 의존성이다. DB Driver 등에 대한 추가 설정도 가능하지만 차후에 필요할 때 추가해도되니 넘어가겠다.

🖥️ 프로젝트 설정

File > Project Structure

프로젝트의 SDK 버전이 생성 시 설정한 Java의 버전과 동일한지 확인하고 동일하지 않다면 수정해준 뒤 확인을 클릭한다.

File > Settings > Build, Excution, Deployment > Build Tools > 해당 빌드툴

Default로 Gradle로 사용하겠다고 설정되어있을텐데 이 부분을 Intellij IDE로 바꿔주고, 하단의 Gradle JVM 버전을 동일하게 맞춰주면 된다.

마지막으로 build.gradle 파일을 열어 sourceCompatibility = '11'까지 마무리해주자. 물론 해당 값은 본인이 사용하는 Java의 버전과 동일하게 설정하면된다.

🖥️ 프로젝트 실행

설정이 완료되었다면 Application 클래스를 실행시켜보자.

정상적으로 실행되면 출력되는 결과이다. 예제에서의 Application 클래스 경로는 다음과 같다.

src > main > java > com.demo.demoproject > DemoProjectApplication

정상적으로 실행된 결과를 확인하기 위해 http://localhost:8080 경로로 접속해보자.

에러페이지가 출력이 되었다면 정상적으로 서버가 가동되고 있는 상태이다.

⚡️ React

이제 Spring Boot를 생성하고 설정하였으니 React 프로젝트를 내부에 생성해보자.

🖥️ React App 생성

cd src/main
npx create-react-app {프로젝트명}

약 2~5분 가량 기다리면 프로젝트 생성이 완료되고 다음과 같은 구조를 가지게 된다.

🖥️ React App 실행

cd fronted
npm start

위와 같이 리액트 앱이 실행되는 모습이 보인다. 나는 3000번 포트가 이미 사용중이어서 3001번으로 실행하였다. 아마 여러분은 localhost:3000으로 실행되었을 것이다.

프로젝트 연동

여기까지 잘 따라왔다면 React와 Spring Boot의 프로젝트가 각각 3000번과 8080번 포트에서 수행되는 모습까지 확인했을 것이다. 그렇다면 이제 두 프로젝트를 연동시켜보자.

⚡️ Proxy 설정

기본적으로 React 프로젝트는 3000번 포트에서 작동되기 때문에 CORS 관련한 오류를 방지하기 위해서 Proxy를 설정해주어야 한다.

CORS 오류와 관련된 내용을 간단히 설명하자면 동일출처에서 데이터 요청을 하지 않았기 때문에 발생하는 오류이다. React와 Spring은 localhost라는 ip는 같지만 포트번호가 다르기 때문에 동일 출처로 판단하지 않아서 발생하는 오류이다.

이러한 부분을 방지하기 위해 Proxy 설정을 해보자.

//미들웨어 설치
npm install http-proxy-middleware --save

설치가 완료되었으면 다음경로에 setupProxy.js 파일을 생성하고 아래 코드를 작성한다.

//경로
src/main/fronted/src/setupProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:8080',	// 서버 URL or localhost:설정한포트번호
      changeOrigin: true,
    })
  );
};

이렇게 설정을 완료하였으면 '/api'로 요청을 보내게되면, Spring 서버로 요청이 도착하게 된다.

⚡️ 통신 테스트

이제 프론트(React)와 백엔드(Spring)의 통신이 정상적으로 이루어지는지 테스트를 수행할 예정이다. 테스트에 사용 될 라이브러리는 Axios이다.

// Axios 설치
npm install axios --save

설치가 완료되면 아래 코드를 App.js에 작성해주자.

import {useEffect, useState} from "react";
import axios from "axios";

function App() {
    const [hello, setHello] = useState('');

    useEffect(() => {
        axios.get('/api/test')
            .then((res) => {
                setHello(res.data);
            })
    }, []);
    return (
        <div className="App">
            백엔드 데이터 : {hello}
        </div>
    );
}

export default App;

다음으로는 Spring으로 이동하여 Controller를 생성하고 아래 코드를 작성하자.

package com.demo.demoproject.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 "테스트입니다.";
    }
}

구조는 다음과 같다.

이제 두개의 프로젝트를 시작해보겠다. 먼저 Spring을 가동시켜주고 React를 가동시켜보자.

두 프로젝트 모두 잘 동작하는 모습을 볼 수 있다.

⚡️ 빌드

이제 모든 설정 및 테스트가 끝났으니 빌드 후 배포했을 때 잘 동작하는지 알아보자. 참고로 개발환경과 배포 환경은 다른 경우들이 많기 때문에 배포를해서 정상적으로 작동하는지 먼저 확인하고 개발을 시작하는 것이 좋다.

공들여서 개발을 다 해놨는데 배포 단계에서 갈아엎는 경우들이 생긴다. 물론 초보라서 이런 실수를 하는 것이지만 이 글을 읽는 분들은 대부분이 나와 같은 초보라는 생각을 하기 때문에 노파심에 강조를 한번하고 넘어가겠다.

build.gradle 파일에 하단 코드를 추가하자.

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"
}

해당 코드는 Spring Boot 프로젝트가 빌드 될 때 React 프로젝트를 먼저 빌드하고 결과를 Spring Boot 프로젝트에 포함시키겠다는 의미이다.

작성을 완료하고 홈 디렉토리로 이동하여 아래 명령어로 빌드를 수행하자.

./gradlew build

위와 같은 화면이 보이면 아래 명령어를 실행하자.

java -jar build/libs/demo-web-0.0.1-SNAPSHOT.jar

위 사진을 보면 포트번호가 8080으로 바뀌어져 있는 모습을 볼 수 있습니다. 이제 개발을 하고 다시 빌드를 하면 정상적으로 어플리케이션을 배포 할 수 있습니다.

그럼 이만.👊🏽

profile
서핑하는 개발자🏄🏽

0개의 댓글