본문 바로가기

개발 관련됨23

왜 서비스로더(ServiceLoader)를 알아야 하는가? java docs 에서 Service Loader 를 다음과 같은 한줄로 정의한다. A facility to load implementations of a service. 서비스 구현을 로드하는 기능입니다. 서비스 구현을 로드하는 기능이 왜 필요한지 부터 이해할 필요가 있을 것 같다. (여기서 서비스 구현의 의미는 비지니스 로직이 담겨진 구체적 클래스를 의미한다.) 우리가 라면을 만드는 코딩을 한다고 가정해보자. public class 신라면제조 { public void make() { pourWater(); boilWater(); putNoodle(); boilNoodle(); putSoup(); putVegetable(); } public static void main(String[] args) { .. 2024. 3. 21.
[특강] 도메인 주도 설계의 사실과 오해 2부 소프트웨어는 도메인에 관련된 문제를 해결하는 것에 초점이 맞춰져 있다. 함께 개발하는 것. 원칙적으로는 그렇다. 도메인 주도 설계의 맥락에서 도메인 모델 = 코드 해결해야할 두 가지 연관된 문제 요구사항에 적합한 모습으로 도메인을 어떻게 모델링할 것인가? 도메인을 반영한 코드를 어떻게 개발할 것인가? = 올바른 모델이 찾는 것이 아니라, 유용한(수정하기 좋은/변경하기 좋은/코드짜기 좋은) 모델을 찾아야 한다. DDD 는 위 두가지를 계속 이야기한다. 도메인을 잘 분석하면 코드로 연결해주는 것을 도와주는 부분이 파트 2에서의 내용 도메인을 분석해서 넣는게 좋은 블록들이 ASSOCIATION / VALUE OBJECT / ENTITY / SERVICE / MODULE 이렇게 해놓고 실제로 동작하는 기능을 만.. 2024. 3. 7.
Java 에 Enum Circular Dependency 이라는 말을 들어봤나요? 문제 어느 날과 다르지 않는 기능 개발 중에 이상한 상황을 마주쳤습니다. 코드부터 살펴보겠습니다. enum DisplayType { DISPLAY_1("1", ServiceType.SERVICE_A), DISPLAY_2("2", ServiceType.SERVICE_A), DISPLAY_3("3", ServiceType.SERVICE_B), DISPLAY_4("4", ServiceType.SERVICE_B); private final String name; private final ServiceType serviceType; DisplayType(String name, ServiceType serviceType) { this.name = name; this.serviceType = serviceType; .. 2023. 12. 16.
Intellij 북마크 기능(스타 부대지정 같은) / 이전 단어 재사용하기 Intellij 를 활용하면서 자주 사용하려고 했으나 사용할 때마다 단축어를 찾는 2가지 케이스가 있습니다. 바로 북마크 기능과 이전 단어 재사용하기 북마크 기능은 스타크레프트를 했던 사람이라면 친숙한 부대 지정과 비슷합니다. ⌥ F3 또는 Ctrl+F11 – 연상 기호 북마크 추가 일단 눌러보면 다음과 같은 화면이 뜹니다. 여기서 사용하고자 하는 단축키를 선택한다. 만약 1을 누르면 다음과 같이 코드 옆에 지정한 숫자 또는 문자를 찾을 수 있다. ^(MacOs) 또는 Ctrl(Windows)을 누른 상태에서 키보드에 지정된 숫자나 문자를 누르면 북마크로 이동할 수 있습니다. 최종 사용하는 모습 2. ⌥ + / - 이전 단어 재사용 2023. 8. 22.
Java Regex 정규표현식 사용시 java.lang.StackOverflowError 가 발생하는걸까 자바에서 정규표현식을 활용하다보면, BuiltIn 클래스인 Pattern 과 Matcher 이 두 가지를 사용하는 경우가 많다. Pattern 과 Matcher 을 사용할 때 주의해야될 점이 있다. 바로 재귀로 인해 무한한 루프에 빠질 수 있다는 것이다. 이로인해 위에서 말하 StackOverflowError 가 발생한다. public class RegexTest { public static void main(String[] args) { // 재귀적으로 일치하는 패턴 Pattern pattern = Pattern.compile("(a|b)*c"); Matcher matcher = pattern.matcher("aaa" + "aaa"); System.out.println(matcher.matches()).. 2023. 2. 25.
비관적 잠금, 낙관적 잠금 그런 동시성 이슈 해결하기 우리가 개발하는 프로덕트에 동시성 이슈는 어떤 것이 있을까? 사실은 그다지 많지 않을 수 있을 것 같다. 특히, 트래픽은 적은 회사에서는 더욱 그러지 않을까 싶다. 그래서 언제든 맞닥뜨리더라도 당황하지 않았으면 좋겠다. 먼저 동시성 이슈가 무엇인지부터 살펴보자. 하나의 Table Row 을 Client 1과 Client 2가 서로 업데이트를 하려고 하다보니, 동시성 이슈가 발생한다. 좀 더 구체적으로 어떤 상황에서 동시성 이슈가 발생하는가? 참고 할 만한 예시 테스트 코드는 다음과 같다. https://github.com/take-small-steps/understanding-concurrency-Issue/blob/9eea5414c1a35ec09484f2281e51e1b18380dd93/src/test.. 2023. 1. 11.
조영호님과 객체지향에 대해서 이야기하기 트레바리에서 (전) CTO님 덕분에 오브젝트 저자 조영호님과 티타임을 가질 수 있는 기회가 생겼습니다. 티타임 자리에서 물었던 질문에 대해서 기록을 남깁니다. 아쉽게도 사진은 찍지 못했지만, 관련해 이야기 나눈 부분에 대해서 공유하기 위해 기록합니다. 대화했던 내용을 녹음했던 것은 아니였기 때문에, 정확하지 않을 수 있습니다. Q. 추상화란 무엇인가? A. 추상화는 필요없는 것을 없애는 것이다. 동시에 추상화는 용도와 의도가 명확해야 한다. 처음부터 추상화를 발견할 수는 없다. 절차지향으로 코드를 작성하고 난 뒤에 중복이 발견될 때, 추상화 될 가능성이 농후하다. 그러므로, 리팩토링을 통해 추상화를 만들어내자. 추상화는 어쩔 수 없이 탑-다운 방식이 아닌 바텀-업 방식에서 나타날 수 밖에 없다. Q. 추.. 2022. 12. 22.
postgresSQL의 Idle in transaction 이란 무엇인가? Node.js 에서 발생한 Transaction 이 부족해서 문제가 발생했고, 해결하는 과정에서 Idle in transaction에 대해서 알게 되었습니다. Idle in transaction 이란 무엇인가? 문서에 따르면 다음과 같은 의미를 가집니다. idle in transaction (waiting for client inside a BEGIN block) 클라이언트가 시작을 열어놓고 기다리고 있다. 즉, 클라이언트가 정상적으로 트랜잭션을 닫지 않았다. 대부분의 Application은 ConnectionPool 을 통해 N개의 Connection 을 쥐고 있습니다. N개의 Connection이 모두다 정상적으로 동작하지 않을 경우에는 다음 Connection 이 열리지 않아 문제가 발생합니다. 그.. 2022. 9. 11.
ConnectionAcquireTimeoutError [SequelizeConnectionAcquireTimeoutError] 문제 해결하기 운영중에 Node.js 모듈이 간혈적으로 갑자기 기능이 동작되지 않는 이슈가 있었습니다. 가장 처음에는 트랜잭션 자체가 동작되지 않아, 로그를 살펴보니 위와같은 내용이 있었습니다. 이게 왜 발생했을까요? Node.js 에서 ConnectionAcquireTimeoutError 이 발생했는데, 이유를 알 수 없었습니다. 에러 메세지에 대한 원인을 찾아보니, Transaction 이 ConnectionPool 을 물고 있고, graphql에서 새롭게 만들 트랜잭션이 없어서 발생한 문제점이라는 사실을 알았습니다. 최근에 const transaction = await sequelize.transaction(); 관련된 작업이 있었고, 그곳에서 transaction 이 정상적으로 종료되지 않았음을 알 수 눈치챌 .. 2022. 9. 11.
안전하게 코드 리팩토링하기 - 1 안전하게 리팩토링하기 SOLID 원칙 중 DIP가 있다. 어떻게 하면 쉽게 리팩토링 할 수 있는지 간단하면서도 강력한 방법을 이야기해볼까 한다. 이것을 아래와 같이 변경한다고 해보자. public class LotteriesFactory { private final RandomNumberGenerator randomNumberGenerator; public LotteriesFactory(RandomNumberGenerator randomNumberGenerator) { this.randomNumberGenerator = randomNumberGenerator; } // 만약 많은 곳에서 해당 코드를 사용하고 있다면 어찌하겠는가 ???????? public String createNumber(){ retu.. 2022. 7. 24.
Message Relay 를 PollingPublisher 방식으로 구현하기 이벤트 소싱을 하기 위해서는 트랜잭션 아웃박스 패턴을 구현해야 합니다. 당연히 트랜잭션 아웃박스 패턴에 대한 이해가 있어야 합니다. 다만, 해당 포스트에서는 자세한 트랜잭션 아웃박스 패턴을 다루지 않을 계획입니다. 다시 트랜잭션 아웃박스 패턴를 표현하는 위 그림에서 네모난 부분이 바로 메세지릴레이를 수행하는 곳입니다. 데이터베이스에 특정 데이터가 Insert 되면, 변경분에 대해서 MessageRelay 는 특정 데이터를 읽어 Message Broker 에게 전달한다. 이 때 MessageRelay 의 구현방식은 2가지가 있습니다. 1. Polling publisher 2. Transaction log tailing 1. Polling publisher 는 일정 주기마다 변경분을 조회해서 메세지를 전달하.. 2022. 6. 19.
정규표현식에서 알지 못했던 capture group 과 non- capture group val groupMD = """((?:\+|\+-)?[.\d]+)([*/])((?:\+|\+-)?[.\d]+)""".toRegex() fun foldGroup(v: String): Double = groupMD.findAll(v).fold(0.0) { acc, curr -> val (_, left, op, right) = curr.groupValues val leftValue = left.replace("+", "").toDouble() val rightValue = right.replace("+", "").toDouble() val result = when (op) { "*" -> leftValue * rightValue "/" -> leftValue / rightValue else -> throw T.. 2022. 6. 6.
Springboot 에서 react.js 연동시 모든 view 맵핑을 index.html으로 forwarding 하는 방법은? [문제] SpringBoot 에서 thymeleaf 대신, React.js 를 ViewTemplate 로 사용하려 한다. 기존의 thymeleaf 는 html 별로 View을 맵핑하고 있었기 때문에, 하나의 html 에서 URL에 따른 여러 화면으로 라우팅되는 SPA Application 에서는 ViewName 맵핑이 정상적으로 동작되지 않는다. ( 참고자료 ) 예를 들어, product/list 라는 View 이름으로 맵핑을 시도한다고 가정해본다면, 프로젝트에서는 /WEB-INF/templates/product/list.html 와 같은 형태로 ViewTemplate 을 맵핑하기 위한 html 이 존재해야 합니다.(꼭, html 일 필요는 없음) 그러므로, 하나의 html 에서 원하는 URL로 라우팅시.. 2022. 4. 26.
Postgresql 에서 epoch time 을 읽을 수 있는 timestamp 변환하는 방법은? 우리가 다루는 시간 중에는 epochtime 이라는게 존재합니다. // epochtime 1970년 1월 1일 00:00:00 UTC 부터 지금까지의 경과 시간을 초로 환산하여 정수로 나타낸 것을 말한다. DB 를 다루다보면, Application 에서 DB 에 데이터를 삽입할 때, application의 date 타입을 Timestamp 로 변환해서 넣는 것이 문제가 되는 경우가 더러 있습니다. 한번만 사용되어지는 DB 라면 더욱더 해당되는데, 종종 ViewTable을 만들기 위한 용도로 만들 경우 약간의 트릭으로 Timestamp 에 넣어야 할 값을 Bigint 타입으로 CREATE Table 한 뒤, 어플리케이션에서 epochtime 으로 값을 삽입합니다. 아래 epochtime 으로 값을 넣을 경.. 2022. 4. 26.
gradle 기반의 여러 모듈에서 공통으로 쓰인 스크립트가 있다면? 멀티 모듈 시스템에서 공통으로 쓰인 Gradle Script 가 있다면 어떻게 해야 될까? RootProject | | - SubProjectA | -- build.gradle | - SubProjectB | -- build.gradle | - SubProjectC | -- build.gradle | - build.gradle 여기서 `SubProjectA` , `SubProjectB`, `SubProjectC` 가 build.gradle 에서 공통으로 사용되는 내용이 있다고 가정하자. 약 모듈이 5개정도 만들어지면서 반복되어지는 스크립트를 발견되었고, 코드 복사/붙여넣기가 불편하다고 느꼈다. 어떻게 해야될까? `base.gradle` 을 하나 만들어 전체 프로젝트에 공유하면 되지 않을까? 걱정되는 마음.. 2022. 2. 6.
MAC OS 에서 Icon 이 Bouncing 하지 않도록 하는 방법 https://howchoo.com/mac/disable-mac-icon-bounce 2021. 9. 26.
docker 에 올라온 postgres 에 접속해, Database 확인하는 방법 InteliiJ 의 편리함에 속아, 실제 DB 작업할 때는 어버버한 저를 위해 남깁니다. 먼저, 작성하기 전에 데이터베이스의 목적은 영속성입니다. 그러나 Docker는 쉽게 지우고 설치할 수 있습니다. DB의 영속성과 Docker? 사실 말이 안맞긴 합니다만... 😳 우리는 개발환경을 빨리 세팅하고 싶으니까...ㅎㅎ 참조문서 - https://hub.docker.com/_/postgres 아래 명령어를 실행했다고 가정하겠습니다. docker run --rm --name mypg -d \ -v ${PWD}/app/src/main/resources:/docker-entrypoint-initdb.d \ -p 5432:5432 \ -e POSTGRES_PASSWORD="password" \ -e POSTGRES.. 2021. 7. 9.
[Inteliij] 대문자 - 소문자 변환 단축키 Command + Shift + u 2021. 6. 3.
[intellij] 동일한 단어를 Multi-line 으로 블록하는 방법 아래 내용은 Mac OS 기준의 단축키로 설명합니다. '⇧ + F6' 이렇게 하면 동일한 단어에 대해서 아래와 같은 창이 뜬다. 그러나, 만약에 위 화면에서 4개의 단어 중 2개만 Multiline으로 하고 싶은 경우 또는, 팝업 창을 띄우지 않고 할 수 있는 방법이 있다. 만약 동일단어 4개 중 2개의 단어만 수정하고 싶은 경우 "^(options) + g" 이렇게 같이 누를 경우 누르는 버튼 횟수에 의해서 알 수 있다. 만약 동일단어 4개를 한번에 팝업창 없이 수정하고 싶은 경우 "^(options)+⌘(command)+g" 버튼을 통해 변경할 수 있다. [참고자료] www.jetbrains.com/help/rider/Multicursor.html?keymap=secondary_intellij_osx.. 2021. 2. 5.
IntelliJ 에서 정규표현식으로 글자 교체하기 (- +\[ \] +[0-9]{1,}\.) $1 $1, $2 이런식으로 교체하려는 문자의 텍스트를 가져올 수 있다. 2021. 1. 28.