[DCommerce] 6편 - k6 성능 테스트로 Redis 동시성 검증하기

Do Hyun ·2026년 5월 19일

commerce-project

목록 보기
6/6

들어가며

5편까지 Redis 동시성 제어와 Kafka 비동기 처리를 구현했다. 이번 편에서는 k6를 사용해서 실제로 동시 주문이 들어왔을 때 재고가 정확히 차감되는지 성능 테스트로 검증했다.


k6란?

k6는 JavaScript로 테스트 스크립트를 작성할 수 있는 오픈소스 성능 테스트 툴이다. Postman처럼 API를 호출하는데, 동시에 수백 명이 요청하는 상황을 시뮬레이션할 수 있다.

brew install k6

테스트 시나리오

목표: 재고 100개인 상품에 200명이 동시에 주문했을 때, 100건만 성공하고 나머지는 재고 부족으로 차단되는지 검증


테스트 스크립트

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
    vus: 200,        // 동시 사용자 200명
    duration: '10s', // 10초 동안
};

export default function () {
    const token = 'Bearer {JWT토큰}';

    const payload = JSON.stringify({
        productId: 2,
        quantity: 1,
    });

    const params = {
        headers: {
            'Content-Type': 'application/json',
            'Authorization': token,
        },
    };

    const res = http.post('http://localhost:8080/order', payload, params);

    check(res, {
        '주문 성공 (201)': (r) => r.status === 201,
        '재고 부족 (400)': (r) => r.status === 400,
    });

    sleep(1);
}

테스트 결과

동시 사용자: 200명
재고: 100개
총 요청: 2000건

주문 성공 (201): 100건  ✅
재고 부족 (400): 1802건 ✅
평균 응답 시간: 54ms
최대 응답 시간: 689ms
처리량: 182건/s

200명이 동시에 요청했지만 딱 100건만 성공했다. 재고를 초과한 주문은 0건.


Redis 동시성 제어 핵심 코드

// StockService.java
public Long decreaseStock(Long productId, int quantity) {
    String key = "stock:" + productId;
    return redisTemplate.opsForValue().increment(key, -quantity);
}

public Long increaseStock(Long productId, int quantity) {
    String key = "stock:" + productId;
    return redisTemplate.opsForValue().increment(key, quantity);
}
// OrderServiceImpl.java
Long remainStock = stockService.decreaseStock(
        createOrderRequestDTO.getProductId(), createOrderRequestDTO.getQuantity()
);

// 재고 부족 체크
if (remainStock < 0) {
    stockService.increaseStock(createOrderRequestDTO.getProductId(), createOrderRequestDTO.getQuantity());
    throw new IllegalArgumentException("재고가 부족합니다.");
}

Redis의 increment 연산은 원자적(Atomic)으로 동작하기 때문에 동시에 여러 요청이 들어와도 정확하게 재고가 차감된다.


Redis가 없었다면?

DB에서 재고를 읽고 차감하는 방식은 아래와 같은 문제가 생긴다.

Thread A: 재고 조회 → 5개 남음
Thread B: 재고 조회 → 5개 남음  ← A가 차감하기 전에 읽음
Thread A: 재고 차감 → 4개
Thread B: 재고 차감 → 4개  ← 실제론 3개여야 하는데!

이런 Race Condition을 Redis의 원자적 연산으로 해결했다.


마치며

k6 성능 테스트를 통해 Redis 동시성 제어가 실제로 동작함을 검증했다.

5편에 걸쳐 DCommerce 프로젝트를 완성했다.

1편 - Entity 설계 + 회원가입
2편 - JWT 로그인
3편 - 상품 + 주문 API
4편 - Redis 동시성 제어
5편 - Kafka 비동기 이벤트
6편 - k6 성능 테스트 (현재)

처음에는 운영 업무만 하다 보니 직접 구조를 짜가며 해볼 기회가 많이 없었는데, 이번 프로젝트를 통해 Spring Boot + Redis + Kafka 조합을 직접 설계하고 구현하며 찍먹해볼 수 있었다.

profile
우당탕탕

0개의 댓글