New
-
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.06.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.01.12
-
[Java] MS949(CP949)와 EUC-KR은 다르다
MS949(CP949)와 EUC-KR은 다르다 요새 대부분 UTF-8을 사용해서 MS949, EUC-KR 등을 잘 사용하지 않는다. (ASCII, ISO-8859-1 등) 하지만 레거시에서는 EUC-KR을 사용하는 경우가 꽤 있는데, 이번에 레거시에서 작업하면서 발생한 문제가 있었다. 레거시 DB는 인코딩을 us7ascii 을 사용하고 있었고, 웹은 EUC-KR로 뿌리고 있었고, 그 중간과정을 MS949로 인코딩해서 던져주었다가, EUC-KR로 변경했는데 표시못하는 한글이 발생하기 시작했다. 가만히 있는 MS949를 왜 EUC-KR로 바꾸었냐면.. 둘이 같은 줄 알았다. EUC-KR과 MS949이 같다고 표현하는 예전?블로그들이 꽤 많았고, 구글링 해가며 개발을 하다보니 그런 지식이 자연스럽게 정립되었는..
2023.09.27
-
[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.03.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.02.23
Best
-
[Spring] Spring의 @EventListener
Spring의 @EventListener 쓰는 이유? 의존성이 강한 로직들의 레이어를 분리할 수 있습니다. 예를 들어 A 서비스의 a 비즈니스 로직을 실행 할 때 B 서비스의 b 추가 로직을 같이 실행해야 하는 경우 A 서비스에 B 서비스를 주입시켜 a 로직 안에 b 로직을 녹이는 경우가 많습니다. 이렇게 점점 강해지는 결합을 이벤트 핸들러라는 레이어로 분리한 뒤 다시 핸들링 하는 느슨한 결합 형태로 만들 수 있습니다. A 서비스의 a 로직 실행 -> 이벤트 발행 -> B 서비스의 b 로직 실행 이렇게 되면 A 서비스는 B 서비스의 변경사항과 관련없이 수정이 필요없게 됩니다. Spring 4 버전 이상으로 올라오며 쓰기가 많이 편해졌습니다. 기존의 이벤트 객체는 ApplicationEvent 와, 이벤트..
2021.04.21
-
[Java] AES-128 양방향 암호화
AES128 양방향 암호화 Github 코드 Hash 암호화와는 다르게 대칭키를 가지고 암호화와 복호화를 진행한다. AES 뒤에 붙는 128이나 192, 256은 대칭키의 bit수를 나타내는 것으로 AES-128의 경우 128bit의 대칭키를 쓰는 암호화 알고리즘이다. 128bit는 16byte이므로, 키의 String length가 16자리이다. (192bit = 24자리, 256bit = 32자리) 키의 길이에 따라서 암호화 라운드의 수만 다르므로 AES-128과 AES-192, AES-256은 구현되는 소스는 같다. 그러나 Java에서는 AES키 길이에 제한을 두기때문에 현재 공식적으로 AES-128밖에 지원하지 않는다. AES-128 이상 사용하려면 JRE의 정책 라이브러리를 갈아 끼우는 방법이 ..
2020.07.05
-
[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.08.07
-
[JAVA] Java Object List 중복제거
Java Object List 중복제거 Github 소스 Java8 이상의 Collections에는 Stream API 사용 시 distinct라는 중복 제거 메소드가 있다. Stream API의 distinct 메소드는 Object 의 equals 로 비교하므로 객체 자체가 같은지를 비교한다. 따라서 리터럴 형태의 String을 인자로 갖는 List등은 비교가 가능한데, Dto 형태의 모델은 비교가 안되며 Object 자체도 같은 주소값을 가지는 경우에는 가능한데 안의 속성을 비교해야 하는 경우 비교가 어렵다. 이런 경우 사용 할 수 있는 Utils 클래스이다. 아래 학생 정보를 담는 클래스가 있다고 하자 Dto Class 예 @Data public class StudentInfo { private l..
2021.01.04
-
[Mybatis] mybatis 사용 시 xml, interface 경로가 일치해야 하는 문제
mybatis 사용 시 xml, interface 경로가 일치해야 하는 문제 springBoot에서 mybatis-spring-boot-starter 를 이용할 때 Data Access Object를 구현하지 않고 인터페이스 자체로 매핑되어 Data Access Object로 이용하는 방식이 있습니다. 하지만 이 방식에서 쿼리 메소드를 가지고 있는 인터페이스 파일과 실제 쿼리문이 담긴 XML 파일의 경로가 같아야 한다는 문제가 있습니다. 예를들어 인터페이스 파일의 패키지 경로가 sunghs.springexample.mapper.SampleMapper 라고 한다면, XML 파일의 경로도 sunghs.springexample.mapper.SampleMapper 이어야 한다는 문제 입니다. (프로젝트 경로로 ..
2021.12.02