Info

Repository

Environment

  • kotlin
  • java 17
  • spring-boot v3.3.2
  • gradle
  • cache
    • redis
  • logging
    • log4j
  • database
    • mysql
    • h2 (in Local)
    • jpa
    • querydsl
  • security
    • spring-security
    • validation
  • test
    • junit5
    • restdocs-mockmvc
    • mockk
  • object
    • mapstruct
    • kassava

Package

build.gradle.kts
plugins {  
    id("org.springframework.boot") version "3.3.2"  
    id("io.spring.dependency-management") version "1.1.6"  
    kotlin("jvm") version "1.9.24"  
    kotlin("plugin.spring") version "1.9.24"  
    kotlin("plugin.jpa") version "1.9.20"  
    kotlin("kapt") version "1.7.10"  
    id("org.asciidoctor.jvm.convert") version "3.3.2"  
    idea  
    jacoco}  
  
group = "com.example"  
version = "0.0.1-SNAPSHOT"  
  
java {  
    toolchain {  
        languageVersion = JavaLanguageVersion.of(17)  
    }  
}  
  
repositories {  
    mavenCentral()  
    maven("https://jitpack.io")  
}  
  
dependencies {  
    // DEFAULT  
    implementation("org.springframework.boot:spring-boot-starter-web:3.1.0")  
    implementation("org.springframework.boot:spring-boot-starter")  
    implementation("org.jetbrains.kotlin:kotlin-reflect")  
  
    // CACHING  
    implementation("org.springframework.boot:spring-boot-starter-data-redis")  
  
    // LOGGING  
    implementation("org.springframework.boot:spring-boot-starter-log4j2:3.0.4")  
  
    // JPA  
    implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.0.4")  
  
    // QUERY_DSL  
    implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta")  
    kapt("com.querydsl:querydsl-apt:5.0.0:jakarta")  
    kapt("jakarta.annotation:jakarta.annotation-api")  
    kapt("jakarta.persistence:jakarta.persistence-api")  
  
    // DATABASE  
    runtimeOnly("com.mysql:mysql-connector-j:8.0.32")  
    runtimeOnly("com.h2database:h2")  
  
    // SECURITY  
    implementation("org.springframework.boot:spring-boot-starter-security:3.0.4")  
    implementation("org.springframework.security:spring-security-jwt:1.1.1.RELEASE")  
    implementation("com.sun.xml.bind:jaxb-impl:4.0.1")  
    implementation("com.sun.xml.bind:jaxb-core:4.0.1")  
    implementation("javax.xml.bind:jaxb-api:2.4.0-b180830.0359")  
    implementation("io.jsonwebtoken:jjwt:0.9.1")  
    testImplementation("org.springframework.security:spring-security-test:6.0.2")  
  
    // VALIDATING  
    implementation("org.springframework.boot:spring-boot-starter-validation:3.0.4")  
  
    // JSON PARSING  
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")  
    implementation("com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.13.3")  
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")  
    implementation("org.glassfish.jaxb:jaxb-runtime:2.3.2")  
  
    // TEST  
    testImplementation("org.springframework.boot:spring-boot-starter-test")  
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")  
    testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")  
    testImplementation("io.mockk:mockk:1.9.3")  
    testImplementation("io.kotest:kotest-runner-junit5-jvm:4.6.0")  
  
    // MAPPING  
    implementation("org.mapstruct:mapstruct:1.5.3.Final")  
    kapt("org.mapstruct:mapstruct-processor:1.5.3.Final")  
    kaptTest("org.mapstruct:mapstruct-processor:1.5.3.Final")  
  
    // CUSTOM toString & equals & hashCode  
    implementation("com.github.consoleau:kassava:2.1.0")  
  
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")  
}  
  
configurations.forEach {  
    it.exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")  
    it.exclude(group = "org.apache.logging.log4j", module = "log4j-to-slf4j")  
}  
  
kotlin {  
    compilerOptions {  
        freeCompilerArgs.addAll("-Xjsr305=strict")  
    }  
}  
  
