본문 바로가기
스프링/만들면서 배우는 실무 백엔드 개발

4. 스프링부트 3.0 적용하기 (feat. HelloWorld API 만들기)

by kdohyeon (김대니) 2023. 3. 22.
반응형

이번 시간에는 만든 프로젝트에 스프링부트 3.0 을 적용해보고 HelloWorld 를 출력하는 API 도 하나 만들어보겠습니다.


https://github.com/kdohyeon/crypto-labs/pull/5

최상단 build.gradle.kts 수정하기

스프링부트를 적용하기 위해서는 먼저 최상단에 위치한 build.gradle.kts 를 수정해야 한다.

  • 스프링부트 버전 3.0.4
  • 스프링 의존성 관리 버전 1.1.0
  • kotlin 버전 1.7.22
// build.gradle.kts

import com.linecorp.support.project.multi.recipe.configureByLabels

plugins {
    id("io.spring.dependency-management") version "1.1.0" apply false
    id("org.springframework.boot") version "3.0.4" apply false
    id("io.freefair.lombok") version "6.4.1" apply false
    id("com.linecorp.build-recipe-plugin") version "1.1.1"

    kotlin("jvm") version "1.7.22" apply false
    kotlin("kapt") version "1.7.22" apply false
    kotlin("plugin.spring") version "1.7.22" apply false
    kotlin("plugin.jpa") version "1.7.22" apply false
}

allprojects {
    group = "kdohyeon.crypto.labs"
    version = "1.0-SNAPSHOT"
}

subprojects {
    apply(plugin = "idea")
}

configureByLabels("kotlin") {
    apply(plugin = "org.jetbrains.kotlin.jvm")
    apply(plugin = "org.jetbrains.kotlin.kapt")
    apply(plugin = "org.jetbrains.kotlin.plugin.spring")
    apply(plugin = "io.spring.dependency-management")

    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        kotlinOptions {
            freeCompilerArgs = listOf("-Xjsr305=strict", "-Xjvm-default=all")
            jvmTarget = "17"
        }
    }

    tasks.withType<Test> {
        useJUnitPlatform()
    }

    the<io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension>().apply {
        imports {
            mavenBom("org.springframework.boot:spring-boot-dependencies:3.0.4")
            mavenBom("com.google.guava:guava-bom:31.1-jre")
            mavenBom("org.jetbrains.kotlin:kotlin-bom:1.7.22")
        }

        dependencies {
            dependency("org.apache.commons:commons-lang3:3.12.0")
            dependency("org.apache.commons:commons-collections4:4.4")
            dependency("commons-io:commons-io:2.11.0")
        }
    }

    repositories {
        mavenCentral()
        maven {
            url = uri("https://maven.restlet.com")
        }
        maven {
            url = uri("https://jitpack.io")
        }
    }

    dependencies {
        val implementation by configurations

        implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
        implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
        implementation("org.jetbrains.kotlin:kotlin-reflect")
    }
}

가장 기본적인 라이브러리들만 추가해두었다.

각 모듈 설정하기

각 모듈에 build.gradle.kts 파일과 gradle.properties 파일을 생성한다.

각 모듈에 build.gradle.kts 파일과 gradle.properties 파일을 생성한다.

build.gradle.kts 파일은 빈 파일로 만들어두고, gradle.properties 파일에는 label=kotlin 을 입력한다. 

label=kotlin

여기까지 하고 Gradle sync 버튼을 클릭해서 성공적으로 Gradle sync 가 되는지 확인한다.

Gradle sync

Hello World API 만들기

이제 점점 기본 틀을 만들어 가고 있으니 Hello World 를 출력하는 API 를 만들어보자.

:crypto-apps:app-api 모듈

이 모듈에 있는 build.gradle.kts 를 아래처럼 수정한다.

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
}

CryptoLabsApplication 클래스

소스 코드를 추가하기 위해 먼저 작업할 디렉토리를 만들어야 한다. 만들어야 하는 디렉토리로는 src/main/kotlin, src/main/resources, src/test/kotlin, src/test/resources 를 만든다. (지금까지 설정이 제대로 되었다면 IDE 가 새로 만들 디렉토리를 추천해준다.)

Directory 생성하기

