본문 바로가기

분류 전체보기

(5)
[QueryDSL] MATCH.. AGAINST.. dialect 사용하기 (Full-Text 검색 함수, 커스텀 함수 정의) with Kotlin 1. FunctionContributor 정의 나는 MatchFunctionContributor라고 선언했다. class MatchFunctionContributor : FunctionContributor { companion object { private const val FUNCTION_NAME = "MATCH_AGAINST" private const val FUNCTION_PATTERN = "MATCH (?1) AGAINST (?2 IN BOOLEAN MODE)" } override fun contributeFunctions(functionContributions: FunctionContributions) { functionContributions.functionRegistry .registerPa..
[Java] 비정적 이너 클래스와 정적 이너 클래스의 차이 (inner class vs static inner class) 스프링 컨테이너의 싱글톤 패턴에 대해 학습하다가 테스트 작성 중 이너 클래스에 대해 접하게 되어 학습하게 되었는데, static 키워드 때문에 이너 클래스의 참조값에 대한 혼란이 컸다.. 그래서 정리하게 되었다. Inner Class (이너 클래스)란? 자바에서 이너 클래스는 클래스 내부에서 또 다른 클래스를 선언하는 걸 말한다. 그런데 이너 클래스 종류중 특히 살펴볼 것은 아래의 두 유형이다. public class OuterClass { // 1. 비정적 이너 클래스 class InnerClass{ void printMessage() { System.out.println("InnerClass"); } } // 2. 정적 이너 클래스 static class StaticInnerClass { void p..
카테고리, 댓글/답글과 같은 계층(트리) 데이터베이스 구조 설계 및 개선하기 카테고리와 같은 계층형 데이터 구조는 어떻게 설계하고 관리해야 할까? 현재 운영하고 있는 사이트에서는 아래 사진과 같이 하나의 카테고리가 있으면 parent_id 컬럼을 이용해 부모-자식 관계를 표현하고 있다. 이 방식을 인접 목록(Adjacency List) 방식이라고 한다. 문제 상황 그러나 프로젝트에서 사용되고 있는 카테고리 목록 조회 API의 본래 요구사항은 현재 카테고리를 기준으로 모든 하위 카테고리를 가져올 수 있어야 한다였으나 현재 스키마 설계로는 조회하고 싶은 카테고리의 가장 마지막 노드(가장 마지막 하위 카테고리)를 parent_id를 통해 몇 번을 조인해서 가져올 수 있는지 알 수 없는 구조였다. 그래서 우선은 재귀 쿼리를 사용해 children 응답 컬럼을 추가하여 모든 하위 카테고리..
[MySQL] 탐색할 컬럼에 분명 인덱스를 걸었는데, 슬로우 쿼리?! (묵시적 형 변환) 현재 운영하고 있는 서버로 유저가 조금이라도 몰리게 되면, 전체적인 응답이 심하게 느려지는 현상이 있었습니다. 원인은 DB의 CPU 사용률이 급속도로 치솟게 된 게 원인이었고, 이를 계기로 슬로우 쿼리들을 개선하기로 했습니다. 그 과정에서 MySQL의 묵시적 형 변환에 대해 알게 되었고, 배웠던 과정을 기록하고자 합니다. 문제 상황 우선 여러 슬로우 쿼리 중 지연 시간이 가장 컸던 쿼리가 users 테이블에서 kakao_id를 통해 유저를 찾아오는 쿼리였는데, 이상했습니다. kakao_id는 인덱스가 걸려있는 컬럼임에도 평균 지연 시간이 817.36ms 이상이었거든요. users 테이블 구조는 다음과 같습니다. CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY K..
[NestJS] Interceptor를 활용한 TypeORM Transaction 코드 개선하기 TypeORM에서 제공해 주고 있는 QueryRunner 트랜잭션을 사용하려면 commit, rollback, release 처리를 수동으로 해주어야 합니다. 그래서 코드가 길어짐과 동시에 가독성이 떨어지게 되고, 트랜잭션을 수행하는 함수마다 동일한 코드가 반복되어 생길 것입니다. 이를 개선하고자 트랜잭션 인터셉터를 생성하여 적용했던 방법을 기록하고자 합니다. 인터셉터의 동작 과정 우선 인터셉터가 동작하는 순서를 그림으로 살펴보면, 컨트롤러를 거쳐 서비스 로직이 실행되기 전/후에 실행된다는 것을 알 수 있습니다. 이 점을 활용해 우리는 아래의 로직을 인터셉터로 구현할 것입니다. 1. 컨트롤러/서비스 로직이 실행되기 전 a. 새로운 QueryRunner 인스턴스를 생성하고 트랜잭션 start b. Requ..