전체 글 497

[리팩토링] Spring AI 1.0.0-M6 → 1.1.8 업그레이드

Spring AI 1.0.0-M6에서 1.1.8로 업그레이드한 과정 AI 챗봇 리팩토링을 시작하기 전에, 프로젝트에서 사용하고 있던 Spring AI 버전과 의존성 구조부터 점검했다.확인 결과 프로젝트는 GA(정식 출시) 이전 마일스톤 버전인 1.0.0-M6를 사용하고 있었고, 현재 공식 문서와 다른 Starter 이름을 사용하고 있었다.이번 글에서는 Spring Boot 버전은 유지하면서 Spring AI를 1.1.8로 업그레이드한 이유와 변경 내용, 기존 프로젝트와의 호환성을 검증한 과정을 정리한다. 1. 기존 프로젝트의 상태 💡GA 이전 Spring AI 마일스톤 버전을 사용하고 있었다.기존 프로젝트의 주요 버전은 다음과 같았다.Java 21Spring Boot 3.4.4Spring AI 1.0...

Projects/plan-it 2026.09.04

[리팩토링] 재고 API - (4) DB 인덱스 및 캐싱

락을 줄였는데 응답시간은 왜 그대로일까💡락 구간 최적화는 검증했고, 인덱스와 캐싱은 다음에 검증할 후보로 남겼다HubEleven의 재고 차감 API를 리팩토링하면서 분산 락 내부에 있던 상품 조회와 응답 생성을 락 밖으로 옮겼다. k6와 Micrometer로 전후를 비교해 처리량과 평균 응답시간이 개선된 것을 확인했다. 이후에는 DB 조회와 인덱스, 상품 기본 정보 캐싱을 다음 개선 대상으로 검토하기로 했다.다만 현재 결과가 곧바로 “인덱스가 없어서 느리다”거나 “캐시를 넣으면 해결된다”는 뜻은 아니다. 이번 글에서는 실제로 확인한 결과, 그 결과에서 세울 수 있는 가설, 후속 작업에서 확인해야 할 조건을 나누어 정리한다. 인덱스/캐시 적용 후의 개선율은 아직 측정하지 않았으므로 성과로 제시하지 않는다..

Projects/hub-eleven 2026.09.03

[리팩토링] 재고 API - (3) 동시성 처리 최적화

동시성 처리로 인해 생긴 병목 구간 분석💡분산락 적용으로 인해 생긴 문제점HubEleven의 재고 차감 API는 같은 상품에 여러 요청이 동시에 들어와도 재고 수량이 어긋나지 않도록 Redisson 분산 락을 사용한다. 같은 상품의 요청을 한 건씩 처리하면서 정합성은 지킬 수 있었지만, 모든 작업을 락 안에 넣으면 앞 요청이 끝날 때까지 뒤 요청이 기다리는 시간이 길어진다.이번 리팩토링의 목표는 분산 락을 제거하거나 요청을 병렬로 처리하는 것이 아니었다. 재고 수량을 보호하는 데 꼭 필요한 작업만 락 안에 남겨 직렬 처리 구간을 줄이는 것이었다.문제 원인💡상품 조회와 응답 생성까지 락 안에서 실행되고 있었다기존 구조에서는 StockDecreaseProcessor 전체가 분산 락 안에서 실행됐다.락 획..

Projects/hub-eleven 2026.09.02

[리팩토링] 재고 API - (3) 동시성 처리 최적화 : k6 스크립트와 자동화 쉘 스크립트 작성

k6와 Bash로 분산 락 성능 측정 자동화하기💡복잡한 성능 측정 절차 자동화동일 상품의 재고 차감 요청이 동시에 들어왔을 때 Redisson 분산 락이 재고 정합성을 지키는지 확인하고, 락 내부 작업을 줄인 전후의 성능을 비교하고자 했다.k6 스크립트 자체는 한 번의 명령으로 실행할 수 있지만, 개선 전후를 정확히 비교하려면 다음 조건을 매번 동일하게 맞춰야 했다.같은 코드 버전과 락 정책으로 서버를 실행해야 한다.매 실행 전 재고를 동일한 수량으로 초기화해야 한다.웜업을 마친 뒤 본 측정 직전에 Micrometer 스냅샷을 저장해야 한다.동일한 VU와 실행 시간으로 k6 테스트를 실행해야 한다.본 측정이 끝난 뒤 같은 서버 프로세스에서 두 번째 스냅샷을 저장해야 한다.k6 결과와 락 지표, 실제 재..

Projects/hub-eleven 2026.09.01

[트러블슈팅] 재고 API - (3) 동시성 처리 최적화 : k6 자동 측정 스크립트의 jq 문법 오류 해결

