Backend/Spring Framework

[Spring Boot] 스프링 부트 + 리액트 통합 빌드 하기 (Gradle), 리액트 라우팅 URL 오류 해결하기

mopil 2022. 6. 28. 01:09
반응형

스프링 부트와 리액트를 통합 빌드하여 배포하는 방법을 정리, 기록 한다.

 

# 디렉토리 구성

먼저 기존에 만들어 놓은 리액트 프로젝트를 스프링 프로젝트 내부로 옮겨와야한다.

frontend 디렉토리를 만들고 여기다 리액트 프로젝트를 다 넣어준다.

주의!

  • gradle 설정을 쉽게 하기위해서 리액트 프로젝트 디렉토리 명은 frontend로 고정한다.
  • 인텔리제이 내부에서 리액트 폴더를 드래그 앤 드랍하면 렉을 먹는다. 윈도우 탐색기로 폴더를 열어서 넣어주도록 하자 (좀 오래걸린다.)

 

# 리액트 설정

package.json

리액트 package.json 에 proxy를 설정해준다. (나중에 로컬 환경이 아닌곳으로 배포해도, 아이피 주소를 적으면 된다.)

 

주의!

  • http:/를 꼭 붙혀주도록 하자

 

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

스프링 부트 build.gradle 하단에 다음 스크립트를 추가한다.

내용은 스프링 부트를 jar로 빌드 할 때, 리액트도 같이 빌드해서 static 폴더에 넣겠다는 뜻이다. 

 

주의!

  • 앞서 설정한 리액트 프로젝트 디렉토리명은 frontend로 여기랑 맞춰줘야한다.

 

# 프로젝트 빌드

인텔리제이에서 Ctrl + E를 누르고 gradle -> buildJar로 jar를 빌드하면 build -> lib 폴더에 jar 파일이 생성된다.

뿐만 아니라, 리액트 프로젝트도 빌드되어 resource -> static 폴더에 index.html 이 생성된다.

 

이렇게 하면 리액트 프로젝트도 성공적으로 빌드된 상태이므로, 그냥 인텔리제이 자체로 스프링 서버를 띄워서 localhost로 접속해도 리액트 화면이 잘 나온다.

 

 

# 리액트 라우트 오류 매핑 (Url 오류 매핑)

이렇게만 하면 리액트 첫 화면만 성공적으로 나오고 추가적인 라우팅 처리를 한 페이지는 not found로 나오게 된다.

이는 스프링에서 컨트롤러로 url 매핑을 처리해주면 된다. (사실 이게 이 포스팅의 핵심이다.)

 

@Controller
public class WebController {

    @GetMapping(value =  {"", "/notice","/list", "/introduce", "/smallbus", "/limousine", "/bigbus", "/request", "/search", "/search/my"})
    public String forward() {
        return "forward:/index.html";
    }
}

이런식으로 리액트 라우트 처리를한 url을 컨트롤러에서 처리해주는 로직을 작성해 준다.

 

주의!

  • 많은 포스팅에서 ErrorController 인터페이스를 구현해서 /error 를 처리하라고 했는데, 이는 더 이상 불가능하다 (사용되지 않음)
  • 정적 index.html 을 템플릿 리졸버가 성공적으로 찾게하려면 무조건!!!!  forward:/ 를 앞에 붙혀줘야한다.

 

다음은 도움을 준 스택오버플로 답변이다.

https://stackoverflow.com/questions/44692781/configure-spring-boot-to-redirect-404-to-a-single-page-app

 

Configure spring boot to redirect 404 to a single page app

I want to configure my Spring Boot app to redirect any 404 not found request to my single page app. For example if I am calling localhost:8080/asdasd/asdasdasd/asdasd which is does not exist, it s...

stackoverflow.com

 

 

반응형