All-open 컴파일러 플러그인

All-open 컴파일러 플러그인

Kotlin에서는 클래스와 그 멤버가 기본적으로 final이에요. 그런데 Spring AOP처럼 클래스가 open이어야 돌아가는 프레임워크나 라이브러리도 있죠. all-open 컴파일러 플러그인은 Kotlin을 그런 프레임워크의 요구에 맞춰주는 역할을 해요. 특정 애너테이션이 붙은 클래스와 그 멤버를, 명시적으로 open 키워드를 쓰지 않아도 open으로 만들어주는 거예요.

출처: All-open compiler plugin

본문

예를 들어 Spring을 쓸 때를 생각해 볼게요. 모든 클래스를 open으로 만들 필요는 없고, @Configuration이나 @Service처럼 특정 애너테이션이 붙은 클래스만 open이면 충분해요. all-open 플러그인이 바로 그런 애너테이션을 직접 지정할 수 있게 해 줘요.

Kotlin은 all-open 플러그인을 Gradle과 Maven 양쪽 모두에서 지원하고, IDE 통합도 완전하게 되어 있어요.

참고: Spring을 쓴다면 kotlin-spring 컴파일러 플러그인을 사용할 수 있어요.

Gradle

build.gradle(.kts) 파일에 플러그인을 추가해요:

plugins {
    kotlin("plugin.allopen") version "2.4.20"
}
plugins {
    id "org.jetbrains.kotlin.plugin.allopen" version "2.4.20"
}

그 다음에는 클래스를 open으로 만들 애너테이션 목록을 지정해요:

allOpen {
    annotation("com.my.Annotation")
    // annotations("com.another.Annotation", "com.third.Annotation")
}
allOpen {
    annotation("com.my.Annotation")
    // annotations("com.another.Annotation", "com.third.Annotation")
}

클래스(또는 그 슈퍼클래스 중 하나)에 com.my.Annotation이 붙어 있으면, 그 클래스 자신과 모든 멤버가 open이 돼요.

메타 애너테이션(meta-annotation)으로도 동작해요:

@com.my.Annotation
annotation class MyFrameworkAnnotation

@MyFrameworkAnnotation
class MyClass // will be all-open

MyFrameworkAnnotation은 all-open 메타 애너테이션인 com.my.Annotation으로 애너테이션되어 있으니, 이것 역시 all-open 애너테이션이 돼요.

Maven

pom.xml 파일에 플러그인을 추가해요:

<plugin>
    <artifactId>kotlin-maven-plugin</artifactId>
    <groupId>org.jetbrains.kotlin</groupId>
    <version>${kotlin.version}</version>

    <configuration>
        <compilerPlugins>
            <!-- Or "spring" for the Spring support -->
            <plugin>all-open</plugin>
        </compilerPlugins>

        <pluginOptions>
            <!-- Each annotation is placed on its own line -->
            <option>all-open:annotation=com.my.Annotation</option>
            <option>all-open:annotation=com.their.AnotherAnnotation</option>
        </pluginOptions>
    </configuration>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-allopen</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
    </dependencies>
</plugin>

all-open 애너테이션이 어떻게 동작하는지 자세한 내용은 Gradle 섹션을 참고해 주세요.

Spring 지원

Spring을 쓴다면 Spring 애너테이션을 일일이 지정하는 대신 kotlin-spring 컴파일러 플러그인을 켤 수 있어요. kotlin-springall-open을 감싸는 래퍼로, 동작 방식은 똑같아요.

build.gradle(.kts) 파일에 spring 플러그인을 추가해요:

plugins {
    id("org.jetbrains.kotlin.plugin.spring") version "2.4.20"
}
plugins {
    id "org.jetbrains.kotlin.plugin.spring" version "2.4.20"
}

Maven에서는 spring 플러그인이 kotlin-maven-allopen 플러그인 의존성으로 제공돼요. 그래서 pom.xml에서 이렇게 켜면 돼요:

<plugin>
    <artifactId>kotlin-maven-plugin</artifactId>
    <groupId>org.jetbrains.kotlin</groupId>
    <version>${kotlin.version}</version>

    <configuration>
        <compilerPlugins>
            <plugin>spring</plugin>
        </compilerPlugins>
    </configuration>

    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-allopen</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
    </dependencies>
</plugin>

이 플러그인은 다음 애너테이션들을 지정해요:

  • @Component
  • @Async
  • @Transactional
  • @Cacheable
  • @SpringBootTest

Maven에서는 spring 플러그인이 kotlin-maven-allopen 플러그인 의존성으로 제공돼요. pom.xml에서 spring을 컴파일러 플러그인으로 지정하면 돼요:

<compilerPlugins>
    <plugin>spring</plugin>
</compilerPlugins>

<dependencies>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-maven-allopen</artifactId>
        <version>${kotlin.version}</version>
    </dependency>
</dependencies>

메타 애너테이션 지원 덕분에, @Component로 메타 애너테이션된 @Configuration, @Controller, @RestController, @Service, @Repository가 붙은 클래스들은 자동으로 open돼요.

물론 같은 프로젝트에서 kotlin-allopenkotlin-spring을 함께 쓸 수도 있어요.

참고: start.spring.io 서비스로 프로젝트 템플릿을 생성하면 kotlin-spring 플러그인이 기본으로 켜져 있어요.

커맨드라인 컴파일러

All-open 컴파일러 플러그인 JAR은 Kotlin 컴파일러의 바이너리 배포판에 들어 있어요. -Xplugin kotlinc 옵션에 그 JAR 파일 경로를 지정하면 플러그인을 연결할 수 있어요:

-Xplugin=$KOTLIN_HOME/lib/allopen-compiler-plugin.jar

annotation 플러그인 옵션으로 all-open 애너테이션을 직접 지정하거나, preset을 켤 수도 있어요:

# The plugin option format is: "-P plugin:<plugin id>:<key>=<value>". 
# Options can be repeated.

-P plugin:org.jetbrains.kotlin.allopen:annotation=com.my.Annotation
-P plugin:org.jetbrains.kotlin.allopen:preset=spring

all-open 플러그인에 쓸 수 있는 preset은 spring, micronaut, quarkus예요.

더 알아보기