[Spring] DB 개인정보 암호화 시스템 구축기: AES‑256‑GCM + Blind Index
·
Spring Framework/Spring & Spring Boot
사이드 프로젝트에서 전화번호, 결제 정보 등 민감 데이터를 다루면서 DB 암호화의 필요성을 느꼈다. 단순히 암호화만 하면 되는 줄 알았는데, 검색은 어떻게 하지? 마이그레이션은? NestJS 서버와 같은 DB를 쓰는데 호환은? 하나씩 해결해 나간 과정을 정리한다. 들어가며개인 프로젝트를 진행하다 보면 전화번호, 빌링키 같은 민감한 데이터를 DB에 저장해야 하는 순간이 온다. 개인정보보호법이나 정보통신망법을 따져보면 양방향 암호화가 필수인 항목들이 꽤 많다. 공부 삼아 직접 암호화 모듈을 설계하고 구현해 봤는데, 생각보다 고려할 것이 많았다.특히 이런 문제들이 까다로웠다:검색 불가: AES-GCM은 랜덤 IV를 사용하므로 WHERE phone = ? 검색이 안 된다기존 데이터 전환: 이미 저장된 평문 데이..
[Spring Batch] Spring Batch 6 도입 중 Chunk 기반 처리 버그 디버깅 및 6.0.1 패치 적용
·
Spring Framework/Spring Batch
1. 들어가며배치 서버 신규 이관 작업을 진행하면서 Spring Batch 6 버전을 도입하였다. Spring Boot 3.x, Java 21 환경을 기준으로 배치 서버를 구성하는 상황이었기 때문에, Spring Batch 역시 최신 메이저 버전을 사용하는 것이 자연스러운 선택이었다. 하지만 이관 과정에서 Chunk 기반 Step이 정상적으로 동작하지 않는 문제를 발견하게 되었고, 해당 문제를 디버깅한 결과 애플리케이션 구현이 아닌 프레임워크 버그임을 확인하게 되었다. 이 글은 Spring Batch 6 도입 과정에서 만난 버그를 어떻게 인지하고, 공식 이슈를 통해 확인한 뒤, 최종적으로 패치 버전을 적용하여 해결한 과정을 정리한 기록이다.2. 중점적으로 봐야 하는 내용Spring Batch 6에서 Ch..
[Spring Batch] JdbcPagingItemReader 정리
·
Spring Framework/Spring Batch
1. 개요JdbcPagingItemReader는 keyset 기반 페이징 방식을 통해 데이터를 일정 단위로 나누어 읽는 ItemReader이다.마지막으로 처리한 위치를 기준으로 다음 데이터를 조회하며, 이는 JdbcCursorItemReader와 구조적으로 완전히 다른 접근 방식이다.JdbcPagingItemReader 역시 AbstractItemCountingItemStreamItemReader의 구현체이지만,커넥션 관리, 장애 복구, 처리 단위 측면에서 Cursor 방식과는 근본적인 차이가 있다.2. 초기화 과정 (doOpen)JdbcPagingItemReader는 AbstractPagingItemReader를 상속하며, Step 시작 시 doOpen() 메서드를 통해 초기화를 수행한다.이 단계에서 ..
[Spring WebFlux] 왜 WebFlux를 선택했는가? (Tomcat NIO와 비교)
·
Spring Framework/Spring & Spring Boot
들어가며티켓팅 프로젝트에서 Spring WebFlux를 사용했다는 이야기를 하면 종종 이런 질문을 받습니다.“톰캣도 NIO를 지원하는데, 굳이 WebFlux를 선택한 이유가 뭔가요?” 저도 처음에는 “어차피 둘 다 non-blocking이면 큰 차이가 없지 않을까?” 라고 생각했지만, 실제로 비교해보면 철학과 활용 범위에서 확실한 차이가 있었습니다. 이번 글에서는 WebFlux와 Tomcat NIO를 비교하며 WebFlux를 선택한 이유를 정리해 보겠습니다.아키텍처의 차이Tomcat NIOServlet API 기반으로 동작필터 체인, Request/Response 객체 등 서블릿 스펙의 제약 존재WebFluxReactive Streams 표준 기반Netty 같은 이벤트 루프 서버에 최적화서버-프레임워크-..
[Spring Batch] 동일한 Job과 Step이 반복 실행되지 않는 문제
·
Spring Framework/Spring Batch
목차# 문제티켓팅 프로젝트에서 배치 잡을 구현하면서 다음과 같은 예외를 마주하였다.java.lang.IllegalStateException: Failed to execute ApplicationRunner ...Caused by: org.springframework.batch.core.repository.JobExecutionAlreadyRunningException: A job execution for this job is already running: # 원인스프링 배치는 기본적으로 잡과 스텝의 상태를 저장하고 이에 기반하여 잡과 스텝의 실행을 1번 만 수행할 수 있도록 보장한다. 배치 잡이 실행되면 JobInstance가 생성된다. 이때 JobInstance는 잡의 논리적 실행을 나타내며 두 가지 ..
[Spring Batch] @EnableBatchProcessing 적용시 배치 잡이 동작하지 않는 문제
·
Spring Framework/Spring Batch
목차# 문제 티켓팅 프로젝트를 개발하면서 Spring Batch를 이용하여 배치 잡을 구현했다. 배치 잡을 구현하면서 배치 서버 기동 시 헬스체크 테스트를 위한 배치 잡을 구현하였는데, @EnableBatchProcessing 어노테이션을 configuration 클래스에 적용했음에도 기본 잡이 실행되지 않는 문제가 발생하였다. 테스트 배치 잡의 경우 프로젝트에서 필요한 기능은 아니었기 때문에 중요한 문제는 아니었지만, 왜 동작하지 않았는지에 대해서 간단하게 정리해보고자 한다. # 원인 문제의 원인은 SpringBoot 3.0 부터 DefaultBatchConfiguration 클래스 혹은 EnableBatchProcessing 어노테이션을 선언할 경우 배치 잡의 자동 실행하는 것을 제한하는 로직이 추가..
[Redisson] SpringBoot + Redisson을 활용한 동시성 문제 해결하기
·
Spring Framework/Spring & Spring Boot
목차 들어가며 SpringBoot를 기반으로 실시간 투표 애플리케이션을 구현하면서, 한 가지 실험을 수행했다. 멀티 스레드 환경에서 다수의 클라이언트 요청이 동시에 하나의 글에 투표를 진행하면 정상적으로 동작할 수 있을까? 실험의 시나리오는 다음과 같다. [상황] 찬성 투표가 100개인 투표 글이 있다. 찬성표를 반대표로 변경하기 위한 업데이트 요청을 동시에 100번 수행한다. [예상 결과] 투표 글의 찬성 투표수는 0이 된다. 투표 글의 반대 투표수는 100이 된다. 시나리오 테스트 코드를 작성한 결과, 예상한 결과와는 다른 결과를 얻을 수 있었다. 문제 정의 테스트를 수행하면서 마주한 문제는 멀티 스레드 환경에서 접할 수 있는 동시성 문제이다. 애플리케이션은 스프링부트를 기반으로 구현되었고, 내장 톰..
[SpringBoot / ERROR] @RequestParam 예외: Name for argument of type [java.lang.String] not specified, and parameter name information not available via reflection.
·
Spring Framework/Spring & Spring Boot
목차 프로젝트를 수행하면서 우연히 질문을 받게 되었다. @RequestParam에 value 속성을 지정하지 않으면 예외가 발생하는가? -sky- 기본적으로 @RequestParam과 @PathVariable은 request의 파라미터와 매개변수의 이름이 동일하다면, value 속성을 생략할 수 있다. 또한 @RequestParam 어노테이션도 생략할 수 있다. 그렇기 때문에 당연하게 발생하지 않고, 매개변수의 이름과 파라미터의 이름이 같다면 어노테이션도 생략할 수 있다고 답했다. 하지만 당연하다고 생각했던 것이 예외를 발생시켰다. 예외를 발생시킨 코드는 아래와 같다. @GetMapping("/login") public ResponseEntity getPostByParam(@RequestParam Str..