kotlin.sourceSets.main {  
    setBuildDir("$buildDir")  
}  
  
idea {  
    module {  
        val kaptMain = file("build/generated/source/kapt/main")  
        sourceDirs.add(kaptMain)  
        generatedSourceDirs.add(kaptMain)  
    }  
}  
  
allOpen {  
    annotation("jakarta.persistence.Entity")  
    annotation("jakarta.persistence.Embeddable")  
    annotation("jakarta.persistence.MappedSuperclass")  
}  
  
tasks.withType<Test>().configureEach {  
    useJUnitPlatform()  
}  
  
tasks.register<Test>("jacocoTest") {  
    group = "verification"  
    description = "only jacoco tests"  
    testClassesDirs = sourceSets["test"].output.classesDirs  
    classpath = sourceSets["test"].runtimeClasspath  
    include("**/coverage/**")  
}  
  
tasks.register<Test>("restDocsTest") {  
    group = "verification"  
    description = "Run tests for the restDocs directory"  
    testClassesDirs = sourceSets["test"].output.classesDirs  
    classpath = sourceSets["test"].runtimeClasspath  
    include("**/com/example/kotlinapiserverguide/restDocs/docs/**")  
    useJUnitPlatform()  
    testLogging {  
        events("passed", "skipped", "failed")  
        showStandardStreams = true  
    }  
}  
  
tasks {  
    test {  
        finalizedBy(jacocoTestReport)  
    }  
  
    jacocoTestReport {  
        dependsOn("jacocoTest")  
        executionData(fileTree(buildDir).include("jacoco/*.exec"))  
        reports {  
            html.required = true  
            xml.required = false  
            csv.required = false  
            classDirectories.setFrom(  
                sourceSets.main.get().output.asFileTree.matching {  
                    exclude("**/dto/*", "**/entity/*", "**/common/filter/*")  
                }  
            )  
        }  
    }  
    val snippetsDir by extra { file("build/generated-snippets") }  
  
    val generateDocs by registering {  
        group = "documentation"  
        dependsOn("restDocsTest")  
        finalizedBy(asciidoctor)  
    }  
  
    asciidoctor {  
        outputs.dir(snippetsDir)  
        doFirst {  
            delete(file("src/main/resources/static/docs"))  
        }  
        inputs.dir(snippetsDir)  
        doLast {  
            copy {  
                from("build/docs/asciidoc")  
                into("src/main/resources/static/docs")  
            }  
        }    }  
    build {  
        dependsOn(asciidoctor)  
    }  
  
    bootJar {  
        dependsOn(asciidoctor)  
    }  
}  
  
gradle.startParameter.isParallelProjectExecutionEnabled = true

Directory Structure

  • docs - asciidoc κ²°κ³Όλ¬Ό (build μ‹œμ—λ§Œ μ‚¬μš©ν•˜κ³  μ‚¬μš©λ˜μ§€ μ•ŠμŒ.)
  • main
    • kotlin
      • api - 각 λ„λ©”μΈλ³„λ‘œ λΆ„λ₯˜
      • common - 도메인과 λ¬΄κ΄€ν•œ μ„€μ • λͺ¨μŒ
        • application - μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ„€μ •
        • cache - μΌ€μ‹œ 관리 (redis)
        • encrypt - μ•”λ³΅ν˜Έν™” 관리
        • exception - μ—λŸ¬ 관리
        • filter - ν•„ν„° 관리 (ν˜„μž¬λŠ” logging만 처리)
        • function - κ³΅ν†΅μœΌλ‘œ μ‚¬μš©ν•˜λŠ” top level function μ •μ˜
        • http - μš”μ²­ 응닡 객체 관리
        • interface - 곡톡 μΈν„°νŽ˜μ΄μŠ€ 관리
        • jpa - jpa κ΄€λ ¨ μ„€μ • 관리
        • paging - νŽ˜μ΄μ§• 객체 관리
        • security - λ³΄μ•ˆ 관리
        • util - 곡톡 function λ˜λŠ” Bean 관리
    • resources
      • sql - DB 관리 (h2 μ‚¬μš© 및 νžˆμŠ€ν† λ¦¬ 관리 μš©λ„)
      • static - docs html λ³€ν™˜ κ²°κ³Όλ¬Ό μ €μž₯
      • application.yaml - μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ 곡톡 μ„€μ •
      • application-{profile}.yaml - ν”„λ‘œνŒŒμΌμ— ν•΄λ‹Ήν•˜λŠ” μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ„€μ •
      • log4j2.xml - 둜그 μ„€μ •
  • test - ν…ŒμŠ€νŠΈ λͺ¨μŒ
    • restDocs - rest api document 생성 Test λͺ¨μŒ.
    • serviceTest - coverage Test λͺ¨μŒ.

