하루라도 AI를 사용하지 않으면 손가락에 가시가 돋는다.

이미지
안녕하세요, 하마연구소입니다. ChatGPT라는 LLM 기반의 AI 서비스가 나오면서 저의 코딩 습관도 변하고 있습니다. 기존에는 막히는 코딩을 해결하기 위하여 구글이나 포털에서 단순 검색하여 나와 동일하거나 비슷한 상황을 찾았고, 그 찾은 게시글에서 해결방법이 있으면 막힌 것을 푸는것이고 아니면 다시 또 검색을 하였습니다. 그러나 이제는 그냥 물어봅니다. ChatGPT에게...아니면 개발툴에 연동된 Copilot이 도움을 줍니다. 월 몇 십 달러짜리 비서가 항상 대기하고 있는거죠. 이제는 ChatGPT를 사용하는 것이 너무나 자연스러우며기존처럼 구글링하는 빈도가 현저하게 줄었습니다. 포털 검색이 없으면 인터넷 사용하기 힘든 것처럼이러다가 AI 없으면 코딩을 못하는 날이 다가올지도 모르겠네요. AI 시대에 어떻게 살아남도록 대비해야할지? AI를 어찌하면 잘 활용할지? AI 활용하여 생산성과 품질을 높이는 것이 대비하는 것인지? 많은 고민이 듭니다. 감사합니다. 

spring-data-jpa에서 AbstractAuditable을 이용한 audit 남기기

이미지
안녕하세요, 하마연구소 입니다. spring-data-jpa에서 entity의 CUD 이력을 남기기 위한 audit 기능을 제공해줍니다. 몇몇 설정한하면 아주 편리하죠. https://docs.spring.io/spring-data/jpa/reference/auditing.html Auditing :: Spring Data JPA Overview Spring Boot Spring Framework Spring Cloud Spring Cloud Data Flow Spring Data Spring Integration Spring Batch Spring Security View all projects Audit 데이터는 보통 생성자(createdBy), 생성일시(createdDate), 수정자(lastModifiedBy), 수정일시(lastModifiedDate)를 기록하며, 아래와 같이 추상클래스로 정의하여 사용하기도 합니다.     1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @MappedSuperclass @EntityListeners (value = [ AuditingEntityListener :: class ] ) @Audited abstract class BaseEntity ( @CreatedBy @Column (nullable = false , updatable = false ) var createdBy : String? = null , @CreatedDate @Temporal (TemporalType.TIMESTAMP) @Column (nullable = false , updatable = false ) var createdDate : Instant? = null , @LastModifiedBy @Column (nullable = f...

갤럭시워치 화면, 제가 원하는 것을 만들고 있습니다.

이미지
안녕하세요, 하마연구소 입니다. 저는 갤럭시워치를 사용하고 있습니다. 이유는? 휴대전화가 갤럭시이기 때문이죠. 만족스럽지 않은 것도 있지만 나름 잘 활용하고 있습니다. 그런데 시계화면이 저에게 딱 맞는 것이 없어서, 기본 페이스로 이것저것 조절해가며 아쉬운데로 사용하고 있습니다. 스토어에서도 만족 할만한 것은 아직 못찾았고요. 그래서 만들기로 했습니다. 생각보다 어렵지 않네요. 삼성에서는 Watch Face Studio 라는 개발툴을 제공해줍니다. 그리고 가이드도 있고요. https://developer.samsung.com/watch-face-studio/ko/overview.html 제가 원하는 시계화면은 복잡한 것이 아니기 때문에, 워치 페이스 스튜디오 이용하여 뚝딱뚝딱 만들고 있습니다. 재밌습니다. 완성하면 마켓에도 올려봐야겠네요. 감사합니다.

Java로 HTML 처리는 jsoup이 짱이네요

이미지
안녕하세요, 하마연구소입니다. 요즘 개인 프로젝트를 시작했으며 HTML 파싱이 필요하였습니다. 고민하지도 않고 jsoup을 사용하고 있습니다.역시 부족한거 없이 잘 사용하고 있습니다. https://jsoup.org 과거에 회사에서 HtmlCleaner를 사용했었는데 필요한 기능은 모두 구현하였지만 무엇인가 부족하고 아쉬운 느낌이었습니다. 그러던 중에 jsoup을 경험했는데 완전 신세계였습니다. 너무 쉽고 편하고, 딱 HTML을 다루기에 최적이었습니다. 그러나 HtmlCleaner을 너무 깊게 적용시켜놔서 jsoup으로 변경하기에는 너무 큰 작업이 필요하였습니다. 이후로 HTML을 다뤄야한다면 무조건 jsoup을 사용합니다. 저는 jsoup에서 XPath로 select하는 방법을 많이 사용하는데요, 사용할 때마다 놀랍습니다. 너무 편해서… 다른 라이브러리도 나왔나 검색해보았지만, 딱히 없네요. HTML을 다루기에는 jsoup이면 만족하고 충분합니다. 파싱이나 생성, 최적화 등 HTML을 만져야 한다면 jsoup 믿고 사용해보세요. 감사합니다.

