Kotlin/JS React + Spring Boot – 2

그래서 빌드를 어떻게 할지 고민을 했는데 좀 수정을 해야한다.

우선, 저번에 multiplatform대신 js를 쓰면 자바스크립트로만 되니까 어쩌구 했던건 안하는게 좋을것같다. 워닝메시지로 js만 쓰는건 나중에 없어질것이니 multiplatform을 쓰라고 나온다…

그리고 bootJar를 이용하여 백엔드에 포함시킬 것이라 다음과 같이 작동하는 task를 만들어야한다.

  1. frontend 빌드
  2. frontend 빌드된 것들을 backend의 resources에 복사
  3. backend bootJar 빌드

그러기에 앞서 backend의 resources를 서빙하기 위해 보통 resources/static/js, resources/static/css 를 사용하기 때문에 복사 편의를 위해 frontend의 output 구조를 약간 바꿔야한다.

요런식으로 번들된 파일을 static/js 밑에 놓이게한다. 프론트엔드에서 별도의 css등을 포함하게… 할 필요가 없나 cssSupport나 scssSupport를 쓰면 require(“~~.css”)를 하면 알아서 style태그에 포함해주니… 여튼 jsMain.resources는 dist에 그대로 복사를 해주니 복사하는 task를 만들면 그 경로에 있는 파일들은 자동으로 복사된다.

./frontend.js가 static/js/frontend.js가 되었으므로 index.html과의 뎁스가 달라졌다. index.html 내의 /frontend.js도 /static/js/frontend.js 로 수정해야한다.

다음은 백엔드쪽 세팅이다. 이건 뭐… 리소스 설정이랑 html파일 서빙… 이런거라서

// 위쪽 package, imports, annotations 생략
class AppConfig(
    private val crossOriginProperties: CrossOriginProperties
) : WebFluxConfigurer {
    override fun addCorsMappings(registry: CorsRegistry) {
        for (allowedOrigin in crossOriginProperties.allowed) {
            registry.addMapping(allowedOrigin.mapping).allowedOrigins(allowedOrigin.origin)
        }
    }

    // 리소스 핸들러 추가
    override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        registry.addResourceHandler("/static/**")
            .addResourceLocations("classpath:/static/")
            .setCacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
    }

    @Bean
    fun routes(): RouterFunction<ServerResponse> = RouterFunctions.nest(RequestPredicates.path("/api"),
        RouterFunctions.route(RequestPredicates.GET("/hello")) {
            ServerResponse.ok().body(BodyInserters.fromValue("Hello World!"))
        }
    ).andNest(
        // 아래쪽 index.html 서빙 추가
        RequestPredicates.path("/"),
        RouterFunctions.route(RequestPredicates.GET("/")) {
            ServerResponse
                .ok()
                .contentType(MediaType.TEXT_HTML)
                .body(BodyInserters.fromResource(ClassPathResource("index.html")))
        }
    )
}

이제 최상단 build.gradle.kts에 task를 만든다. Task는 2개를 만들것이다.

  1. 프론트 빌드하고 복사하는 태스크
  2. 1과 백엔드 빌드하는 태스크

build.gradle.kts 마지막에 다음을 추가한다.


val frontendProject = subprojects.find { it.name == "frontend" }!!
val backendProject = subprojects.find { it.name == "backend" }!!

tasks.register<Copy>("copyFrontEndToBackEnd") {
    // 이 task가 실행되려면 frontend의 build가 실행되어야함
    dependsOn(frontendProject.tasks.getByName("build"))
    copy {
        // 복사       
 from(frontendProject.layout.buildDirectory.dir("dist/js/productionExecutable"))
        include("**/*.html", "**/*.js", "**/*.css")
        into(backendProject.layout.projectDirectory.dir("src/main/resources"))
    }
}

tasks.register("buildFullstack") {
    // 위에서 만든걸 먼저 해야함
    dependsOn(tasks.getByName("copyFrontEndToBackEnd"))
    // bootJar 빌드해야함
    dependsOn(backendProject.tasks.getByName("bootJar"))
}

이러면 대충은 되는듯?


근데 생각해보니 프로젝트 구조가 좀 잘못되긴 한 듯?

backend 메인 프로젝트에 frontend가 서브로 들어가 있는게 맞는 것 같다. 나중에 다시 올려야징

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다