jOOQ 사용해보기
jOOQ 사용해보기

jOOQ 사용해보기

Tags
SpringWebflux
jOOQ
Gradle
buildSrc
Published
November 8, 2025
Author
lkdcode
SpringWebFlux 기반의 프로젝트에서 Query 빌더 도구로 SpringDataJpa 는 블로킹방식이라 부적합하다.
복잡한 쿼리를 안전하게 작성할 수 있고 R2DBC 를 지원하는 라이브러리 중 jOOQ 채택했다.
(jOOQ 의 철학도 마음에 든다.)
 
notion image
 
  1. Database First
ORM 이 데이터베이스 구조를 다루지 않게 한다. 이는 데이터베이스가 더 우선이며 단일 진실 공급원(Single Source of Truth) 철학을 지키고 있다.
 
  1. Typesafe SQL
SQL 을 jOOQ 만의 DSL 로 풀어낸다. QueryDSL 을 사용했다면 익숙한 문법이고 SQL 만 알아도 누구나 쉽게 작성할 수 있는 DSL 을 제공한다.
 
notion image
 
다양한 모델들(POJO, record)을 제공하고 SQL 방언과 프로시저를 지원한다. 충분히 사용할 가치가 있다.
ORM 은 Java → DB schema 로 엔지니어링한다면 jOOQ 는 DB schema → Java 로 엔지니어링하는 리버스 엔지니어링이다. 즉 Database 스키마로부터 타입 세이프한 Java 코드를 생성하여 SQL 작성을 도와주는 라이브러리이다.
 
이제 어떻게 설정하는지 알아보자.
 

🔥 시작에 앞서

Java 21, kotlin, Gradle, Flyway 를 함께 사용하며 gradle 버전은 9.0.0 을 사용한다. (DB는 postgreSQL)
또 jOOQ 는 여러가지 커스텀 기능을 제공하는데 buildSrc 를 이용한 단일 모듈과 멀티 모듈에서 적용하는 방법을 설명한다.
 
  • 단일 모듈 + buildSrc
 
  • 멀티 모듈
 
# gradle-wrapper.properties distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists
 

🔥 설정하기

jOOQ 철학 중 하나는 데이터베이스를 단일 진실 공급원으로 보는 것이다. jOOQ 는 데이터베이스 스키마로부터 타입 세이프한 Java 코드를 생성해준다. 결과적으로 DB 와 애플리케이션의 불일치를 제거하고 타입 안정성과 스키마 일관성을 컴파일 시점에서 보장한다.
 
데이터베이스의 스키마의 관리가 중요하므로 flyway 를 사용하여 해결하자.
이때 build Task 순서가 중요한데 flyway → jOOQ 순서로 수행되게 빌드 Task 파이프라인을 설정해야 한다.
 
  • root/buildSrc/src/main/kotlin/JooqLibs
object JooqLibs { const val PATH = "gradle/dep/jooq-dep.gradle" const val NS_STUDER_JOOQ = "nu.studer.jooq" const val VERSION = "10.1.1" const val STRATEGY_NAME = "dev.lkdcode.framework.config.JPrefixGeneratorStrategy" const val TARGET_PACKAGE_NAME = "dev.lkdcode.jooq" const val DEFAULT_DIRECTORY = "generated/jooq" const val JOOQ_VERSION = "3.20.8" const val JOOQ = "org.jooq:jooq:$JOOQ_VERSION" const val JOOQ_KOTLIN = "org.jooq:jooq-kotlin:$JOOQ_VERSION" const val JOOQ_KOTLIN_COROUTINES = "org.jooq:jooq-kotlin-coroutines:$JOOQ_VERSION" const val JOOQ_META = "org.jooq:jooq-meta:$JOOQ_VERSION" const val JOOQ_CODEGEN = "org.jooq:jooq-codegen:$JOOQ_VERSION" const val JOOQ_POSTGRESQL_CONNECTOR = "org.postgresql:postgresql" }
 
  • root/build.gradle.kts
plugins { id(JooqLibs.NS_STUDER_JOOQ) version JooqLibs.NS_STUDER_JOOQ_VERSION id(FlywayLibs.ID) version FlywayLibs.VERSION }
 
ns.studer.jooq 플러그인을 추가하여 Gradle Task 에 추가한다.
./gradlew generateJooq 태스크가 추가되고 jooq { … } 블록 안에서 다양한 설정들을 할 수 있다.
마찬가지로 flyway 도 추가한다.
 
  • root/gradle/dep/jooq-dep.gradle
