전체 글 493

[트러블슈팅] 재고 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..

[동시성 처리] Redisson은 어떻게 Redis Pub/Sub을 이용해 재시도(Retry) 로직을 구현할 수 있을까?

Redis와 RedissonRedis는 메모리 기반 Key-Value NoSQL 데이터베이스이다.데이터를 메모리에 저장하기 때문에 매우 빠른 읽기/쓰기 성능을 제공하며 캐시, 세션 저장소, Pub/Sub, 분산 락 등에 자주 사용된다.Redisson은 Java 환경에서 Redis를 쉽게 사용할 수 있도록 제공하는 Client 라이브러리이다.Client 라이브러리란 애플리케이션과 외부 시스템 사이의 통신을 추상화하여 개발자가 쉽게 사용할 수 있도록 도와주는 라이브러리를 의미한다.예를 들어 개발자는lock.lock();만 호출하지만 실제로는 Redisson이 Redis 명령어를 생성하여 Redis 서버와 통신한다.Java Application ↓ Redisson ↓ Redis Co..

Projects/hub-eleven 2026.06.24

[트러블슈팅] Redisson 분산 락 적용 중 트랜잭션 커밋 순서 문제를 해결한 과정 (2)

추가 해결 사항💡 문제 상황Redisson 분산 락 적용 중 트랜잭션 커밋 순서 문제를 해결하는 과정에서 다수의 동시 요청이 하나의 재고 락에 몰리면서 일부 요청이 tryLock의 대기 시간 안에 락을 획득하지 못하는 상황이 발생했고, 이 요청들이 락 획득 실패 예외로 처리되어 동시성 테스트 통과가 이뤄지지 않는 문제가 발생했다.💡 문제 증상현재 tryLock(WAIT_TIME_SECONDS, LEASE_TIME_SECONDS, TimeUnit.SECONDS)에서 WAIT_TIME_SECONDS 동안 락 획득을 기다리지만, 그 시간 안에 락을 얻지 못하면 false를 반환한다.이를 곧바로 STOCK_LOCK_TIMEOUT 예외로 변환했기 때문에 일부 요청이 재시도 없이 실패 처리되어 동시성 테스트가..

Projects/hub-eleven 2026.06.23

[트러블슈팅] Redisson 분산 락 적용 중 트랜잭션 커밋 순서 문제를 해결한 과정 (1)

진행 환경💡진행 환경Java 17Spring Boot 3.5.7MySQL 8.0.44Gradle문제 상황💡 문제 상황 💡 문제 증상Redisson 분산락을 적용했지만, 100개의 동시 요청을 보냈을 때 재고가 기대값처럼 정확히 차감되지 않았다.테스트 기대값은 다음과 같다.초기 재고 : 100요청 수 : 100개요청당 차감 수량 : 1기대 결과 : 최종 재고 0실제 결과 : 최종 재고가 0이 아니거나, 일부 요청이 실패하는 동시성 문제가 발생원인 분석💡 원인 1 : 락 해제가 트랜잭션 커밋보다 먼저 일어난다. ❗️StockServiceImpl.java@Transactionalpublic StockResult decreaseStock(StockRequests.Decrease request) { ..

Projects/hub-eleven 2026.06.22

[동시성 처리] 재고 감소 락 추상화 및 Redisson 락 구현 (아키텍처 구조 보완 필요)

아키텍처 구조💡현재 프로젝트 구조 💡인터페이스 구현 구조application service ↓application port(interface) ↑infrastructure adapter(implementation)Redisson에 대한 직접 의존을 application service에서 분리하기 위해, application 계층에 port 인터페이스를 두고 infrastructure 계층에서 구현하도록 설계했다.(왜 인터페이스는 application 계층에 두고, 구현체는 infrastructure 에 두는 걸까?)아 어렵넹Lock 추상화 인터페이스 StockLockManager 구현 💡StockLockManager.javapackage com.hubEleven.stock.applicat..

Projects/hub-eleven 2026.06.02