k6 자동 측정 스크립트의 jq 문법 오류 해결💡부하 테스트는 완료됐지만 결과 계산 단계에서 오류가 발생했다k6를 이용한 재고 차감 부하 테스트는 정상적으로 완료됐지만, Micrometer 스냅샷과 k6 결과를 조합해 최종 판정을 생성하는 단계에서 jq 문법 오류가 발생했다.jq: error: syntax error, unexpected ifjq: error: May need parentheses around object key expressionjq: 3 compile errors 부하 요청과 측정값 수집은 이미 끝난 상태였고, JSON 결과를 계산하는 jq 코드만 실행되지 않은 상황이었다.문제가 발생한 코드💡객체의 값으로 사용한 if 표현식을 괄호로 감싸지 않았다| .average = { l..

Projects/hub-eleven 2026.08.04

[리팩토링] 재고 API - (3) 동시성 처리 최적화 : Micrometer 도입

코드 구현💡기존 코드@Component@RequiredArgsConstructorpublic class RedissonStockLockManager implements StockLockManager { private static final int MAX_RETRY_COUNT = 3; private static final long WAIT_TIME_SECONDS = 3L; private static final long LEASE_TIME_SECONDS = 5L; private static final long RETRY_BACKOFF_MILLIS = 100L; private final RedissonClient redissonClient; @Override public T executeWithLock(S..

Projects/hub-eleven 2026.08.02

[리팩토링] 재고 API - (3) 동시성 처리 최적화 : Micrometer 란?

Micrometer란?💡 Micrometer란?Micrometer는 Java 애플리케이션의 메트릭을 수집하기 위한 계측 라이브러리이다.메트릭을 직접 장기간 저장하거나 대시보드로 시각화하지는 않는다.Prometheus, Datadog 등 다양한 모니터링 시스템에 연결할 수 있는 공통 API를 제공한다.동일한 계측 코드를 유지하면서 모니터링 시스템을 변경할 수 있도록 설계되었다.메트릭(Metric)애플리케이션 상태를 숫자로 표현한 측정 데이터이다.예: HTTP 요청 수, HTTP 응답 시간, JVM Heap 사용량, DB Connection 수Micrometer가 해결하는 문제Prometheus와 Datadog 같은 모니터링 시스템은 서로 다른 계측 방식을 사용한다.Micrometer는 공통 API를 제공..

Projects/hub-eleven 2026.07.30

[부하테스트] 재고 API - (2) k6 부하 테스트 환경과 개발 환경 분리

진행 환경💡 진행 환경Java 17Spring Boot 3.xMySQL 8RedisDocker Composek6Redisson문제 상황💡 문제 상황 k6 재고 차감 부하 테스트를 구성하면서 테스트용 상품과 재고를 SQL로 직접 생성했다.시드 SQL 코드 리뷰 과정에서 기존에 같은 product_id를 가진 재고가 다른 stock_id로 저장되어 있다면 테스트 재고가 추가 삽입되어 하나의 상품에 여러 재고가 존재할 수 있다는 문제가 발견됐다.처음에는 시드 SQL만 수정하면 해결될 것이라 생각했지만 테스트 환경을 확인하면서 더 근본적인 문제가 있다는 것을 알게 되었다. 💡 기존 환경용도MySQLRedis개발 환경Docker MySQL (hubeleven)DB 0Spring Boot 테스트Homebrew..

Projects/hub-eleven 2026.07.29

[부하테스트] 재고 API - (1) k6로 테스트 해보기

재고 차감 성능 문제 발견현재 재고 차감 로직은 분산락을 획득한 상태에서 다음 작업을 수행한다.락 획득-> 상품 조회-> 재고 조회-> 재고 수량 검증-> 재고 차감-> 트랜잭션 커밋-> 응답 데이터 생성-> 락 해제 재고 정합성을 위해 순차 처리가 필요한 핵심 구간은 재고 조회, 수량 검증, 차감 및 트랜잭션 커밋이다.반면 상품명과 같은 상품 기본 정보 조회는 재고 수량의 정합성을 보장하기 위해 반드시 재고 락 안에서 실행할 필요는 없다.따라서 상품 조회가 락 내부에 포함되면서 각 요청의 락 점유 시간이 길어지고, 뒤의 요청들이 락을 기다리는 시간도 함께 증가했을 가능성이 있다. 💡가설재고 정합성과 직접 관계없는 상품 조회와 응답 생성을 락 밖으로 이동하면 락 점유 시간이 감소하고, 동일 상품에 대한..

Projects/hub-eleven 2026.07.28

[부하테스트] 부하 테스트 란? (feat. k6)

중요한 개념💡 처리량 (Throughput)정의 : 단위 시간당 시스템이 처리하는 요청의 양지표 : 주로 TPS(Transactions Per Second)나 RPS(Requests Per Second)로 측정한다.의미 : 시스템이 얼마나 많은 일을 할 수 있는지 성능의 '양'을 나타낸다.💡 지연 시간 (Latency)정의 : 사용자가 요청을 보낸 시점부터 응답을 받을 때까지 걸리는 시간의미 : 사용자에게 얼마나 빠른 '경험'을 주는지 성능의 '질'을 나타낸다.💡 상관관계부하가 증가해도 일정 수준까지는 처리량이 늘어나지만, 임계치를 넘으면 지연 시간이 급격히 증가하고 처리량은 정체되거나 하락한다.부하 테스트 툴 선정 (k6)💡 K6 란?k6 백엔드 API나 웹 서비스에 가상의 사용자, 즉 Virt..