EKS Fargate 를 기본사양으로 약 1달 정도 사용해 봤다. Fargate 의 기본사양(최소사양)은 vCPU 0.25 / memory 0.5GB 이다. 1개의 CPU 코어가 2 vCPU 니까 0.25면... Spring Jar 파일 돌리는데 부팅시 스프링 로그가 2초에 1줄 정도씩 나왔나. 당연히 부팅시간도 상당히 늘어난다. ALB 의 health check 도 길어지고... 부팅된 후에는 Lazy 설정 때문에 Slave DataSource 가 처음 세팅될 때도 10초 이상의 응답으로 Timeout 이 발생하기도 했다. 그것 빼고는 단일 어플리케이션 돌아가는데 큰 문제는 없어보였다. 이것저것 다 빼다보면 어디다 써야할지... t2.nano 보다도 낮은 사양... 우선 xms / xmx 을 확인해 봤다.
programmatic 설정은 왠지 간단해 보였는데 code generate 는 실패했다.ㅋㅋ; 어쨌든 공식 사이트에서도 서드 파티 플러그인을 추천하니 어쩔수 없이...
Spring Boot + Jooq + Mysql 로 테스트 했지만, 아래에 Spring Boot 관련 라이브러리는 대부분 제외했다. Spring Boot 연동도 문제없음.
1. dependency 설정
build.gradle - jooq 로 자바 코드를 생성하고 DSL 을 사용하는데 필요한 plugin 과 DB 커넥터 추가.
// Jooq / Mysql connector
plugins {
id 'java'
id 'nu.studer.jooq' version '6.0.1' // gradle-jooq-plugin
}
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
runtimeOnly 'mysql:mysql-connector-java:8.0.25'
jooqGenerator('mysql:mysql-connector-java:8.0.25')
}
2. Code generation 설정
org.jooq.codegen 으로 DB 의 테이블에 매핑되는 클래스를 생성하도록 설정이 필요하다. JDBC 설정부터 DB의 어느 테이블을 클래스로 변환하고 제외할 것인지 상세하게 설정할 수 있다. codegen 으로 생성된 클래스로 DSL 질의를 실행할 수 있다. build.gradle 에 이어서 추가...
jooq {
version = '3.15.1' // default (can be omitted)
edition = nu.studer.gradle.jooq.JooqEdition.OSS // default (can be omitted)
configurations {
main { // name of the jOOQ configuration
generateSchemaSourceOnCompilation = true // default (can be omitted)
generationTool {
logging = 'WARN' // TRACE, DEBUG, INFO, WARN, ERROR, FATAL
onError = 'LOG' // FAIL, LOG, SILENT
jdbc {
driver = 'com.mysql.cj.jdbc.Driver'
url = 'jdbc:mysql://example-db-cluster.cluster-clas4lq5kfel.ap-northeast-2.rds.amazonaws.com:3306/portal'
user = 'user'
password = 'password'
properties {
property {
key = 'ssl'
value = 'true'
}
}
}
generator {
name = 'org.jooq.codegen.DefaultGenerator'
strategy {
// org.jooq.codegen.KeepNamesGeneratorStrategy - DB 네이밍 유지: 언더바, 대소문자 등... 기본값은 PascalCaseNames
name = 'org.jooq.codegen.DefaultGeneratorStrategy'
}
database {
// https://www.jooq.org/doc/3.15/manual/code-generation/codegen-advanced/codegen-config-database/codegen-database-name/
name = 'org.jooq.meta.mysql.MySQLDatabase'
inputSchema = 'portal'
includes = '.*' // 정규표현식
excludes = 'test_.* | temp_.*'
}
generate {
generatedSerialVersionUID = 'CONSTANT'
javaTimeTypes = true // java.time.*
deprecated = false
records = true
immutablePojos = true
fluentSetters = true
}
target {
// packageName = 'nu.studer.sample'
packageName = 'com.example.api.jooqgen'
// directory = 'build/generated-src/jooq/main' // default (can be omitted)
directory = 'src/main/java' // default (can be omitted)
}
}
}
}
}
}
공식 예제에서 약간의 내용만 바꿨다. 눈치채지 못할 만큼...ㅋ DB 로부터 Java code 를 생성하기 위한 스크립트이기 때문에, jooq 버전, DBCP 설정도 들어가고, 생성 전략, 코드 생성할 디렉토리 등등... 조금 길어보이긴 하지만 별거 없다. 만약 DB 스키마가 이미 존재한다면 여기까지 하고 generateJooq 태스크를 실행하면 설정한 디렉토리에 Java 클래스들이 생성되는 것을 확인할 수 있다. 별 문제가 없다면...
3. DSL 테스트
portal.account 테이블에 id, email 이 있다 치고, entity, controller 대충 만들고 DSL 로 쿼리 뽑기.
package com.example.api;
import com.example.joooq.gen.tables.Account;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class AccountRepository {
private final DSLContext dsl;
public AccountRepository(DSLContext dsl) {
this.dsl = dsl;
}
public List<Account> getList1() {
return dsl.select(DSL.field("id"), DSL.field("email"))
.from(DSL.table("account")).fetchInto(AccountEntity.class);
}
public List<Account> getList2() {
return dsl.select(Account.ACCOUNT.IDX, Account.ACCOUNT.EMAIL)
.from(Account.ACCOUNT).fetchInto(AccountEntity.class);
}
}
뙇!
getList1 의 쿼리 결과가 잘 나온다면 DB 연동이 잘 된것이고,
getList2 의 쿼리 결과가 잘 나온다면 생성된 jooq 코드가 잘 연동된 것이고.
* 연동 후기
처음에 programmatic 방식으로 접근했다가 codegen 에 실패했는데... 에러도 안나고 뭐... 그래서 plugin 방식으로 설정을 마쳤다. spring 이고 jooq plugin 이고 다 최신버전으로 설치했는데, jooq 버전을 비롯하여 중간중간 중복된 라이브러리들이 많이 거슬렸다. 가이드를 보고 spring 의 dependency-management 와 버전을 맞추면 해결된다.
target directory 이슈... codegen 에서 기본 타겟 디렉토리는 build/generated-src/jooq/main 이며 모든 개발자가 각각 빋드하여 코드를 생성해야 한다. 이를 소스셋(src/main/java) 로 변경한다면 버전관리가 가능할 수 있지만 해당 디렉토리를 삭제하고 generate 하기 때문에 target 디렉토리를 src/main/java 로 했다가는 그 안의 소스 패키지가 빌드할 때마다 다 날아간다. 이를 막기 위한 옵션으로 clean 속성을 제공하기는 하나, 정작 해당 값을 false 로 지정하면 에러가 발생한다.
generator.target.clean must not be set to false. Disabling the cleaning of the output directory can lead to unexpected behavior in a Gradle build.
기본값대로 build 디렉토리를 이용하거나, 만약 소스가 포함되지 않은 별도의 타겟 디렉토리 구성이 필요하다면 독립된 디렉토리나 별도의 모듈에 추가하는 것을 추천한다.
정상적으로 생성됐다면 이 snippets 들을 불러올 템플릿 asciidoc 파일을 생성한다. (/src/main/asciidoc/)
= Document Title
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toc-title: API 명세서
:toclevels: 4
[[api]]
== Book Api
api 에 관련된 설명을 이곳에 적습니다..
include::{snippets}/book/curl-request.adoc[]
include::{snippets}/book/http-request.adoc[]
include::{snippets}/book/path-parameters.adoc[]
include::{snippets}/book/http-response.adoc[]
include::{snippets}/book/response-fields.adoc[]