본문 바로가기
  • Code Smell

Framework45

[Spring] 커스텀 어노테이션 스캔하기 (Scan Custom Annotation) 커스텀 어노테이션 스캔하기 (Scan Custom Annotation)마커 인터페이스와 비슷한 기능으로 커스텀으로 마커 어노테이션도 만들 수 있다.또는 기능이 담긴 어노테이션을 만들 때, Aspect를 이용해 특정 어노테이션이 붙은 클래스나, 메소드를 weaving 할 수 있게 만들 수 있다.그런데 이 방법은 커스텀 어노테이션이 어느 클래스에 붙어있는지 특정할 수 있어야 하는데, (해당 클래스나 메소드가 호출 될 때 등)특정 할 수 없다면 모든 클래스를 대상으로 특정 어노테이션이 붙어있는지 검사하는 방법밖에 없다.이러한 기능이 필요한 케이스를 예를 들면 다음과 같다.특정 어노테이션이 붙은 클래스들을 알고 있어야 할 때특정 어노테이션이 붙은 클래스가 특정 타입의 인터페이스, (추상)클래스를 상속했는지 검사.. 2024. 11. 25.
JAVA21 전환기 JAVA21 전환기자바21이 2023년 9월경 출시되었다. 그리고 자바21을 지원하는 Spring Boot 3.2가 2023년 11월쯤 릴리즈 되었고 자바21에 대한 오류보고나 스프링 3.2에 대한 깃허브 이슈들을 찾아본 뒤, 적용하는데에 큰 이슈가 없을 것으로 판단해 2024년 1월경 자바21로 전환하기로 결정했다.회사는 지금 MSA 구조로 자바11을 사용중인데, 적은 리소스로 많은 트래픽을 담당하기 위해 블로킹 IO를 담당하는 MVC 프로젝트와 인터페이스 및 동시성 처리를 위한 webflux 프로젝트로 분리되어 있다.즉 공식적인 Reactive IO 를 지원하지 않는 (redis, mongodb 등 대부분은 요즘 지원하지만..) 오라클(R2DBC는 공식이 아니라 제외했다.) 등을 사용하려면 MVC 프.. 2024. 6. 19.
[spring] Stream, Future 사용시 주의해야 할 점 (커넥션 풀이 남는 이슈) Stream, Future 사용시 주의해야 할 점 (커넥션 풀이 남는 이슈) 얼마 전 코드에서 Stream 을 수행하면서 그 안에 DB 를 조회해서 데이터를 가져오는 로직이 있었는데, 트래픽이 많은데도 불구하고, 커넥션을 다 사용하지 못했다. 환경과 증상은 이러했다. 서버는 spring boot의 Hikari Connection Pool 사용함 min, max connection은 동일하게 20개로 설정 하지만 APM으로 확인 시, 실제 사용되는 커넥션은 9개였고, 노는(idle) 커넥션이 11개정도 였다. 트래픽이 몰리는 순간에도 hikaricp_connections_acquire_seconds_sum, hikaricp_connections_pending 수치만 증가할 뿐 idle 커넥션은 일정하게 8.. 2024. 1. 12.
[Spring] Spring AOP 사용시 주의 점 Spring AOP 사용시 주의 점 Spring AOP는 기존에 JDK Dynamic Proxy 를 사용하다가, Spring boot 2.0, Spring framework 4.3 에 올라와서 기본 프록시 라이브러리로 CGLib을 사용한다. 뭐가 다른거지 JDK Dynamic Proxy 와 CGLib 의 가장 큰 차이는 프록시 대상 객체가 인터페이스를 구현했느냐 여부이다. 신입 시절에 백엔드를 개발하다보면 회사 코드가 Service-ServiceImpl 로 구현되어 있었는데, 이게 Loose Coupling을 해결하기 위한 것인가 보다 했으나, 다형성을 위해 구현되는 경우가 거의 없었다. (interface : class = 1 : N 이 거의 없고 대부분 1 : 1) 아마 JDK Dynamic Prox.. 2023. 3. 31.
[Spring Boot Batch] Chunk Multi Thread 처리 시 Thread 분배 문제 (1 reader multiple writer) Spring Batch Multi Thread 처리 시 Thread 를 최대한 이용한다 (1 reader & multiple writer) 일반적으로 Thread-safe 한 PagingItemReader를 사용하면서, ItemProcessor, ItemWriter를 사용하며 Multi-Thread 처리를 할때 다음과 같이 생각하게 됩니다. ThreadPoolTaskExecutor 에서 꺼낸 1개의 worker 가 Reader-Processor-Writer 처리를 다 할 것이다. 즉, ThreadPoolTaskExecutor 에서 생성 된 1개의 worker 가 CHUNK SIZE 만큼 DB를 읽어 현재 worker 가 process, write 를 같이 할 것이라고 생각합니다. 하지만 다른 결과가 나옵.. 2023. 2. 23.
[Spring redis] value 에 큰 따옴표 (double quote) 한번 더 들어가는 문제 Redis 큰 따옴표 (더블 쿼테이션) 한번 더 들어가는 문제 업무를 진행하다가 아래와 같은 형태로 묶인 데이터를 한번에 가져와야 할 일이 있었습니다. 데이터는 레디스에 있고, 해시셋(HashSet) 형태로 그룹핑 되어 있습니다. 레디스 내부 데이터 구조 GroupA - data1 - data2 - data3 GroupB - data4 - data5 - data6GroupA 와 GroupB 는 각각 해시셋 구조입니다. 그 밑에 data 를 멤버로 가지고 있습니다, 그리고 각각의 그룹 데이터의 세부적인 사항은 key-value 형태로 가지고 있었습니다. data1 - value1 data2 - value2 data3 - value3 ...데이터는 그룹은 약 20개 정도 되며, 한개의 그룹에는 보통 멤버가 .. 2023. 1. 19.
[Spring] ActiveProfiles 와 spring.profiles.active 가 일치하지 않는 현상 (ActiveProfiles & spring.profile.active does not match) @ActiveProfiles 와 spring.profiles.active 가 일치하지 않는 현상 테스트코드를 작성할 때 profile 주입을 위해서 아래와 같이 주입하고는 했습니다. 그런데 뭔가 이상한 현상을 발견했는데, 사내 프로젝트 소스에서 profile 에 따른 통합 테스트 진행 시 의도한 바와 같이 진행되지 않는 걸 발견했습니다. 테스트 1) application.yml 프로퍼티 로드 application.yml 에는 profile에 따라 프로퍼티를 override 합니다. 즉 default profile 로 작성된 프로퍼티를 가져오고, 그 뒤 세팅한 profile 값으로 덮어 씌우는 방식입니다. 그래서 아래처럼 테스트를 진행했습니다. 그리고 테스트 프로퍼티를 가져 올 bean을 작성합니다. 그리.. 2022. 8. 7.
[Spring] 동적으로 Bean 생성 또는 개입하기 (Dynamic Bean Create, BeanPostProcessor) 동적으로 Bean 생성 또는 개입하기 (Dynamic Bean Create, BeanPostProcessor) application yml 에 List 형태로 어떤 프로퍼티를 추가하거나 했을 때 추가적으로 Bean 생성 메소드를 만들지 않아도, 자동으로 만들어 놓게 할 수 있습니다. 스프링에서는 개발자가 직접 지정한 Bean을 만들기 전에, 만들어지는 중에, 만들어진 후에 개입 할 수 있도록 추상체를 제공하고 있습니다. 즉 어떤 시점에 개입해서 추가 로직 처리를 할지 (= 추가적인 bean 을 생성할지) 추상체를 구현하기만 하면 되고, 그걸 ApplicationContext 에 등록하면 ApplicationContext는 알아서 구현체를 찾아 적절한 시점에 후킹해 줍니다. BeanPostProcessor.. 2022. 6. 23.
[Spring] 파라미터 바인딩을 해주는 HandlerMethodArgumentResolver (Webflux Version) 파라미터 바인딩을 해주는 HandlerMethodArgumentResolver (Webflux Version) 예제는 mvc 포스팅과 동일합니다. 모델과 서비스는 동일하게 되어있다고 간주하고 진행합니다. webflux에서 다른부분만 따로 포스팅 합니다. MVC 포스팅 먼저 webflux 에는 HandlerInterceptor가 존재하지 않습니다. 설계 컨셉에 맞지 않아 Interceptor의 역할을 WebFilter에 등록해주어야 합니다. 또한 Webflux에서는 WebFilter 뿐만 아니라 HandlerFilterFunction 으로 RouterFunction의 endpoint 별로 부분적으로 필터 제한이 가능하게 하는 추상체가 있습니다. 하는 역할은 WebFilter와 동일하지만, WebFilter.. 2022. 6. 20.