
여러 이유로 인해 팀 이동을 하게 되었고, 주요 기술 스택이 Rails에서 Kotlin + Spring boot가 되었다. 일반적인 Spring boot stack과 다르게 Kotlin에 최적화된 Exposed를 사용 중인데, 이 과정에서 조금의 불편함들을 느끼고 있다.
그 중 하나는 Rails의 query log이다.

위 사진처럼 Rails는 주로 쿼리를 남긴 위치를 알 수 있어서 디버깅에 편리하다. 또한 쿼리 앞에 /* position */ 형태로 쿼리가 남아 AWS Performance monitor나 DBA분들이 전달주시는 로그에서 쉽게 쿼리 위치를 알 수 있다. 하지만 Exposed는 그런 기능이 없어 디버깅에 많은 시간을 쏟아야한다.
Application의 Stdout log로 남기는 것에 대한 이야기는 아니다. 만드는 SQL 구문에 Comment를 추가하는 것 관련한 이야기이다. MySQL에서 주석은 다음 문서를 참고하자. https://dev.mysql.com/doc/refman/8.4/en/comments.html
Exposed는 GlobalStatementInterceptor를 제공해서 모든 쿼리의 실행 이전에 쿼리를 조작할 수 있다. 이 기능을 활용해보자. 우린 실행 이전에 조작이 필요하므로 beforeExecution를 사용하자.
이 글은 Exposed v1.0 버전이 아니라 v0.61 기준으로 작성되었다. v1을 쓴다면 Query 대신 AbstractQuery에서 comments를 조작해야한다.
package com.blog.exposed
import org.jetbrains.exposed.sql.Query
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.statements.GlobalStatementInterceptor
import org.jetbrains.exposed.sql.statements.StatementContext
class TestStatementInterceptor : GlobalStatementInterceptor {
override fun beforeExecution(
transaction: Transaction,
context: StatementContext,
) {
when (val statement = context.statement) {
is Query -> {
statement.adjustComments(
position = Query.CommentPosition.FRONT,
content = "Some comment",
)
}
}
}
}
이제 쿼리 작성은 끝났다. 이제 등록하기 위해
META-INF/services/org.jetbrains.exposed.sql.statements.GlobalStatementInterceptor
위 경로에 우리가 만든 TestStatementInterceptor를 등록해주자.
내용을
com.blog.exposed.TestStatementInterceptor
처럼 적으면 등록이 된다.

실제 요청을 날려 검증해볼 경우 잘 나오는 걸 확인할 수 있다.