Problem
레이어드아키텍처 나 헥사고날아키텍처.. 등등 에서 모듈을 나누는 경우가 많다.
모듈을 분리 하는 이유는
재사용성 , 계층간 관심사 분리 , 추상화 등이 있다.
무엇보다 이번에 계획하게 된 이유는
컨트롤러를 코틀린으로 작성하고 JPA를 직접적으로 사용하는 Service계층은 자바로 작
성하고 싶었다.
코틀린은 Null에 대한 안정성과 자바코드보다 훨신 더 간결함을 가지고 있는 언어이다.
위 장점은 요청을 받는 Controller 단에 최적의 언어라고 생각했다.
하지만 코틀린은 아직 Jpa 와 100프로는 어울리지 않는 언어라고 한다.
https://tech.inflab.com/20240110-java-and-kotlin/
Spring Boot & JPA에서 Java와 Kotlin을 함께 사용하기
Spring Boot & JPA 환경에서 Java와 Kotlin을 함께 사용한 이유와 사용 예제를 소개합니다.
tech.inflab.com
Solution
Presentation 모듈 : Controller
Domain 모듈 : Service
Support 모듈 : 로깅 , 배치 , AOP 등등...
코틀린과 자바를 상용운용 하기위해서는 코틀린에서 지원하지 않는 Lombok 이나 java annotation에도 주의를 기울여야 한다.
https://d2.naver.com/helloworld/6685007#ch1
루트프로젝트(최상위디렉토리) 아래 하위 모듈들을 생성해준다.
모듈을 생성하는 방법은 2가지가 있다
- Module을 바로 생성하기
- 디렉토리를 생성해 모듈로 만들기
아래 그림을 보면 takeItEasy 모듈을 그대로 설정하면 첫번째 그림처럼 나오고
디렉토리를 생성해서 모듈로 만들어주면 한개로 나온다.
이건 필자가 혼자 공부하기 때문에 아직 해결하지 못한과제로 ... 남아있다.
이 밖에도 무수한 에러들을 만났어서 해결에 집중하느라 다음에 해보도록 하겠다..
Step 1
디렉토리를 만들어서 하위에 src 디렉토리와 build.gradle 파일을 만들어준다.
src디렉토리는 그 전에 프로젝트 생성하는 것 처럼 만들어주면 된다.
Step 2
최 상위 디렉토리에 있는 Setting.gradle 파일에 만들어준 모듈들을 연결시켜준다.
//root - setting.gradle.kts
rootProject.name = "takeItEasy-postApi"
//include 안에 모듈명(디렉토리명)을 넣어주면 된다.
include("takeItEasy-support","takeItEasy-domain","takeItEasy-presentation")
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
}
setting.gradle 파일은 최상위 1개만 존재하고 다른 모듈에는 없어야 한다.
//root - build.gradle.kts
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
id("org.springframework.boot") version "3.1.0" apply false
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.8.21"
kotlin("plugin.spring") version "1.8.21" apply false
}
allprojects {
group = "com.sudoSoo"
version = "0.0.1-SNAPSHOT"
repositories {
mavenCentral()
mavenLocal()
maven ("https://repo.spring.io/release")
maven ("https://repo.spring.io/milestone/")
maven ("https:/jitpack.io")
}
}
java {
sourceCompatibility = JavaVersion.VERSION_17
}
subprojects {
apply(plugin = "org.springframework.boot")
apply(plugin = "io.spring.dependency-management")
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:3.0.4")
mavenBom("com.google.guava:guava-bom:31.1-jre")
mavenBom("org.jetbrains.kotlin:kotlin-bom:1.7.22")
}
}
tasks.register("prepareKotlinBuildScriptModel"){}
configurations.all {
exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
}
//자바 모듈
if (name == "domain") {
apply(plugin = "java")
java {
sourceCompatibility = JavaVersion.VERSION_17
}
//코틀린 모듈
}else{
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "org.jetbrains.kotlin.plugin.spring")
dependencies {
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
tasks{
compileKotlin {
kotlinOptions.jvmTarget = "17"
kotlinOptions.freeCompilerArgs = listOf(
"-Xopt-in=kotlin.RequiresOptIn",
"-XXLanguage:+InlineClasses"
)
}
compileTestKotlin {
kotlinOptions.jvmTarget = "17"
}
}
}
tasks {
val bootJar: BootJar by getting(org.springframework.boot.gradle.tasks.bundling.BootJar::class)
{
enabled = false
}
val jar by getting(Jar::class) {
enabled = true
}
}
dependencies {
implementation("org.springframework.boot:spring-boot-devtools")
implementation("org.springframework.boot:spring-boot-starter-jdbc")
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<Test> {
useJUnitPlatform()
}
}
- allprojects 모든 프로젝트에 공통으로 넣어야 할 설정을 넣어준다.
- subprojects 하위 모듈들에게 공통으로 들어가야 할 설정들을 넣어준다.
//presentation - build.gradle.kts
dependencies {
implementation(project(":takeItEasy-domain"))
implementation("org.springframework.boot:spring-boot-starter-web")
}
presentation -> domain 의존성을 주입해준다.
support 도 마찬가지로 넣어준다.
build.gradle.kts 은 각 모듈에 필요한 라이브러리들을 넣어준다.
step 3
각 모듈의 src 안에 main 디렉토리를 완성시켜준다.
주의할점
위에서 써놓은것과 같이 kotlin 에서는 lombok 호환이 안되어서 deLombok을 해주어야 한다.
queryDSL 설정도 Jpa설정도 유의해서 사용 해야 한다
느낀점
각 라이브러리버전 호환성이 너무 어려웠다.
파일 구조가 어떻게 되어있는지 몰라서 여러 레퍼런스들을 종합적으로 찾아보면서 정리해보았다.
어디까지나 독학이므로 정답은 아니다
참고 자료
https://tech.inflab.com/20240110-java-and-kotlin/
https://d2.naver.com/helloworld/6685007#ch1
https://tech.inflab.com/20240110-java-and-kotlin/
https://www.youtube.com/watch?v=rE89ppAmf_Y
'개-발 > Java + Spring + Kotlin' 카테고리의 다른 글
[Spring Batch] 스프링 배치 개념 (0) | 2024.03.27 |
---|---|
[Kotlin] build.gradle 환경변수 적용 (0) | 2024.03.18 |
[Java] CQRS 패턴 적용기 (Feat.Redis) (0) | 2024.03.07 |
[Kotlin] 단위 테스트 작성하기 (feat.JUnit5 , MockK) (0) | 2024.02.21 |
[Spring Batch] addBatch로 다량 쿼리문 한번에 실행 (bulk insert) (0) | 2024.01.17 |