Kotlin의 모든 클래스에서 logger 객체를 편하게 얻을 수 있는 방법

안녕하세요, 하마연구소 입니다. Java에서 프로그래밍 할 때 편의를 위하여 Lombok 을 거의 필수로 이용합니다. 보통 클래스변수의 getter()와 setter()를 자동으로 생성해주는 @Data 어노테이션을 붙이는 것을 많이 사용합니다. 그리고 @Log, @Slf4j 등 logger 객체를 쉽게 얻을 수 있는 기능을 제공하는데, 꽤 유용합니다. 코드가 많이 간단해집니다. Kotlin으로 프로그래밍하면서 이와 같은 logger 객체를 쉽게 얻어주는 라이브러리를 찾아보았지만, 찾지 못했습니다. 최근 Kotlin 버전에서는 Lombok을 공식적으로 사용할 수 있게 되었습니다. (https://kotlinlang.org/docs/lombok.html) 하지만 아직(현재버전 1.5.21) @Log, @Log4j2, @Slf4j 등의 어노테이션은 지원을 하지 않습니다.  아래는 순수하게 Kotlin 코딩으로 간단하게 logger 객체를 얻을 수 있는 방법입니다. Inline function 으로 모든 객체에서 접근가능하도록 정의하였고, reified 키워드를 사용하여 런타임시에도 해당 객체에서 generic type에 접근할 수 있도록 하였습니다. 1 2 3 4 5 6 7 import org.slf4j.Logger import org.slf4j.LoggerFactory /** * 모든 Kotlin 클래스에서 SLF4J의 Logger 객체를 얻을 수 있다. */ inline fun T. logger (): Logger { return LoggerFactory.getLogger(T :: class.java) } Log4j2 객체가 필요하다면 function의 반환값과 구현부분을 살짝 변경하면 되겠죠? 혹시 이 방법말고 또다른 기똥찬 방법 알고 계시면 답글 부탁드립니다. 감사합니다.

[Spring] spring-boot 2.1(SpringFramework 5.1)에서 없어진 기능, JSONP 간단하게 구현하기

안녕하세요, 하마연구소입니다. SpringFramework에서 JSONP 처리를 기본 기능으로 제공하였지만, 스프링부트 2.1(스프링프레임워크 5.1)부터 없어졌습니다. 이미 Deprecated 처리되어 언제가는 없어질 것을 예상했지만, 담당하고 있는 시스템에서는 아직 JSONP가 필요한 상황입니다. 없어진 AbstractJsonpResponseBodyAdvice.java 소스 https://github.com/spring- projects /spring-framework/blob/5.0.x/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java Spring에서는 기본 기능으로 빠졌어도 3rd 파트 라이브러리가 있겠지 싶어 폭풍검색을 했지만 찾을 수 없었습니다. 그래서 그냥 직접 구현하려고 하였지만, 은근히 스프링 코어쪽 소스를 이곳저곳 건드려야하는 복잡함을 느꼈습니다. 그래서 최소한의 소스로 최대한 직관적으로 JSONP를 처리할 수 있도록 구현했습니다. JsonpAdvice.java ControllerAdvice로 request 파라미터에 jsonp 또는 callback이 있으면 JSONP로 처리하기 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import org.apache.commons.lang3.StringUtils ; import org.springframework.core.MethodParameter ; import org.springframework.http.MediaType ; import org.springframework.http...

[Spring] spring-vault에서 @VaultPropertySource 여러개 사용하면 안되는 이유

안녕하세요, 하마연구소 입니다. 스프링 기반의 어플리케이션을 개발할 때, 환경설정으로 보안정보를 다루기 위하여 Vault를 이용합니다. 일반적으로 가장 간단하게 Vault를 이용하는 방법은 @VaultPropertySource 또는 @VaultPropertySources 어노테이션을 사용하는 것입니다. 1 2 3 4 5 6 7 8 9 10 11 12 import org.springframework.context.annotation.Configuration ; import org.springframework.vault.annotation.VaultPropertySource ; @Configuration @VaultPropertySource (value = { "secret/hippolab/wallet1" , "secret/hippolab/wallet2" , "secret/hippolab/wallet3" , "secret/hippolab/wallet4" }) public class VaultConfig { } 위 샘플코드에서는 wallet1, wallet2, wallet3, wallet4에 선언된 모든 환경설정은 어플리케이션 로딩시에 스프링 MutablePropertySources에 포함되어 ${vault.properties1}과 같이 쉽게 사용할 수 있습니다. 그러나 어플리케이션을 만들다보면 여러개의 @VaultPropertySource 어노테이션을 서로 다른 파일에 작성해야할 경우가 있습니다. 이럴때는 아래와 같이 VaultConfig1.java와 VaultConfig2.java 파일에 나눠서 코딩하였습니다. 1 2 3 4 5 6 7 8 9 10 11 12 import org.springframework.context.annotation.Configuratio...