디렉토리 4개를 모두 만들면 아래와 같은 구조가 완성된다. 그리고 바로 스프링 어플리케이션 클래스를 만들기 전에 패키지 구조도 만들어준다. "kdohyeon.crypto.labs" 와 같이 설정해줄 수 있다. 주의할 점은 패키지와 디렉토리는 달라서 꼭 패키지로 만들어주어야 한다.

생성한 패키지 아래에 "CryptoLabsApplication" 처럼 스프링 어플리케이션 클래스를 만든다.

crypto-apps 모듈의 디렉토리 구성

@SpringBootApplication
class CryptoLabsApplication

fun main(args: Array<String>) {
    runApplication<CryptoLabsApplication>(*args)
}

SampleController

Hello World 문자열을 반환할 수 있는 API 를 만들어보자. controller 패키지를 만들고 하위에 SampleController 클래스를 생성한다.

SampleController

스프링 어플리케이션 실행하기

Sample API 도 만들었으니 스프링부트를 실행시켜보자. IntelliJ 에서는 우측 상단에 위치하는 세모 모양과 벌레 모양을 클릭해서 어플리케이션을 실행시킬 수 있는데, 지금은 설정이 되어 있지 않으니 설정을 해야한다. (IntelliJ 에서 자동으로 설정을 해주는 경우도 있다.)

비활성화 되어있는 어플리케이션 실행 버튼

ADD CONFIGURATION... 을 클릭하면 아래와 같은 화면이 나오는데 순서대로 클릭해서 "Spring Boot" 까지 클릭한다. Name 과 Builds and run 부분에 값을 채워넣는다. 

스프링부트 어플리케이션 설정

여기까지 설정을 하면 어플리케이션을 실행할 수 있게 세모 버튼과 벌레 버튼이 활성화된다.

세모 버튼을 클릭해서 실행을 시켜보면 8080 포트로 웹서버가 실행된다.

실행을 해두고 브라우저에서 만들어둔 API 주소를 입력해보면 "Hello World" 가 노출된다.

트러블 슈팅

스프링부트 3.0.x 버전으로 업그레이드 시 겪었던 에러 상황들과 해결 방법에 대해 정리한다.

트러블 슈팅 1. PermittedSubclasses requires ASM9 에러

> java.util.concurrent.ExecutionException: org.gradle.api.GradleException: 
> Failed to create Jar file /Users/trenbe/.gradle/caches/jars-9/18746126a0d682c507cb5be874bd3ec6/spring-core-6.0.3.jar.
...
> Caused by: java.lang.UnsupportedOperationException: PermittedSubclasses requires ASM9
	at org.objectweb.asm.ClassVisitor.visitPermittedSubclass(ClassVisitor.java:266)

Gradle wrapper 버전 문제로 "gradle-wrapper.properties" 파일의 gradle 버전을 7.6 으로 맞춰주면 해결된다.

gradle-wrapper.properties 파일은 /crypto-labs/gradle/wrapper/ 디렉토리에 위치한다.

Gradle wrapper 버전 7.2 -> 7.6 업그레이드

트러블 슈팅 2. Cannot inline bytecode built with JVM target 17 into ... 에러

스프링부트 어플리케이션 클래스를 만드는 과정에서 아래 에러가 발생했다.

Cannot inline bytecode built with JVM target 17 into bytecode that is being built with JVM target 1.8. Please specify proper '-jvm-target' option

JVM 버전 이슈

해결 방법은 build.gradle.kts 에 kotlinOptions 으로 jvmTarget 을 명시해주면 된다. 아래 코드를 최상단 build.gradle.kts 의 configureByLabel("kotlin") { ... } 부분에 추가했다.

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
    kotlinOptions {
        jvmTarget = "17"
    }
}

추가된 부분

트러블 슈팅 3. 스프링부트 main 클래스를 찾을 수 없을 때

어플리케이션 실행을 하기 위해서는 main 클래스를 잡아줘야 하는데, 무슨 일인지 제대로 찾지 못하는 경우가 발생할 수 있다.

지속적으로 main 클래스를 찾지 못하는 모습

이럴 때는 main 클래스가 제대로 정의되어 있는지 보면 된다.

좌: main 클래스를 찾지 못함, 우: main 클래스를 찾는데 성공

반응형

댓글