[Spring] DB 개인정보 암호화 시스템 구축기: AES‑256‑GCM + Blind Index
·
Spring Framework/Spring & Spring Boot
사이드 프로젝트에서 전화번호, 결제 정보 등 민감 데이터를 다루면서 DB 암호화의 필요성을 느꼈다. 단순히 암호화만 하면 되는 줄 알았는데, 검색은 어떻게 하지? 마이그레이션은? NestJS 서버와 같은 DB를 쓰는데 호환은? 하나씩 해결해 나간 과정을 정리한다. 들어가며개인 프로젝트를 진행하다 보면 전화번호, 빌링키 같은 민감한 데이터를 DB에 저장해야 하는 순간이 온다. 개인정보보호법이나 정보통신망법을 따져보면 양방향 암호화가 필수인 항목들이 꽤 많다. 공부 삼아 직접 암호화 모듈을 설계하고 구현해 봤는데, 생각보다 고려할 것이 많았다.특히 이런 문제들이 까다로웠다:검색 불가: AES-GCM은 랜덤 IV를 사용하므로 WHERE phone = ? 검색이 안 된다기존 데이터 전환: 이미 저장된 평문 데이..
[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 같은 이벤트 루프 서버에 최적화서버-프레임워크-..
[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..