728x90

분류 전체보기 168

MySQL 으로 형태소 분석기 없는 자동완성만들기

오늘은 간단하게 형태소 분석기 까지는 필요없는 자동완성 기능을 만들때 빠르게 만들 수 있는 방법을 해보려고 한다. 실제로 회사에도 적용한 방법이다 :) Ngram-Parser 를 택한 이유 일단 MySQL 에 ngram parser 를 이용한 방법인데 ngram parser 를 선택한 이유는 아래와 같았다. 첫째, 자동완성으로 검색되야 할 데이터 들이 MySQL 에서 관리되야 할 대상들이였다. -> 사실 NoSQL 로 가져가면 대표적으로 ES 형태소 분석 parser 나 빠른 검색등이 가능하다고 알려져 있으나 내 조건은 위와 같았다. 두번째, 딱히 ES 를 이것만을 사용하자고 추가하기에는 자원의 낭비이다. -> 굳이 MySQL 로도 가능한데 얼마 차이 안나는 성능때문에? 의문이다. 그리고 ROW 수가 적..

Spring 2022.02.24

Spring 에서 왜 Private Method 는 Cglib Proxy 에 포함이 되지않을까?

Spring 면접 하면 잘 등장하는 단골 질문 중 하나이다. 이 개념을 이해하기 위해서는 일단 Proxy 디자인 패턴에 대해서 간단하게 짚고 넘어가야 한다. 우리가 흔히 볼 수 있는 Server-Client 형태는 아래와 같다. Client 는 Server 에 요청을 보내고, Server 는 요청을 처리한다. 만약 객체 세상으로 가져온다고 했을때는 아래 그림처럼 A 객체가 B 객체에게 협력을 요청하는 것일 수 있다. 근데 만약 B 객체는 너무나 은밀한 친구라 중간에 누군가 자신이 한것처럼 대신 행동을 하는 척 해줬으면 좋겠다 라고 해보자. 그렇다면 A 객체는 B 객체와 이야기 하는것 같지만 사실은 대리자가 대신 해주고 있는 것으로 객체를 설계 해주어야 할 것이다. 위와 같은 설계가 될 것 이다. 하지만 ..

Spring 2022.02.22

Redis-Cluster 이미지 사용시 Redis-stat 쉽게 붙이기

Redis-Cluster 를 구축할때 아래 이미지를 많이 사용하는 것으로 알고 있다. grokzen/redis-cluster:6.0.5 도커에는 기본적으로 내부 IP 를 통한 통신을 할 수 있게 되는데 이것이 궁금하다면 docker0 Bridge 에 대해서 공부해보면 된다. 일단 여기는 삽질을 막는 내용만 적을 것이므로 docker0 Bridge 에 대해서 공부한 내용은 따로 적진 않겠다. docker 공식문서에도 잘 나와있으니 충분히 공부할 수 있을거라고 생각한다. 일단 가볍게 얘기해서 docker 간의 통신을 구축할때 docker 내부 접속 ip 를 알아야 할 때가 있었는데 이때 해결방법은 간단하게 같은 network 로 묶거나 혹은 host network 방식을 이용하거나 내부 접속 IP 를 알아낸..

Docker 2022.02.15

인덱스 컬럼의 가공(연산)은 예상치 못한 결과를 초래한다.

MySQL 2판을 보던 중 한가지 사실을 알았다. 바로 WHERE 조건문에 INDEX 를 통해서 검색하려고 할때 INDEX 에 변환 또는 연산을 가하게 될 경우 인덱스 조건을 안타게 된다는 사실이다. 아래 쿼리를 한번 보자. 지금 위의 쿼리를 한번 살펴보면 첫번째 쿼리는 age 라는 INDEX 컬럼에 2를 곱한 뒤 age=20 인 컬럼의 데이터를 가져오는 쿼리이다. 두번째 쿼리는 반대로 age = 40/2 인 즉 age = 20 인 쿼리를 가져오는 것이므로 두 쿼리의 결과는 아래처럼 똑같다. 하지만 결과는 같은데 MySQL 의 옵티마이저가 내린 판단은 다르다. 그 이유는 무엇일까? MySQL 에서는 기본적으로 정렬에 B-Tree 자료구조를 이용하는데 이때 사용자가 설정한 Index 의 값으로 정렬이 되어..

데이터베이스 2022.02.13

Redisson 을 분산 Lock 을 위해 사용한 이유