Tree

directories
.
β”œβ”€β”€ docs
β”‚Β Β  └── asciidoc
β”œβ”€β”€ main
β”‚Β Β  β”œβ”€β”€ kotlin
β”‚Β Β  β”‚Β Β  └── com
β”‚Β Β  β”‚Β Β      └── example
β”‚Β Β  β”‚Β Β          └── kotlinapiserverguide
β”‚Β Β  β”‚Β Β              β”œβ”€β”€ api
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”œβ”€β”€ member
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ controller
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ domain
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ dto
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ entity
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  β”‚Β Β  └── mapper
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  β”œβ”€β”€ repository
β”‚Β Β  β”‚Β Β              β”‚Β Β  β”‚Β Β  └── service
β”‚Β Β  β”‚Β Β              β”‚Β Β  └── user
β”‚Β Β  β”‚Β Β              β”‚Β Β      β”œβ”€β”€ controller
β”‚Β Β  β”‚Β Β              β”‚Β Β      β”œβ”€β”€ domain
β”‚Β Β  β”‚Β Β              β”‚Β Β      β”‚Β Β  β”œβ”€β”€ dto
β”‚Β Β  β”‚Β Β              β”‚Β Β      β”‚Β Β  └── mapper
β”‚Β Β  β”‚Β Β              β”‚Β Β      └── service
β”‚Β Β  β”‚Β Β              └── common
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ application
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ cache
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ encrypt
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── annotation
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ exception
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── controller
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ filter
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── domain
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ function
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ http
β”‚Β Β  β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ constant
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── domain
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ interfaces
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ jpa
β”‚Β Β  β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ entity
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── querydsl
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ paging
β”‚Β Β  β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ annotation
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── dto
β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ security
β”‚Β Β  β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ config
β”‚Β Β  β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ constant
β”‚Β Β  β”‚Β Β                  β”‚Β Β  └── provider
β”‚Β Β  β”‚Β Β                  └── util
β”‚Β Β  └── resources
β”‚Β Β      β”œβ”€β”€ sql
β”‚Β Β      └── static
β”‚Β Β          └── docs
└── test
    β”œβ”€β”€ kotlin
    β”‚Β Β  └── com
    β”‚Β Β      └── example
    β”‚Β Β          └── kotlinapiserverguide
    β”‚Β Β              β”œβ”€β”€ restDocs
    β”‚Β Β              β”‚Β Β  β”œβ”€β”€ constant
    β”‚Β Β              β”‚Β Β  β”‚Β Β  └── parser
    β”‚Β Β              β”‚Β Β  β”œβ”€β”€ docs
    β”‚Β Β              β”‚Β Β  β”‚Β Β  └── base
    β”‚Β Β              β”‚Β Β  β”œβ”€β”€ infix
    β”‚Β Β              β”‚Β Β  └── util
    β”‚Β Β              └── serviceTest
    β”‚Β Β                  β”œβ”€β”€ member
    β”‚Β Β                  β”‚Β Β  └── coverage
    β”‚Β Β                  β”‚Β Β      └── memberService
    β”‚Β Β                  └── user
    β”‚Β Β                      └── coverage
    β”‚Β Β                          └── userService
    └── resources
        └── org
            └── springframework
                └── restdocs
                    └── templates

Trees

3🌳

more