이 내용은 baeldung의 querydsl 내용을 정리한 글이다. (https://www.baeldung.com/intro-to-querydsl) Querydsl의 목적 ORM 프레임워크는 엔터프라이즈 자바의 핵심이다. 이것은 객체지향과 관계형 데이터베이스 모델과의 간극을 좁혀주는 역할을 한다. 또한 개발자로 하여금 더 깨끗하고 더 정교하게 퍼시스턴스 코드와 도메인 로직을 작성하게 도와준다. 하지만 ORM 프레임워크에서 가장 어려운 디자인 요소 중 하나는 올바르고 타입 안정성(type-safe)있는 쿼리를 작성하는데 있다. JAVA ORM 프레임워크 중 가장 널리 사용되는 것 중 하나인 Hibernate는 문자열 기반 쿼리 언어인 HQL(JPQL)을 사용한다. 가장 확실한 단점은 타입 안정성이 부족하고..
이 글은 아래 링크를 정리한 자료이다. https://www.baeldung.com/spring-events 1. 개요 스프링 이벤트는 스프링에서 많은 주목을 받지 않는 것 중 하나이지만 가장 유용한 기능 중 하나이다. 스프링에서 제공하는 많은 기능을 가진 ApplicationContext에서 제공하는 기능 중 하나이다. 여기서 지켜야할 몇 가지 규칙이 있다. 이벤트 클래스는 스프링 프레임워크 4.2 이전 버전을 사용한다면 ApplicationEvent를 확장해야 한다. 4.2부터는 더 이상 ApplicationEvent를 확장할 필요가 없다. 퍼블리셔는 ApplicationEventPublisher를 주입(inject)해야 한다. 리스너는 ApplicationListener 인터페이스를 구현해야 한다...
썸네일 변환 작업을 하다가 skija 라는 라이브러리를 사용하게 되었다. 이 라이브러리는 os별로 사용하는 라이브러리가 다르다. 그래서 os에 맞는 dependency를 걸어줘야 한다. skija는 skia를 java로 바인딩을 해주는 역할을 하는데 내부적으로 os에 따른 최적화 작업이 다르다. Skija dependency 지금 사용하려는 platform도 위의 4가지를 모두 사용해야 하는 상황이다. 그래서 maven에서 할 수 있는 방법을 찾아보니 아래와 같이 사용하면 profile에 os와 arch에 맞게 설정할 수가 있다. pom.xml platform-mac-m1 mac aarch64 org.jetbrains.skija skija-macos-arm64 0.93.6 platform-mac-inte..
1. Future Future는 비동기 연산의 결과를 나타낸다. 연산작업이 완료되었는지, 대기하는지를 체크하는 메소드들이 있다. 응답 결과는 연산이 완료되었을 때 get 메소드를 사용하여 조회될 수 있고 필요하다면 블로킹을 할 수도 있다. 작업 취소는 cancel 메소드를 통해 수행될 수 있다. 작업이 정상적으로 완료되었는지? 취소되었는지 체크하는 메소드들도 제공된다. 연산 작업이 완료되면 취소는 될 수 없다. 아래에서 기본적인 Future의 동작 샘플 코드를 한번 보자. 1.1 async - 비동기 실행 1.2 isDone - 작업 완료상태 1.3 cancel - 작업을 취소 1.4 invokeAll - 모든 작업 완료 1.5 invokeAny - 하나의 작업 완료 1.1 async @Test publ..
이미지 썸네일을 만드는 방법에는 여러가지가 있다. 자바가 아닌 라이브러리도 많이 있지만 호환성이나 특정 설치프로그램이 필요한 경우가 있어서 여기서는 자바로 생성하는 방법만 알아본다. 1. 썸네일 라이브러리 Java 코어를 이용 java.awt.Graphics2D Image#getScaledInstance 라이브러리 이용 Imgscalr Thumbnailator Marvin Skija Metadata 추출 (Thumbnail) Metadata Extractor - 이미지 파일에서 썸네일 정보 추출 1) java.awt.Graphics2D Graphics2D는 2차원의 Shape, text, image를 렌더링하는 기본 클래스이다. 사용법 public static BufferedImage resizeImag..
파일시스템 변경을 감지해야 할 경우가 있다. 특정 디렉토리에 파일 변경(추가/삭제/수정)이 발생한 경우를 주기적으로 모니터링 해야 하는 경우이다. 기본적으로 아래의 두 가지 방법이 있다. WatchService 사용 Apache Commons IO Monitor 라이브러리 사용 1. WatchService 동작 방식 WatchService를 사용하는 첫 번째 단계는 java.nio.file.FileSystem 인스턴스를 생성하는 것이다. WatchService watchService = FileSystems.getDefault().newWatchService(); 그 다음 모니터링 할 디렉토리 경로를 만들자. Path path = Paths.get("pathToDir"); 이 단계 이후에 Standard..
1. 쓰레드 풀 (Thread Pool) 자바에서, 쓰레드는 운영체제 리소스인 시스템 수준의 쓰레드와 관련이 있다. 만일 무분별하게 쓰레드를 생성한다면, 빠르게 리소스 고갈을 만나게 될 것이다. 운영체제는 병렬 수행을 위해 쓰레드 간 컨텍스트 스위칭(context switching)을 한다. 간단히 생각하면, 쓰레드를 더 많이 생성할수록, 쓰레드가 실제 하는 작업 시간은 줄어들게 된다. 쓰레드 풀(Thread Pool) 패턴은 멀티쓰레드 애플리케이션에서 리소스를 절약하는데 도움을 주고 사전에 정의된 수를 제한하여 병렬성을 유지할 수 있게 한다. 쓰레드 풀을 사용할 때, 병렬 작업의 형태로 동시성 코드를 작성하고 쓰레드 풀 인스턴스에서 실행한다. 이 인스턴스는 작업을 실행하는데 여러 개의 쓰레드를 재사용하..
jpa를 사용할 때 기본적으로 SQL 로그가 표시되지 않는다. 그래서 SQL 출력을 위해 설정을 해주면 표시가 되는데 조금 불편하다. 이를 위해 P6Spy를 사용하면 우리가 원하는 형태로 표시가 되는데 그 내용을 한번 알아보자. SQL 로그를 찍기위한 테스트 케이스를 작성해보자. 테스트 케이스 작성 @Test void test() { userService.register(new User(1, "홍길동")); User user = userService.find(1); } userService를 등록하고 조회하는 테스트를 만들고 실행하면 insert와 select가 실행이 될텐데 해당 SQL이 표시되지 않는다. 로그 표시 spring.jpa.show-sql: true를 하면 기본 로그가 표시가 된다. Hib..
spring boot 라이브러리 dependency 확인하는 방법 Spring boot를 사용하다 보면 특정 spring boot에서 어떤 버전의 라이브러리를 사용하는지 궁금할 때가 있다. 물론 spring boot에서 알아서 지정해주지만 특별한 경우는 찾아봐야 할 경우가 있다. 그런 경우는 아래 방법대로 찾아가면 된다. 1. https://spring.io/ 로 접속 2. project > spring boot 선택 3. 해당 버전의 Reference Doc.을 선택 4. Dependency Version를 선택 5. 여기서 찾으려고 하는 라이브러리를 groupId나 artifactId로 검색하면 된다.
@Transactional(readOnly = true)는 트랜잭션을 사용할 때 읽기 전용으로 사용하겠다는 의미이다. readOnly로 사용 시 아래와 같은 장점이 있다고 한다. 장점 JPA를 사용할 경우 변경감지를 수행하지 않아 성능상 이점을 가져올 수 있다. mysql 이중화 구성(master/slave)를 사용할 경우 readOnly를 사용할 경우 slave를 자동으로 호출해줘서 DB 부하를 줄여줄 수 있다. 읽기 가독성 증가 (의도적으로 읽기 전용으로 사용하겠다고 명시) transactionId를 부여되지 않아 오버헤드를 줄일 수 있다. 여기서 readOnly 사용을 할 때 몇 가지 궁금점이 생겼다. 1) @Transactional(readOnly = true)일 때 수정작업(update)을 하면..
전체 중 상위 10개 확인하기 ps -eo user,pid,ppid,rss,size,vsize,pmem,pcpu,time,cmd --sort -rss | head -n 11 top 명령어로 메모리 확인 top 명령어 실행 후 shift + m 으로 메모리 사용량을 정렬하여 확인
openfeign을 사용할 때 header에 값을 추가하여 전달하는 방법이다. 1. Header의 값이 1개 header가 1개일 경우는 아래와 같이 headers에 추가하려는 name=value 형식으로 넣으면 된다. @FeignClient(name = "userClient", url = "http://localhost:8080") public interface UserClient { @RequestMapping(value = "/users/1", method = RequestMethod.GET, headers = "header1=value1") User find(); } 실행 결과 [nio-8080-exec-1] com.example.feign.UserClient : [UserClient#find] ..
1. 개요 Hibernate로 Spring Data JPA를 사용할 때, @DynamicUpdate와 같은 추가적인 특징을 사용할 수 있다. @DynamicUpdate는 JPA 엔터티에 적용될 수 있는 클래스 수준의 어노테이션이다. 이는 변경된 컬럼에 대해서만 업데이트할 수 있는 구문을 만들어낸다. 2. JPA @Entity 애플리케이션이 시작될 때 Hibernate는 CRUD에 대한 SQL 구문을 만들어낸다. 이 SQL 구문은 한번 생성되어 성능 향상을 위해 메모리에 캐싱된다. 생성된 SQL 업데이트 구문은 엔터티의 모든 컬럼을 포함한다. 엔터티를 업데이트 하는 경우에, 수정된 컬럼의 값은 SQL 업데이트 구문에 전달된다. 업데이트 되지 않는 컬럼의 경우에는 Hibernate에서 업데이트를 위해 기존 ..
개요 스프링 부트 애플리케이션 시작 시 특정 테이블을 생성하거나 데이터를 초기화 하는 스크립트를 실행하고 싶은 경우가 있다. spring data jpa를 사용하는 경우는 repository를 생성하여 특정 테이블이 자동생성되게 할 수도 있지만 그렇지 않은 경우는 아래 방법을 사용하면 된다. schema.sql : DCL 스크립트 (테이블 생성) data.sql : DML 스크립트 (데이터 생성, 수정, 삭제) schema.sql과 data.sql로 구분한 것은 관례적으로 테이블 생성과 데이터 생성으로 분리한 것이지 반드시 그렇게 실행되는 것은 아니다. data.sql에 DCL 스크립트가 있어도 테이블 생성이 된다. 하지만, 여러가지가 혼재되어 있으면 보기 어려우니 그 목적에 맞게 구분하여 모아두는 것이..
intellij를 사용할 때 pom.xml에 dependency를 추가할 때 의존성이 자동완성이 되어 편하게 사용할 수 있다. 그런데 어느날 자동완성이 되지 않아서 항상 의존성을 찾아서 붙여야 하는 불편함이 있다. 그래서 해결방법을 찾아보니 repository update를 해주면 된다고 되어 있다. IDE 의존성 추천은 maven repository의 인덱싱 기반으로 동작한다. remote repository의 경우는 index정보를 다운로드 받아서 자동완성 시 사용한다. setting에서 update repository를 사용해서 갱신할 수 있다. Build, Execution, Deployment | Build Tools | Maven | Repositories settings.
1. 개요 actuator는 스프링 부트 애플리케이션의 모니터링이나 메트릭 기능을 HTTP와 JMX의 엔드포인트를 통해 제공한다. 사용하는 방식은 spring-boot-starter-actuator 의존성을 추가하는 것이다. Maven 프로젝트에서는 아래와 같이 추가할 수 있다. org.springframework.boot spring-boot-starter-actuator 2. Endpoints 기술에 구애받지 않는 공통적인 enpoint ID Description auditevents 현재 애플리케이션의 audit event 정보를 노출한다. AuditEventRepositoryBean이 필요하다. beans 애플리케이션 내의 모든 스프링 빈의 목록을 표시한다. caches 사용 가능한 캐쉬를 노출한..
아래의 경우처럼 두 개의 Thread가 동시에 공유 변수에 값을 저장하고 조회하는 경우가 있다. 시간의 차이로 인해 값의 내용이 원하는 결과로 조회되지 않는다. 아래의 테스트 케이스를 한번 보자. public class ThreadLocalTest { @Test public void test() throws InterruptedException { User user = new User(); Thread thread1 = new Thread(() -> { user.setName("hong_1"); sleep(1000); System.out.println("thread1 user: " + user.getName()); }); Thread thread2 = new Thread(() -> { sleep(500)..
intellij에서 key promoter x를 설치하면 사용하는 기능에 대한 단축키를 표시해준다. 아래는 자주 사용하는 단축키를 모아둔 것이다. 단축키 ⌘ - command ⇧ - shift ⌥ - option ⌃ - control ↩ - return fn - function ↑ ↓ → ← arrow 단축키 설명 ⌘1 project 이동 ⌘2 bookmark 이동 ⌘8 services 화면 이동 ⌘9 git 화면 이동 ⌘E 최근 수정 파일 보기 ⌘/ 주석으로 처리 ⌘D 중복 라인 생성 ⌘D (git tool) git diff ⇧⌘↩ 구문 완성 ⇧⌘N scratch 파일 생성 ⌥⌘↩ 포맷팅 ⇧⌘V 클립보드에서 붙여넣기 Esc 에디터 화면으로 이동 ⌥F12 terminal ⌃⇧F12 close all to..
테스트 케이스 작성 시 여러 Thread를 사용하는 경우가 있다. 여러 Thread가 실행되기 전에 테스트 실행이 끝나버리는 문제가 있는데 어떻게 해결할 수 있는지 알아보자. 예제 코드 public class CountDownLatchTest { static class UserThread extends Thread { private String id; public UserThread(String id) { this.id = id; } @Override public void run() { User user = new User(); user.register(id); } } static class User { public void register(String id) { try { Thread.sleep(100..
일반적인 서비스 로직을 작성할 때 메소드 내에서 복잡한 서비스 로직을 수행하고 이벤트(kafka)를 발행하는 경우가 많다. 이런 경우 트랜잭션이 성공적으로 완료된 이후에 이벤트가 발행되기를 기대하지만 로직 내의 실행 순서에 따라 의도하지 않게 이벤트가 발행이 되는 경우도 있다. 그래서 스프링에서는 트랜잭션을 종료하고 이벤트를 발행하는 방법으로 @TransactionalEventListener를 사용을 한다. @TransactionalEventListener를 사용하게 되면 트랜잭션이 종료된 이후에 이벤트를 발행하는 것이기 때문에 이벤트 발행시점을 트랜잭션 이후로 미룰 수 있는 장점이 있다. 하지만, 여기서는 @TransactionalEventListener를 사용하지 않고 kafka 트랜잭션과 DB 트랜..
* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.