dependencies { implementation(JooqLibs.JOOQ) implementation(JooqLibs.JOOQ_KOTLIN) implementation(JooqLibs.JOOQ_KOTLIN_COROUTINES) jooqGenerator(JooqLibs.JOOQ_META) jooqGenerator(JooqLibs.JOOQ_CODEGEN) jooqGenerator(JooqLibs.JOOQ_POSTGRESQL_CONNECTOR) }
jOOQ 의 기본 DSL 기능과 코틀린과 관련된 의존성을 추가한다.
 
jooqGenerator 설정은 빌드 타임에 코드 생성을 위한 설정이다. generateJooq 태스크를 실행할 때만 사용되는 의존성이고 JOOQ_METAJOOQ_CODEGEN 은 DB 메타 데이터를 읽고 코드 생성을 도와준다.
generateJooq 태스크 시점에 PostgreSQL 연결 → 데이터베이스 정보 읽기 → Java/Kotlin 코드 생성 흐름으로 진행된다.
 
  • root/build.gradle.kts
jooq { configurations { create("main") { jooqConfiguration.apply { jdbc.apply { driver = "org.postgresql.Driver" url = "jdbc:postgresql://localhost:15432/lkdcode" user = "lkdcode" password = "lkdcode" } } } } }
 
jooq { … } 블록을 위와 같이 채우고 generateJooq 태스크를 확인해보자.
notion image
 
generateJooq 태스크를 실행해보자. (명령어는 $ ./gradlew generateJooq)
notion image
 
 
generateJooq 태스크가 성공하면서 root/build/generated-src/jooq/.. 경로에 java 코드를 생성했다.
현재 아무런 추가 설정이 없어서 모든 정보가 생성됐는데 설정을 통해 필요한 객체만 생성할 수 있다.
 
 

🚀 generateJooq

 
jOOQ 코드를 생성하기 위해 여러가지 방법이 있고 설정 또한 살짝 복잡하다.
본 글에서는 아래의 4가지 항목을 살펴보고 어떻게 설정하는지 설명한다.
 
  1. DB 연결을 CI/CD 수준에서 주입하거나, application.yml 로 핸들링할 것이다. 여기서는 application.yml 을 읽어와 적용하는 방법을 알아본다.
  1. java 코드 → kotlin 코드로 생성하기
  1. jOOQ 의 철학(리버스 엔지니어링)을 보호해줄 수 있는 flyway 를 적용하기
  1. generateJooq 시점에 커스텀한 생성 전략을 적용하기
 
 

🚀 DB 연결 정보

 
jooq { .. } 바디에 데이터베이스 연결 정보를 하드코딩하고 싶은 개발자는 없을 것이다.
설령 프라이빗해서 하드코딩한다고 하더라도 개발환경과 프로덕션환경 로컬환경 등 환경이 변할 때마다 수정하는 것때문이라도 하드코딩은 피할 것이다.
 
시스템 환경 변수를 읽는 방법이 제일 간단하다. (주요 비밀키를 CI/CD 단계에서 주입하기도 하기에)
val databaseUser = System.getProperties()["databaseUser"] ?: "lkdcode" val databasePassword = System.getProperties()["databasePassword"] ?: "lkdcode" # ./gradlew generateJooq -DdatabaseUser=lkdcode -DdatabasePassword=lkdcode
 
또, application.yml 을 읽어 적용하는 방법도 있다.
우선 application.yml 을 읽기 위해선 org.yaml.snakeyaml.Yaml 이 필요하다.
여러 코드들이 build.gradle.kts 한 곳에 있으면 읽기도 복잡하므로 root/buildSrc/.. 쪽으로 빼내고 import 하여 사용하자.
 
  • root/buildSrc/build.gradle.kts
plugins { `kotlin-dsl` groovy } repositories { mavenCentral() } dependencies { implementation(gradleApi()) implementation("org.yaml:snakeyaml:2.2") }
 
