이번에 회사에서 신규 프로젝트를 kotlin 과 spring boot 를 사용해서 개발하기로 했다.
kotlin, spring boot 둘 다 처음 접해보기 때문에 기본 개념과 동작 원리부터 공부를 하고 있다.
그러나 공부와 별개로 프로젝트 진행은 되어야 하기 때문에 어제부터 동료 개발자 분과 초기 프로젝트 세팅을 진행했다.
기술스택은 kotlin, spring boot 2.3.5, JPA + querydsl, liquibase, Gradle + kotlin dsl 로 정해졌다.
따라서 동료 개발자분은 spring security 부분을, 나는 jpa + querydsl 을 초기 설정하였다.
그러나 kotlin dsl 기반의 gradle을 이용해서 querydsl 을 설정하는 방법에 대한 문서가 많이 없었고, 처음 경험하는 입장에서 많이 해멨기에 블로그에 글로 정리해 두려 한다.
우선 querydsl 은 다음과 같은 도구이다. querydsl 에 대한 문서는 구글에 많이 있어 특징만 간략하게 적어두면 다음과 같다.
# Querydsl
- SQL, JPQL을 코드로 작성할 수 있게 해주는 builder api
- SQL 과 달리 타입 체킹이 가능하고, 컴파일 단계에서 오류를 걸러낼 수 있음
- SQL 쓰느라 객체 컨텍스트에 대한 초점을 잃지 않고 개발할 수 있다
https://ict-nroo.tistory.com/117
# build.gradle.kts 세팅
아래 코드에서 Querydsl 관련 주석이 달린 부분을 프로젝트 루트의 build.gradle.kts 파일에 추가한다.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
val kotlinVersion = "1.5.31"
id("org.springframework.boot") version "2.5.6"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("plugin.jpa") version kotlinVersion // jpa
kotlin("jvm") version kotlinVersion
kotlin("plugin.spring") version kotlinVersion
kotlin("kapt") version "1.4.10" // querydsl 추가
idea // querydsl 추가
}
noArg {
annotation("javax.persistence.Entity")
}
group = "test"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
val querydslVersion = "4.4.0" // querydsl 추가
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// querydsl 추가
implementation("com.querydsl:querydsl-jpa:$querydslVersion")
kapt("com.querydsl:querydsl-apt:$querydslVersion:jpa")
kapt("org.springframework.boot:spring-boot-configuration-processor")
// querydsl 추가 끝
developmentOnly("org.springframework.boot:spring-boot-devtools")
runtimeOnly("mysql:mysql-connector-java") // Mysql driver
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
// querydsl 추가
idea {
module {
val kaptMain = file("build/generated/source/kapt/main")
sourceDirs.add(kaptMain)
generatedSourceDirs.add(kaptMain)
}
}
// querydsl 추가 끝
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
처음 해당 코드들을 추가하면 gradle에서 kapt 가 적용된 부분에 대해 빨간줄을 그으며 import 하라고 알려줄 수 있는데, 무시하고 build 하거나 reference sync 해주도록 한다.
위 gradle 파일 중 idea(Intellij 기준) 세팅 코드가 있는데, 해당 코드는 querydsl 을 통해 생성될 QClass의 directory 위치를 등록해두는 동작을 수행한다.
그리고 테스트 환경에서 mysql 을 사용할 것이기 때문에 mysql driver도 의존성에 추가하였다.
# Database Setting
database 설정은 application.properties(application.yml) 파일에서 설정할 수 있다. (프로젝트에서 안보인다면 프로젝트 보기 구조를 IDE 좌측 상단에서 Packages를 선택하여 변경한다)
application.properties 을 이용하는 경우
spring.datasource.url=jdbc:mysql://localhost:3306/test // DB url
spring.datasource.username=root // User name
spring.datasource.password=test // password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver // Mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.database=mysql
spring.jpa.show-sql=true
application.yml 을 이용하는 경우 (yaml 파일 형식이 더 직관적이고 가독성이 좋아서 추천하는 방법이다)
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: test
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
database: mysql
show-sql: true
마지막으로 QuerydslConfig
클래스를 작성해준다.
package com.test.config
import com.querydsl.jpa.impl.JPAQueryFactory
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import javax.persistence.EntityManager
import javax.persistence.PersistenceContext
@Configuration
class QuerydslConfig (
@PersistenceContext
private val entityManager: EntityManager
) {
@Bean
fun jpaQueryFactory(): JPAQueryFactory {
return JPAQueryFactory(this.entityManager)
}
}
해당 클래스에서는 entity의 영속성 컨텍스트를 관리하는 entitymanager
를 의존성 주입받아 JPAQueryFactory
의 인자로 넘겨준다. JPAQueryFactory
는 Querydsl의 QueryFactory
를 상속받은 JPQLQueryFactory
의 구현체이며 @Bean
어노테이션을 통해 Spring Bean으로 등록되어 관리된다.
QuerydslConfig
는 @Configuration
어노테이션을 이용하여 해당 클래스에서 Bean을 생성하고 있음을 명시한다. @Configuration
역시 내부를 들여다보면 @Component
어노테이션을 포함하기 때문에 QuerydslConfig
클래스도 Bean으로 등록됨을 알 수 있다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
/**
* Explicitly specify the name of the Spring bean definition associated with the
* {@code @Configuration} class. If left unspecified (the common case), a bean
* name will be automatically generated.
* <p>The custom name applies only if the {@code @Configuration} class is picked
* up via component scanning or supplied directly to an
* {@link AnnotationConfigApplicationContext}. If the {@code @Configuration} class
* is registered as a traditional XML bean definition, the name/id of the bean
* element will take precedence.
* @return the explicit component name, if any (or empty String otherwise)
* @see AnnotationBeanNameGenerator
*/
@AliasFor(annotation = Component.class)
String value() default "";
...생략
여기까지 되었다면 초기 설정은 끝났다.
다음으로는 Entity와 Repository 를 작성하여 실제 데이터베이스와 매핑되는 Entity 객체를 기반으로 Querydsl의 QClass를 자동 생성하는 과정과 함께, kotlin을 사용하여 Entity 객체를 작성하면서 느낀 점에 대해서 작성하고자 한다.
'Spring' 카테고리의 다른 글
[spring boot / kotlin] kotlin으로 JPA entity 작성하기 (0) | 2021.11.21 |
---|
댓글