IT 개발 관련/[프로젝트]

[예약구매] 상품 상세 조회 캐싱 적용 전과 후

Baileyton 2024. 7. 22. 17:56
728x90

상품 상세 조회 시, 데이터베이스로부터 매번 데이터를 가져오는 것은 성능 저하를 초래할 수 있습니다. 이를 개선하기 위해 캐싱을 도입할 수 있습니다.

 

Product Entity

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "products")
public class Product extends BaseTimeEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String category;
    @Column(nullable = false)
    private Integer price;
    @Column(nullable = false)
    private Integer quantity;
    @Column(nullable = false)
    private String description;
}

 

ProductController

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/products")
public class ProductController {

    private final ProductService productService;

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        return productService.getProductById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}

 

ProductService

@Service
@RequiredArgsConstructor
public class ProductService {

    private final ProductRepository productRepository;

    public Optional<Product> getProductById(Long id) {
        return productRepository.findById(id);
    }
}

 

ProductRepository

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}

 

Get요청으로 /api/products/1 상품 상세 정보 조회를 할 경우

 

 

이 와 같은 결과를 확인 할 수 있다.

 

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-cache'

캐싱 관련 의존성을 추가

 

 

캐싱을 활성화하기 위해 @EnableCaching 어노테이션을 추가합니다.

 

Entity 수정

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "products")
public class Product extends BaseTimeEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String category;
    @Column(nullable = false)
    private Integer price;
    @Column(nullable = false)
    private Integer quantity;
    @Column(nullable = false)
    private String description;
}

 

ProductService 수정

@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "products")
public class ProductService {

    private final ProductRepository productRepository;

    @Cacheable(key = "#id")
    public Optional<Product> getProductById(Long id) {
        return productRepository.findById(id);
    }
}

 

@CacheConfig 및 @Cacheable 어노테이션을 사용하여 캐싱을 적용합니다.

 

 

 

JMeter 테스트 결과

  • 캐싱 적용 전
    • 평균 응답 시간: 20ms
    • 최소 응답 시간: 14ms
    • 최대 응답 시간: 108ms
    • 표준 편차: 6.54
  • 캐싱 적용 후
    • 평균 응답 시간: 8ms
    • 최소 응답 시간: 5ms
    • 최대 응답 시간: 50ms
    • 표준 편차: 3.42

 

캐싱 적용 전

  • 모든 요청에 대해 데이터베이스를 조회
  • 높은 응답 시간과 데이터베이스 부하

캐싱 적용 후

  • 첫 번째 요청 이후 동일한 데이터는 캐시에서 조회
  • 응답 시간 단축 및 데이터베이스 부하 감소

 

결과 분석

캐싱을 적용한 후, 응답 시간이 크게 개선되었습니다. 평균 응답 시간은 약 60% 감소하였고, 최대 응답 시간 또한 크게 줄어들었습니다. 표준 편차가 줄어든 것도 응답 시간의 일관성이 높아졌음을 의미합니다.

728x90