Dokka Maven
Dokka Maven (Maven)
Maven 기반 프로젝트에서도 Dokka로 문서를 만들 수 있어요. 이번에는 Maven용 Dokka 플러그인을 어떻게 적용하고, 어떤 설정을 쓸 수 있는지 차근차근 살펴볼게요.
출처: Maven
본문
Maven 기반 프로젝트의 문서를 생성하려면 Dokka용 Maven 플러그인을 사용하면 돼요.
Gradle용 Dokka 플러그인에 비해 Maven 플러그인은 기본 기능만 제공하고, 멀티 모듈 빌드는 지원하지 않아요.
Maven example 프로젝트를 방문하면 Dokka가 Maven 프로젝트에서 어떻게 설정되는지 직접 만져보면서 익힐 수 있어요.
Dokka 적용하기
Dokka를 적용하려면 POM 파일의 plugins 섹션에 dokka-maven-plugin을 추가해야 해요:
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>dokka</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
문서 생성하기
Maven 플러그인이 제공하는 goal은 다음과 같아요:
| Goal | Description |
|---|---|
| dokka:dokka | Dokka 플러그인을 적용해서 문서를 생성해요. 기본적으로 HTML 형식이에요. |
Experimental
| Goal | Description |
|---|---|
| dokka:javadoc | Javadoc 형식으로 문서를 생성해요. |
| dokka:javadocJar | Javadoc 형식의 문서를 담은 javadoc.jar 파일을 생성해요. |
기타 출력 형식 (Other output formats)
기본적으로 Dokka용 Maven 플러그인은 HTML 출력 형식으로 문서를 만들어요.
나머지 출력 형식들은 모두 Dokka 플러그인으로 구현되어 있어요. 원하는 형식으로 문서를 생성하려면 그 형식을 Dokka 플러그인으로 설정에 추가해야 해요.
예를 들어 실험적인 GFM 형식을 쓰려면 gfm-plugin 아티팩트를 추가하면 돼요:
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
...
<configuration>
<dokkaPlugins>
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>gfm-plugin</artifactId>
<version>2.2.0</version>
</plugin>
</dokkaPlugins>
</configuration>
</plugin>
이 설정을 적용하면 dokka:dokka goal을 실행했을 때 GFM 형식으로 문서가 생성돼요.
Dokka 플러그인에 대해 더 알고 싶다면 Dokka plugins 문서를 참고해요.
javadoc.jar 만들기
라이브러리를 저장소에 배포하고 싶다면, 라이브러리의 API 레퍼런스 문서를 담은 javadoc.jar 파일을 제공해야 할 수도 있어요.
예를 들어 Maven Central에 배포하려면 프로젝트와 함께 javadoc.jar를 반드시 제공해야 해요. 다만 모든 저장소에 그런 규칙이 있는 건 아니에요.
Gradle용 Dokka 플러그인과 달리 Maven 플러그인에는 바로 쓸 수 있는 dokka:javadocJar goal이 있어요. 기본적으로 target 폴더에 Javadoc 출력 형식으로 문서를 생성해요.
내장 goal이 마음에 들지 않거나 출력을 커스터마이즈하고 싶다면(예를 들어 Javadoc 대신 HTML 형식으로 생성하고 싶다면) 다음과 같은 설정으로 Maven JAR 플러그인을 추가해서 비슷하게 만들 수 있어요:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
<execution>
<id>dokka-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>dokka</classifier>
<classesDirectory>${project.build.directory}/dokka</classesDirectory>
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</execution>
</executions>
</plugin>
이 설정에서 문서와 그 .jar 아카이브는 dokka:dokka와 jar:jar@dokka-jar goal을 실행해서 생성돼요:
mvn dokka:dokka jar:jar@dokka-jar
라이브러리를 Maven Central에 배포한다면 javadoc.io 같은 서비스를 써서 별다른 설정 없이 라이브러리의 API 문서를 무료로 호스팅할 수도 있어요. 이 서비스는 javadoc.jar에서 바로 문서 페이지를 가져와요. HTML 형식과 잘 맞아서, 이 예시에서 작동하는 모습을 볼 수 있어요.
설정 예시 (Configuration example)
Maven 플러그인의 설정 블록으로 Dokka를 구성할 수 있어요.
문서 출력 위치만 바꾸는 기본 설정 예시를 보여드릴게요:
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
...
<configuration>
<outputDir>${project.basedir}/target/documentation/dokka</outputDir>
</configuration>
</plugin>
설정 옵션 (Configuration options)
Dokka에는 작성자와 독자의 경험을 모두 맞춤 설정할 수 있는 옵션이 아주 많아요.
아래에서 각 설정 섹션의 예시와 상세 설명을 살펴볼게요. 페이지 맨 아래에는 모든 설정 옵션을 적용한 예시도 있으니 참고해요.
일반 설정 (General configuration)
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
<!-- ... -->
<configuration>
<skip>false</skip>
<moduleName>${project.artifactId}</moduleName>
<outputDir>${project.basedir}/target/documentation</outputDir>
<failOnWarning>false</failOnWarning>
<suppressObviousFunctions>true</suppressObviousFunctions>
<suppressInheritedMembers>false</suppressInheritedMembers>
<offlineMode>false</offlineMode>
<sourceDirectories>
<dir>${project.basedir}/src</dir>
</sourceDirectories>
<documentedVisibilities>
<visibility>PUBLIC</visibility>
<visibility>PROTECTED</visibility>
</documentedVisibilities>
<reportUndocumented>false</reportUndocumented>
<skipDeprecated>false</skipDeprecated>
<skipEmptyPackages>true</skipEmptyPackages>
<suppressedFiles>
<file>/path/to/dir</file>
<file>/path/to/file</file>
</suppressedFiles>
<suppressAnnotatedWith>
<annotation>com.example.SuppressMe</annotation>
</suppressAnnotatedWith>
<jdkVersion>8</jdkVersion>
<languageVersion>1.7</languageVersion>
<apiVersion>1.7</apiVersion>
<noStdlibLink>false</noStdlibLink>
<noJdkLink>false</noJdkLink>
<includes>
<include>packages.md</include>
<include>extra.md</include>
</includes>
<classpath>${project.compileClasspathElements}</classpath>
<samples>
<dir>${project.basedir}/samples</dir>
</samples>
<sourceLinks>
<!-- Separate section -->
</sourceLinks>
<externalDocumentationLinks>
<!-- Separate section -->
</externalDocumentationLinks>
<perPackageOptions>
<!-- Separate section -->
</perPackageOptions>
</configuration>
</plugin>
skip
문서 생성 여부를 건너뛸지 결정해요.
기본값: false
moduleName
프로젝트/모듈을 가리킬 때 쓰는 표시 이름이에요. 목차, 내비게이션, 로깅 등에 사용돼요.
기본값: {project.artifactId}
outputDir
형식과 관계없이 문서가 생성되는 디렉토리예요.
기본값: {project.basedir}/target/dokka
failOnWarning
Dokka가 경고나 오류를 내보냈을 때 문서 생성을 실패 처리할지 결정해요. 모든 오류와 경고가 먼저 내보내질 때까지 대기해요.
이 설정은 reportUndocumented와 함께 쓰면 잘 맞아요.
기본값: false
suppressObviousFunctions
자명한 함수(obvious functions)를 숨길지 결정해요.
다음에 해당하는 함수는 자명한 것으로 간주돼요:
kotlin.Any,Kotlin.Enum,java.lang.Object,java.lang.Enum에서 상속된 함수 — 예:equals,hashCode,toString- (컴파일러가 생성한) 합성 함수로 문서가 없는 것 — 예:
dataClass.componentN,dataClass.copy
기본값: true
suppressInheritedMembers
주어진 클래스에서 명시적으로 오버라이드되지 않은 상속 멤버를 숨길지 결정해요.
참고: 이 옵션은 equals/hashCode/toString 같은 함수는 숨길 수 있지만, dataClass.componentN이나 dataClass.copy 같은 합성 함수는 숨길 수 없어요. 그런 경우에는 suppressObviousFunctions를 쓰세요.
기본값: false
offlineMode
원격 파일/링크를 네트워크를 통해 해석할지 결정해요.
여기에는 외부 문서 링크를 생성할 때 쓰는 package-list도 포함돼요. 예를 들어 표준 라이브러리의 클래스를 클릭 가능하게 만들 때죠.
이 값을 true로 두면 특정 상황에서 빌드 시간을 크게 줄일 수 있어요. 다만 표준 라이브러리를 포함한 의존성의 클래스/멤버 링크를 해석하지 않아서 문서 품질과 사용자 경험이 떨어질 수 있어요.
참고: 가져온 파일을 로컬에 캐시하고 Dokka에 로컬 경로로 제공할 수도 있어요. externalDocumentationLinks 섹션을 확인해 보세요.
기본값: false
sourceDirectories
분석하고 문서화할 소스 코드 루트예요. 디렉토리와 개별 .kt/.java 파일을 받아요.
기본값: {project.compileSourceRoots}
documentedVisibilities
문서화할 가시성(visibility) 수정자 집합이에요.
protected/internal/private 선언을 문서화하고 싶을 때, 또는 public 선언은 제외하고 내부 API만 문서화하고 싶을 때 사용할 수 있어요.
패키지 단위로도 설정할 수 있어요.
기본값: PUBLIC
reportUndocumented
documentedVisibilities와 다른 필터를 적용한 뒤에도 남는, 문서가 없는 보이는 선언(KDoc이 없는 선언)에 대해 경고를 낼지 결정해요.
이 설정은 failOnWarning과 함께 쓰면 잘 맞아요.
패키지 수준에서 오버라이드할 수 있어요.
기본값: false
skipDeprecated
@Deprecated로 어노테이션된 선언을 문서화할지 결정해요.
패키지 수준에서 오버라이드할 수 있어요.
기본값: false
skipEmptyPackages
여러 필터를 적용한 뒤에도 보이는 선언이 하나도 없는 패키지를 건너뛸지 결정해요.
예를 들어 skipDeprecated를 true로 두고 패키지에 deprecated 선언만 있다면, 그 패키지는 비어 있는 것으로 간주돼요.
기본값: true
suppressedFiles
숨길 디렉토리나 개별 파일이에요. 여기에 속한 선언은 문서화되지 않아요.
suppressAnnotatedWith
어노테이션으로 선언을 숨길 때 쓰는, 완전히 정규화된 이름(FQN) 목록이에요.
이 어노테이션 중 하나로 어노테이션된 선언은 생성된 문서에서 제외돼요.
jdkVersion
Java 타입의 외부 문서 링크를 생성할 때 사용할 JDK 버전이에요.
예를 들어 어떤 public 선언 시그니처에서 java.util.UUID를 쓴다면, 이 옵션이 8로 설정되어 있을 때 Dokka는 그 타입에 대한 JDK 8 Javadocs의 외부 문서 링크를 생성해요.
기본값: JDK 8
languageVersion
분석과 @sample 환경을 구성할 때 쓰는 Kotlin 언어 버전이에요.
기본적으로 Dokka에 내장된 컴파일러가 사용할 수 있는 가장 최신 언어 버전이 사용돼요.
apiVersion
분석과 @sample 환경을 구성할 때 쓰는 Kotlin API 버전이에요.
기본적으로 languageVersion에서 유도돼요.
noStdlibLink
Kotlin 표준 라이브러리의 API 레퍼런스 문서로 연결되는 외부 문서 링크를 생성할지 결정해요.
참고: noStdLibLink가 false로 설정되어 있을 때 링크가 생성돼요.
기본값: false
noJdkLink
JDK의 Javadocs로 연결되는 외부 문서 링크를 생성할지 결정해요.
JDK Javadocs의 버전은 jdkVersion 옵션으로 정해져요.
참고: noJdkLink가 false로 설정되어 있을 때 링크가 생성돼요.
기본값: false
includes
모듈 및 패키지 문서를 담고 있는 Markdown 파일 목록이에요.
지정한 파일의 내용은 모듈 및 패키지 설명으로 파싱되어 문서에 포함돼요.
classpath
분석과 인터랙티브 샘플에 쓰는 클래스패스예요.
의존성에서 오는 일부 타입이 자동으로 해석되지 않을 때 유용해요. .jar와 .klib 파일을 모두 받아요.
기본값: {project.compileClasspathElements}
samples
@sample KDoc 태그로 참조되는 샘플 함수를 담고 있는 디렉토리나 파일 목록이에요.
소스 링크 설정 (Source link configuration)
sourceLinks 설정 블록으로 각 시그니처에 url로 연결되는 source 링크를 특정 줄 번호와 함께 추가할 수 있어요. (줄 번호는 lineSuffix로 설정 가능해요.)
이 기능은 독자가 각 선언의 소스 코드를 찾는 데 도움을 줘요.
예시는 kotlinx.coroutines에 있는 count() 함수의 문서에서 볼 수 있어요.
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
<!-- ... -->
<configuration>
<sourceLinks>
<link>
<path>src</path>
<url>https://github.com/kotlin/dokka/tree/master/src</url>
<lineSuffix>#L</lineSuffix>
</link>
</sourceLinks>
</configuration>
</plugin>
path
로컬 소스 디렉토리의 경로예요. 현재 모듈의 루트 기준 상대 경로여야 해요.
참고: Unix 형식의 경로만 허용돼요. Windows 스타일 경로는 오류를 발생시켜요.
url
문서 독자가 접근할 수 있는 소스 코드 호스팅 서비스의 URL이에요 (GitHub, GitLab, Bitbucket 등). 이 URL은 선언의 소스 코드 링크를 생성하는 데 사용돼요.
lineSuffix
URL에 소스 코드 줄 번호를 덧붙일 때 쓰는 접미사예요. 독자가 파일뿐 아니라 선언이 있는 특정 줄로 이동할 수 있게 도와줘요.
번호 자체는 지정한 접미사 뒤에 붙어요. 예를 들어 이 옵션이 #L이고 줄 번호가 10이라면, 결과 URL 접미사는 #L10이 돼요.
주요 서비스들이 쓰는 접미사:
- GitHub:
#L - GitLab:
#L - Bitbucket:
#lines-
외부 문서 링크 설정 (External documentation links configuration)
externalDocumentationLinks 블록으로 의존성의 외부 호스팅 문서로 연결되는 링크를 만들 수 있어요.
예를 들어 kotlinx.serialization의 타입을 쓰고 있다면, 기본적으로 그 타입은 문서에서 해석되지 않은 것처럼 클릭할 수 없어요. 하지만 kotlinx.serialization의 API 레퍼런스 문서가 Dokka로 만들어져 kotlinlang.org에 게시되어 있으므로, 외부 문서 링크를 설정할 수 있어요. 그러면 라이브러리 타입에 대한 링크를 Dokka가 생성해서 클릭 가능하게 해결해 줘요.
기본적으로 Kotlin 표준 라이브러리와 JDK에 대한 외부 문서 링크는 이미 설정되어 있어요.
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
<!-- ... -->
<configuration>
<externalDocumentationLinks>
<link>
<url>https://kotlinlang.org/api/kotlinx.serialization/</url>
<packageListUrl>file:/${project.basedir}/serialization.package.list</packageListUrl>
</link>
</externalDocumentationLinks>
</configuration>
</plugin>
url
링크할 문서의 루트 URL이에요. 끝에 슬래시가 있어야 해요.
Dokka는 주어진 URL에 대한 package-list를 자동으로 찾아서 선언들을 서로 연결하려고 최선을 다해요.
자동 해석이 실패하거나 로컬 캐시 파일을 쓰고 싶다면 packageListUrl 옵션을 설정하는 걸 고려해 보세요.
packageListUrl
package-list의 정확한 위치예요. Dokka가 자동으로 해석하도록 두는 대신 직접 지정하는 방법이에요.
패키지 목록에는 문서와 프로젝트 자체에 대한 정보(모듈 이름, 패키지 이름 등)가 담겨 있어요.
네트워크 호출을 피하려고 로컬 캐시 파일로 지정할 수도 있어요.
패키지 옵션 (Package options)
perPackageOptions 설정 블록으로 matchingRegex와 일치하는 특정 패키지에 대한 옵션을 설정할 수 있어요.
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
<!-- ... -->
<configuration>
<perPackageOptions>
<packageOptions>
<matchingRegex>.*api.*</matchingRegex>
<suppress>false</suppress>
<reportUndocumented>false</reportUndocumented>
<skipDeprecated>false</skipDeprecated>
<documentedVisibilities>
<visibility>PUBLIC</visibility>
<visibility>PRIVATE</visibility>
<visibility>PROTECTED</visibility>
<visibility>INTERNAL</visibility>
<visibility>PACKAGE</visibility>
</documentedVisibilities>
</packageOptions>
</perPackageOptions>
</configuration>
</plugin>
matchingRegex
패키지를 매칭할 때 쓰는 정규 표현식이에요.
기본값: .*
suppress
문서를 생성할 때 이 패키지를 건너뛸지 결정해요.
기본값: false
documentedVisibilities
문서화할 가시성 수정자 집합이에요.
이 패키지 안의 protected/internal/private 선언을 문서화하고 싶을 때, 또는 public 선언은 제외하고 내부 API만 문서화하고 싶을 때 사용할 수 있어요.
기본값: PUBLIC
skipDeprecated
@Deprecated로 어노테이션된 선언을 문서화할지 결정해요.
프로젝트/모듈 수준에서도 설정할 수 있어요.
기본값: false
reportUndocumented
documentedVisibilities와 다른 필터를 적용한 뒤에도 남는, 문서가 없는 보이는 선언(KDoc이 없는 선언)에 대해 경고를 낼지 결정해요.
이 설정은 failOnWarning과 함께 쓰면 잘 맞아요.
기본값: false
전체 설정 (Complete configuration)
아래에서 가능한 모든 설정 옵션을 동시에 적용한 모습을 볼 수 있어요.
<plugin>
<groupId>org.jetbrains.dokka</groupId>
<artifactId>dokka-maven-plugin</artifactId>
<!-- ... -->
<configuration>
<skip>false</skip>
<moduleName>${project.artifactId}</moduleName>
<outputDir>${project.basedir}/target/documentation</outputDir>
<failOnWarning>false</failOnWarning>
<suppressObviousFunctions>true</suppressObviousFunctions>
<suppressInheritedMembers>false</suppressInheritedMembers>
<offlineMode>false</offlineMode>
<sourceDirectories>
<dir>${project.basedir}/src</dir>
</sourceDirectories>
<documentedVisibilities>
<visibility>PUBLIC</visibility>
<visibility>PRIVATE</visibility>
<visibility>PROTECTED</visibility>
<visibility>INTERNAL</visibility>
<visibility>PACKAGE</visibility>
</documentedVisibilities>
<reportUndocumented>false</reportUndocumented>
<skipDeprecated>false</skipDeprecated>
<skipEmptyPackages>true</skipEmptyPackages>
<suppressedFiles>
<file>/path/to/dir</file>
<file>/path/to/file</file>
</suppressedFiles>
<jdkVersion>8</jdkVersion>
<languageVersion>1.7</languageVersion>
<apiVersion>1.7</apiVersion>
<noStdlibLink>false</noStdlibLink>
<noJdkLink>false</noJdkLink>
<includes>
<include>packages.md</include>
<include>extra.md</include>
</includes>
<classpath>${project.compileClasspathElements}</classpath>
<samples>
<dir>${project.basedir}/samples</dir>
</samples>
<sourceLinks>
<link>
<path>src</path>
<url>https://github.com/kotlin/dokka/tree/master/src</url>
<lineSuffix>#L</lineSuffix>
</link>
</sourceLinks>
<externalDocumentationLinks>
<link>
<url>https://kotlinlang.org/api/core/kotlin-stdlib/</url>
<packageListUrl>file:/${project.basedir}/stdlib.package.list</packageListUrl>
</link>
</externalDocumentationLinks>
<perPackageOptions>
<packageOptions>
<matchingRegex>.*api.*</matchingRegex>
<suppress>false</suppress>
<reportUndocumented>false</reportUndocumented>
<skipDeprecated>false</skipDeprecated>
<documentedVisibilities>
<visibility>PUBLIC</visibility>
<visibility>PRIVATE</visibility>
<visibility>PROTECTED</visibility>
<visibility>INTERNAL</visibility>
<visibility>PACKAGE</visibility>
</documentedVisibilities>
</packageOptions>
</perPackageOptions>
</configuration>
</plugin>
더 알아보기
- Dokka를 Javadoc 형식으로 쓰는 방법은 Dokka Javadoc 문서를 참고해요.
- 플러그인으로 Dokka를 확장하는 법은 Dokka plugins에서 배워요.