[Kotlin, Spring] 간단한 블로그 애플리케이션 만들기 (2) - build.gradle.kts 및 BlogApplication.kt 분석

은지일·2023년 9월 6일
0

Kotlin

목록 보기
2/2

다음 블로그 게시글은 Spring.io Guides의
Building web applications with Spring Boot and Kotlin을 기반으로 작성되었습니다.

지난 시간에 이어 Kotlin & Gradle 기반 Spring Boot 프로젝트를 생성했을 때 만들어지는
build.gradle.kts 및 기본 애플리케이션 클래스 파일 BlogApplication.kt 파일을 분석해 보겠다.
Java 기반 프로젝트와의 차이점에 집중해서 살펴보면 좋을 것 같다.

1. build.gradle.kts 분석

생성된 프로젝트의 루트 경로에서 build.gradle.kts 파일을 확인 할 수 있다.
위에서부터 천천히 살펴보자.

(1) 플러그인

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.1.3"
    id("io.spring.dependency-management") version "1.1.3"
    kotlin("jvm") version "1.8.22"
    kotlin("plugin.spring") version "1.8.22" // (1)
    kotlin("plugin.jpa") version "1.8.22" // (2)
}

plugins 부분을 살펴보면 Spring 과 JPA 플러그인이 추가되어 있다.
해당 플러그인들은 Kotlin 프로젝트에서 Spring과 JPA를 보다 편리하게 사용할 수 있도록 도와준다.

  • (1) : Kotlin은 Java와 다르게 클래스와 메서드가 기본적으로 final이다. 따라서 쉽게 수정하거나 확장할 수 없다. 그러므로 해당 플러그인을 추가하면 Spring 어노테이션이 붙은 클래스 및 메서드를 자동으로 열어준다. 예를 들어 CGLIB 프록시에서 요구하는 open 키워드를 추가하지 않고도 @Configuration 또는 @Transactional 빈을 생성 할 수 있게 해준다.
  • (2) : JPA에서 Kotlin의 null을 허용하지 않는 속성을 사용할 수 있도록 해준다. 해당 속성을 사용하려면 @Entity, @MappedSuperclass 또는 @Embeddable로 주석이 달린 모든 클래스에 대해 기본 생성자(NoArgsConstructor)가 필요한데, 이를 자동으로 추가해 준다.

(2) 컴파일러 옵션

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict" // (1)
        jvmTarget = "17"
    }
}

Kotlin의 주요 기능 중 하나는 런타임에 유명한 NullPointerException과 부딪히지 않고 컴파일 시 null 값을 깔끔하게 처리하는 null 안전이다. 이를 통해 무효성 선언을 통해 애플리케이션을 더 안전하게 만들고 Optional과 같은 래퍼 비용을 지불하지 않고도 "값 또는 값 없음" 시맨틱을 표현할 수 있다.

Java는 유형 시스템에서 null 안전성을 표현할 수 없지만, Spring Framework는 org.springframework.lang 패키지에 선언된 툴링 친화적인 어노테이션을 통해 전체 null 안전성을 제공한다. 기본적으로 Kotlin에서 사용되는 Java API의 유형은 null 검사가 완화되는 플랫폼 유형으로 인식된다. JSR 305 어노테이션 + Spring null 가능성 어노테이션에 대한 Kotlin 지원은 Kotlin 개발자에게 전체 Spring 프레임워크 API에 대한 null 안전성을 제공하며, 컴파일 시 null 관련 문제를 처리할 수 있는 이점이 있다.

  • (1) : 이 기능은 strict 옵션과 함께 -Xjsr305 컴파일러 플래그를 추가하여 활성화할 수 있다. 간단히 말해서, 해당 플래그를 활성화하면 Spring 프레임워크 API와 상호 작용하는 Kotlin 코드가 컴파일 시 잠재적인 null 관련 문제를 포착할 수 있다.

(3) 의존성

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-mustache")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin") // (1)
    implementation("org.jetbrains.kotlin:kotlin-reflect") // (2)
    developmentOnly("org.springframework.boot:spring-boot-devtools")
    runtimeOnly("com.h2database:h2")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

프로젝트를 생성하면서 추가했던 의존성 외에도 기본적으로 2개가 추가되어 있는 것을 확인할 수 있다.
Spring Boot 웹 애플리케이션에는 2개의 Kotlin 특정 라이브러리가 필요하며(표준 라이브러리는 Gradle을 통해 자동으로 추가됨), 기본적으로 구성된다.

  • (1) : jackson-module-kotlin -> Kotlin 클래스 및 데이터 클래스의 직렬화/역직렬화 지원
  • (2) : kotlin-reflect -> Kotlin 리플렉션 지원 라이브러리

2. BlogApplication.kt 분석

차이점을 한눈에 볼 수 있도록 Java 기반 애플리케이션 클래스 파일도 가져왔다.

// Java - BlogApplication.java

@SpringBootApplication
public class BlogApplication {

	public static void main(String[] args) {
		SpringApplication.run(BlogApplication.class, args);
	}

}
// Kotlin - BlogApplication.kt

@SpringBootApplication
class BlogApplication // (1)

fun main(args: Array<String>) {
    runApplication<BlogApplication>(*args) // (2)
}

구조가 조금 더 단순하고, 몇 가지 차이점이 존재한다.
장황한 Java의 main 메서드보다 더 단순한 main function이 마음에 든다.

  • (1) : 기본적으로 괄호가 없다. 다만, @Bean 애너테이션을 사용해 Bean을 추가하고자 할 경우에는 괄호를 추가할 수 있다.
  • (2) : SpringApplication.run(BlogApplication::class.java, *args)에 대한 관용적 대안이다. Kotlin은 Java와 다르게 세미콜론이 필요없다.
profile
항상 더 나은 방법을 찾는 백엔드 개발자 은지일입니다 :)

0개의 댓글