package dev.lkdcode import org.gradle.api.Project import org.yaml.snakeyaml.Yaml class YmlParser { private static final SPRING = "spring" private static final SPRING_PROFILE_ACTIVE = "spring.profiles.active" private static final FLYWAY = "flyway" private static final URL = "url" private static final DRIVER = "driver-class-name" private static final USER = "user" private static final PASSWORD = "password" private static final SCHEMA = "schemas" private static final LOCATIONS = "locations" private final Project project YmlParser(Project project) { this.project = project } String getFlywayDriver() { return String.valueOf(navigate(loadYml(), SPRING, FLYWAY, DRIVER)) } String getFlywayUrl() { return String.valueOf(navigate(loadYml(), SPRING, FLYWAY, URL)) } String getFlywayUser() { return String.valueOf(navigate(loadYml(), SPRING, FLYWAY, USER)) } String getFlywayPassword() { return String.valueOf(navigate(loadYml(), SPRING, FLYWAY, PASSWORD)) } String getFlywaySchema() { return String.valueOf(navigate(loadYml(), SPRING, FLYWAY, SCHEMA)) } List<String> getFlywayLocations() { return navigate(loadYml(), SPRING, FLYWAY, LOCATIONS) as List<String> } private static Object navigate(final Map yml, final Object... keys) { def current = yml for (key in keys) { if (!(current instanceof Map)) return null current = current[key as String] if (current == null) return null } return current } private Map loadYml() { def ymlFile = project.file("src/main/resources/application-${getActiveProfile()}.yml") if (!ymlFile.exists()) { throw new FileNotFoundException("YAML file not found: ${ymlFile.path}") } return new Yaml().load(ymlFile.text) as Map ?: [:] } private String getActiveProfile() { return (project.findProperty(SPRING_PROFILE_ACTIVE) as String) ?: 'local' } }
 
 
page icon
✅ buildSrc
Gradle 빌드에서 사용할 수 있는 특별한 디렉토리이다.
의존성 버전 중앙 관리, 빌드 로직 재사용 등 여러 기능을 지원하며
프로젝트 루트에 buildSrc 디렉토리만 만들면 Gradle 이 자동으로 인식하고 컴파일한다.
 
  • root/build.gradle.kts
val databaseDriver: String = YmlParser(project).flywayDriver val databaseUrl: String = YmlParser(project).flywayUrl val databaseUser: String = YmlParser(project).flywayUser val databasePassword: String = YmlParser(project).flywayPassword jooq { configurations { create("main") { jooqConfiguration.apply { jdbc.apply { driver = databaseDriver url = databaseUrl user = databaseUser password = databasePassword } } } } }
 
위와 같이 YmlParser.groovy 를 이용해 application.yml 의 값을 읽어올 수 있다.
 
 

🚀 java → kotlin

Java 프로젝트라면 Java 클래스(POJO, record)를 생성하고 Kotlin 프로젝트라면 Kotlin 코드를 생성해야 한다.
jooqConfiguration.apply{..} 바디안에 설정해 줄 수 있다.
 
jooq { configurations { create("main") { jooqConfiguration.apply { /* 생략.. */ generator.apply { name = "org.jooq.codegen.KotlinGenerator" } } } } }
 
KotlinGenerator 를 추가해주면 jOOQ 가 생성하는 코드는 xxx.kt 로 생성해준다.
jOOQjOOQThe jOOQ User Manual. 공식문서를 참고하면 다양한 설정들이 있는데 대표적으로 몇 가지만 설정해본다.
 