이전 포스팅에서 분산락에 관한 포스팅을 적었었는데 왜 Redisson 이라는 라이브러리를 사용했는지 적어보려고 한다. 일단 Spring-Boot-Starter-Redis 에서 사용하는 Library 는 Lettuce 라는 라이브러리를 사용한다. Lettuce 에서 Lock 을 구현할때는 스핀락 구조의 형태로 락을 많이 이용합니다. fun test() { val lockKey = "test" val lockTime = "3" val command = redisClient.connect().sync() try { // lock 을 획득하기 전까지 계속해서 Loop 를 순회 while (!command.setnx(lockKey, lockTime)) { // process } } catch (e: Excepti..

데이터베이스 2022.02.12

Redisson 으로 분산 Lock 구현하기

회사 프로젝트를 진행하던 동시성 문제를 해결하기 위해 분산락이 필요할 것 같다는 판단이 들었습니다. 분산락이란 무엇일까요? 아주 가볍게 설명하자면 예를 들어, 가게는 하나의 주문만 받을 수 있는데 A 손님과 B 손님이 0.0001 초차이로 주문을 한다고 해봅시다. 근데 가게에 있는 주문 기계는 주문이 들어오면 이미 주문을 받았는지를 체크하고 주문 수락을 누르는 프로세스라고 해봅시다. 하지만 주문을 받았는지 체크하기 위해서는 대략 0.1 초정도의 시간이 필요합니다. 그래서 가계기계는 A 손님의 주문과 B 손님의 주문간의 간격이 0.0001 초 밖에 되지 않아서 A 주문과 B 주문을 동시에 받게되는 상황이 발생합니다. 만약 지금과 같은 상황이면 주문을 받는 순간 뭔가 Lock 을 걸어 제어가 가능할 것 입니..

Spring 2022.02.10

[StackOverflow] 왜 자식생성자에서 super() 를 써야 하는가?

최근에 영어 공부도 할겸 StackOverflow 활동을 이틀에 하나정도는 답변을 다는 식으로 활동해보려고 한다. 일단 질문은 아래내용이다. https://stackoverflow.com/questions/70973089/using-super-in-child-constructor Is it unnecessary to put super() in constructor? Isn't this one automatically put by the compiler if I don't put it in a subclass's constructor? That means I don't even need to care about it? In some articles they put it out. And if I've got..

Java 2022.02.03

[Spring Batch] Data 를 CSV 파일로 만들기

회사에서 Spring Batch 를 통해서 DB Column 들을 CSV 로 전환해서 뽑을 필요가 있었다. 일단 간단하게 DB 에서 값을 읽어와서 CSV 로 만드는 작업을 해보자. @Entity @Table(name = "user") class User( name: String, email: String ) { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long? = null @Column(name = "name", length = 20) var name: String = name @Column(name = "email", length = 30) var email: String = email override fun toString()..

Spring 2022.01.23

Ko-Test Framework 사용해보기

코틀린 하면서 처음에는 잘 이해하지 못했던 DSL 문법의 간결함을 알게 되면서 infix 로 연계하여 만들 수 있는 DSL 구조가 좋은 것 같다는 생각이 들었다. 예를 들면 원래 Java + QueryDSL 을 사용한다면 아래와 같은 코드가 작성될 수 있을 것이다. selectFrom(person).where(person.name.eq("roach)) 하지만 코틀린의 infix 를 이용한다면 다르게 풀어볼 수도 있을 것이다. selectFrom person where person.name is "roach" 내 생각엔 Kotlin 에서 QueryDSL 을 쓰는건 계속해서 JPA + QueryDSL 을 써왔기때문이라고 생각하는데 Kotlin + Spring + JPA 를 이용한다면 QueryDSL 보다 i..

Kotlin 2022.01.21

Web 계층에 Port 를 통해 더 자유로운 코드 짜기

아래 코드를 한번 보자. Cotroller 에서 Service 계층을 바로 참조하고 있다. 이건 보통 일반적인 비즈니스 로직을 작성할때 많이 작성되는 코드이다. @RestController class UserJoinController( private val userJoinService: UserJoinService ) { @GetMapping("/users") fun hello() { userJoinService.join() } } 이건 보통 일반적인 코드인데 한가지 문제점이라면 문제점이 있을 수 있다. 만약 User 가 회원가입하는 부분이 MSA 환경으로 분리된다면 어떻게 대응할 수 있을까? 아마도, 기존의 UserService 를 지워야 하거나 수정하는 현상이 발생할 것이다. 우리가 클린코드 / 클린..

Architecture 2022.01.20
728x90