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