generator.apply { name = "org.jooq.codegen.KotlinGenerator" generate.apply { isJavaTimeTypes = true // java.time.* 사용여부 isDeprecated = false // @Deprecated 생성 여부 isFluentSetters = true // setter 체이닝 여부 isRecords = true // Record 클래스 생성 여부 isDaos = false // DAO 생성 여부 isKotlinNotNullPojoAttributes = true // Kotlin non null POJO isKotlinNotNullRecordAttributes = true // Kotlin non null Record isKotlinNotNullInterfaceAttributes = true // Kotlin non null Interface } }
 
공식문서를 참고해서 알맞게 사용하면 된다.
 

🚀 Flyway 적용하기

./gradlew generateJooq 태스크를 다시 보면 buildSrcgenerateJooq 순서로 실행된다.
jOOQ 의 철학을 올바르게 지키려면 데이터베이스 스키마를 먼저 검증해야할 것이다.
공식문서에서도 Flyway 와 함께 사용하는 것을 권장하고 있으니 Flyway 의 태스크를 generateJooq 태스크 전에 추가하여 스키마의 유효성 검사를 진행한 후 jOOQ 코드를 생성해보자!
 
 
  • root/build.gradle.kts 에 Flyway plugin 과 Gradle plugin repository 를 추가해준다.
plugins { id(FlywayLibs.ID) version FlywayLibs.VERSION } repositories { gradlePluginPortal() }
 
page icon
gradlePluginPortal()
Gradle 플러그인을 받아오는 레파지토리이다.
 
notion image
이제 build.gradle.kts 에서 flyway 와 관련된 태스크들이 추가됐고 flyway { ... } 블록을 사용할 수 있다. flyway 기본적으로 JDBC 를 기반으로 연결한다.
 
flyway 태스크를 실행하기 전에 빌드 스크립트 의존성이 필요하다.
 
일반적으로 dependencies {..} 스크립트는 애플리케이션 코드를 실행할 때 필요한 의존성이라
Gradle 빌드를 하기위해서 해당 의존성을 사용할 수 없다.
 
다시 돌아와서 Flyway 와 관련된 태스크는 Gradle 플러그인 실행하는데 이때 dependencies {..} 의존성은 플러그인 클래스 패스에 포함되지 않는다.
buildscript {..} 블록을 사용해서 Gradle 플러그인이 사용할 의존성을 추가해주자.
 
  • root/build.gradle.kts
buildscript { repositories { mavenCentral() } dependencies { classpath(FlywayLibs.DB_POSTGRESQL) classpath(FlywayLibs.POSTGRESQL_CONNECTOR) } }
 
 
  • flyway 태스크들
notion image
notion image
 
이제 정상적으로 잘 실행되니 generateJooq 태스크 전에 flyway 의 태스크를 추가하여 데이터베이스의 스키마 유효성 검사를 진행해보자!
 
tasks.named("generateJooq") { dependsOn("flywayMigrate") }
 
  • ./gradlew generateJooq
notion image
 
buildSrcflywayMigrategenerateJooq 태스크 순서로 실행된 것을 확인할 수 있다.
 
 
만약 application.yml 에 있는 db/migration 을 통해 flyway 의 Location 정보를 읽으려고 할 때 실패한다면 아래처럼 processResources 를 추가해주자.
tasks.named("flywayMigrate") { dependsOn("processResources") } tasks.named("flywayClean") { dependsOn("processResources") } tasks.named("flywayInfo") { dependsOn("processResources") }
processResources 를 실행해서 src/main/resources 파일들을 복사하여 다른 태스크에서 사용할 수 있도록 도와준다.
 
 

🚀 jOOQ 코드 생성 전략 커스텀하기

QueryDSL 을 사용하면 QMyTable 컨벤션으로 Q 접두사가 붙는다. 개발하면서 한 눈에 알아 차릴 수 있고 클래스명이 겹치지 않으니 import 구문도 따로 신경쓰지 않아도 된다. 고로 편하다.
jOOQ 도 코드 생성 전략을 통해 여러가지 커스텀을 할 수 있다!
 
jOOQjOOQCodegen configuration: Custom generator strategies
공식문서를 참고하면 여러 방법들을 알려주는데 그 중 DefaultGeneratorStrategy 클래스를 오버라이딩해서 커스텀해보자.
 
DefaultGeneratorStrategy 를 사용해서 커스터마이징하려면 JVM 컴파일 실행 흐름을 짚고 넘어가야한다.
 
JVM 컴파일 실행 흐름을 간략하게 보면,
.javajavac.class클래스로더JVM로딩링킹초기화 순서대로 진행된다.
클래스로더.class 바이트 코드를 JVM 에 로딩하는데 여러 클래스로더가 계층 구조로 이루어져있다.
 
Java9+ 부터는 Extensions CLPlatform CL 로 변경됐으며
Bootstrap ClassLoaderPlatform ClassLoaderApplication ClassLoaderCustom ClassLoader 순서로 부모 위임으로 아래로 검색된다.
 
플러그인으로 등록한 nu.studer.jooq 를 통해 Custom CL 에서 jOOQ Worker 가 동작하면서 코드를 생성해준다.
# build.gradle.kts plugins { id(JooqLibs.NS_STUDER_JOOQ) version JooqLibs.VERSION }
 
Gradle 을 시작하면 Gradle Daemon 이 시작되고 CL 들이 준비된다.
이후 build.gradle.kts 를 해석하여 nu.studer.jooq 플러그인을 로드한다.
 
generateJooq Task 를 실행하는 시점에 Worker API 를 호출하여 jooqGenerator configuration 기반으로 jOOQ 코드 생성기를 실행하고 우리가 커스터마이징할 DefaultGeneratorStrategy 코드도 읽어서 .java(.kt) 파일을 생성해준다.
 
generateJooq 는 격리된 환경에서 실행되는데 implementation, runtimeOnly 의존성은 해당 worker 에게 안 보인다. 즉 전략 클래스가 있더라도 worker 클래스패스에 없다면 ClassNotFoundException 과 같은 에러가 발생하면서 종료된다. 컴파일을 선행하고 올바른 클래스 패스를 포함시켜 generateJooq 가 사용할 수 있도록 해야 한다.
 
한 마디로 커스터마이징한 DefaultGeneratorStrategy 클래스가 준비되어야 한다는 것!
 

🎯 buildSrc 로 클래스 패스에 포함시키기

 
단일 모듈, 작은 프로젝트, 멀티 모듈 관리하기 싫음.. 등일 때 buildSrc 를 활용하여 해결할 수 있다.
buildSrc 는 가장 먼저 빌드되어 JAR 로 올린다. generateJooq 시점에 해당 클래스가 존재하므로 사용할 수 있다.
 
우선 buildSrc 디렉토리와 함께 buildSrc 가 사용할 의존성을 추가해준다.
  • root/buildSrc/build.gradle.kts
plugins { `kotlin-dsl` } repositories { mavenCentral() } dependencies { implementation("org.jooq:jooq-codegen:3.20.8") implementation("org.jooq:jooq-meta:3.20.8") }
 
jOOQ 코드 생성과 관련된 의존성을 추가해주자.
root/buildSrc/src/main/… 에서 의존성과 관련된 파일들을 정의하고 있는데 정작 root/buildSrc/build.gradle.kts 에서는 사용할 수 없다.
 
컴파일 과정 순서때문인데 buildSrc/build.gradle.kts 가 컴파일되기 전에 먼저 평가되기 때문에
oot/buildSrc/src/main/… 안에 정의한 object, class 등 을 가져다 쓰는 건 불가능하다.
아쉽지만 root/buildSrc/build.gradle.kts 는 평문으로 작성해주자.
 
generateJooq 와 관련된 의존성을 추가해주고 소스 코드를 작성하자.
  • LkdCodeGeneratorStrategy
package dev.lkdcode.jooq import org.jooq.codegen.DefaultGeneratorStrategy import org.jooq.codegen.GeneratorStrategy import org.jooq.meta.Definition import org.jooq.meta.TableDefinition class LkdCodeGeneratorStrategy : DefaultGeneratorStrategy() { override fun getJavaClassName(definition: Definition, mode: GeneratorStrategy.Mode): String = if (mode == GeneratorStrategy.Mode.DEFAULT || mode == GeneratorStrategy.Mode.RECORD) { DEFAULT_PREFIX + super.getJavaClassName(definition, mode) } else super.getJavaClassName(definition, mode) override fun getJavaIdentifier(definition: Definition?): String = when (definition) { is TableDefinition -> DEFAULT_PREFIX + super.getJavaIdentifier(definition) else -> super.getJavaIdentifier(definition) } companion object { private const val DEFAULT_PREFIX = "J" } }
 
 
  • root/build.gradle.kts
val buildSrcClasspath = files( rootProject.file("buildSrc/build/classes/kotlin/main"), rootProject.file("buildSrc/build/classes/java/main") ) dependencies { jooqGenerator(buildSrcClasspath) jooqGenerator("org.jetbrains.kotlin:kotlin-stdlib:2.0.21") } jooq { configurations { create("main") { jooqConfiguration.apply { generator.apply { /* 생략 */ strategy.apply { name = "dev.lkdcode.jooq.LkdCodeGeneratorStrategy" } } } } } }
 
root/buildSrc/… 에서 정의한 LkdCodeGeneratorStrategy.kt 의 클래스를 jOOQ 코드 생성 전략으로 사용해야 한다. 위와 같이 strategy.name 에 등록해주고 해당 클래스의 위치를 찾을 수 있게 설정해주면 된다.
 
buildSrcClasspath 를 통해root/buildSrc/… 에서 정의한 LkdCodeGeneratorStrategy.kt 의 클래스를 가리키고, dependencies 에 jooqGenerator 로 등록해주면 된다.
 
jooqGenerator config에 jOOQ 코드 생성이 수행되는 Worker 의 전용 클래스 패스에 커스텀한 전략을 등록해주어 생성시 참조하게 된다.
 
  • Task: generateJooq
notion image
 
설정한대로 buildSrc → Flyway → jOOQ 태스크대로 수행이 됐고 접두사를 붙여 생성에 성공했다.
다양한 설정과 전략이 있으므로 입맛에 맞게 커스터마이징하면 된다.
 
buildSrc 에 클래스를 두기 보다는 멀티모듈이 더 유리한데 이는 컴파일과 관련이 있다.
buildSrc 가 변경되면 전체 스크립트를 한 번 더 읽게 되는 비용이 발생한다.
(또 창시자도 모듈로 관리하는 것을 추천하기도 하고)
 
단일 프로젝트용이거나 간단하게 추가하거나, 혹은 모듈을 별도로 두기 싫을 때 외에는 jooq 관련 모듈로 관리하는 것을 추천한다.
 
 

🎯 멀티 모듈로 클래스 패스에 포함시키기

buildSrc 방법을 알아봤으니 멀티 모듈로 관리해보자.
jooq 설정과 관련된 모듈 하나와 api 모듈 하나를 준비하고 build.gradle.kts 를 설정하자
root/build.gradle.kts , root/settings.gradle.kts 를 설정해주고 각 모듈을 설정해주면 된다.
 
 
jooq-config 모듈은 커스텀 DefaultGeneratorStrategy 클래스가 존재하는 모듈로 관련 설정 클래스를 두면 된다.
  • root/jooq-config/build.gradle.kts
plugins { kotlin(Kotlin.WITH_JVM) version Kotlin.KOTLIN_VERSION } dependencies { implementation(JooqLibs.JOOQ_CODEGEN) }
 
lkdcode-api 모듈은 일반 어플리케이션 모듈로 jooq-config 모듈을 참조해서 jOOQ 관련 코드를 생성할 수 있다.
  • root/lkdcode-api/build.gradle.kts
/* 생략 */ apply { from(SpringWebFluxLibs.PATH) from(DatabaseLibs.PATH) from(KotlinLibs.PATH) from(FlywayLibs.PATH) from(FlywayLibs.CONFIG_PATH) from(JooqLibs.PATH) from(JooqLibs.CONFIG_PATH) } tasks.named("generateJooq") { dependsOn("flywayMigrate") } tasks.named("build") { dependsOn("generateJooq") }
 
root/build.gradle.kts 에서 작성한 설정들 외에 해당 모듈에서 필요한 설정들을 추가해 준다.
../gradle 디렉토리에 Gradle 이 동작할 때 필요한 스크립트들을 분리해서 관리하거나 한 곳에 작성해도 된다.
 
  • root/lkdcode-api/gradle/config/flyway-config.gradle
import dev.lkdcode.yml.YmlParser def ymlParser = new YmlParser(project) def flywayDriver = ymlParser.getFlywayDriver() def flywayUrl = ymlParser.getFlywayUrl() def flywayUser = ymlParser.getFlywayUser() def flywayPassword = ymlParser.getFlywayPassword() def flywaySchema = ymlParser.getFlywaySchema() def flywayLocations = ymlParser.getFlywayLocations() flyway { driver = flywayDriver url = flywayUrl user = flywayUser password = flywayPassword defaultSchema = flywaySchema locations = flywayLocations } tasks.named('flywayMigrate') { dependsOn processResources } tasks.named('flywayClean') { dependsOn processResources } tasks.named('flywayInfo') { dependsOn processResources }
 
flyway 관련 설정을 해준다. 기존 설정과 다른게 없고 flyway 관련 태스크가 수행되기 전에 processResources 태스크를 먼저 실행해서 classpath 의 마이그레이션 파일을 찾게 한다. (buildSrc 버전과 동일한 설정이다.)
 
  • root/lkdcode-api/gradle/config/jooq-config.gradle
/* 생략 */ dependencies { jooqGenerator(project(":jooq-config")) }
동일한 설정들은 생략하였다.
jooq 코드 생성이 수행되는 Worker 가 해당 모듈을 참조하여(우리가 작성한 커스텀 전략 클래스) 코드를 생성할 수 있게 jooq-config 모듈을 jooqGenerator 에 등록해준다.