
최근 대규모 마이크로서비스 환경에서 운영 중인 주문 관리 시스템의 주문 조회 API에서 심각한 성능 저하 현상이 발생했습니다.
해당 API는 주문 정보를 조회하는 중요한 엔드포인트로, 평균 응답 시간은 2초 이상을 기록하며 전체 시스템 성능의 병목 지점으로 작용했습니다. 문제를 해결하기 위한 분석이 필요했습니다.
1. 불필요한 JPA 설정이 로드됨
모든 마이크로서비스에서 JPA 설정이 불필요하게 활성화되어 데이터베이스와의 연결 비용이 과도하게 발생하고 있었습니다.
특히 읽기 전용 작업에서도 JPA 설정을 비활성화할 수 있는 상황이었음에도 불구하고, JPA 설정이 계속 활성화되면서 성능 저하를 일으켰습니다.
2. 읽기 전용 작업에서 불필요한 도메인 모델 변환 발생
도메인 모델에서 직접 데이터를 조회하고 변환하는 과정에서 불필요한 엔티티 변환이 이루어졌습니다.
읽기 전용 작업에서는 변환 비용을 줄이고, 필요한 데이터만 조회할 수 있는 방법이 필요했습니다.
3. 테스트 환경 구성의 어려움
테스트 환경에서 독립적인 테스트 환경 구축이 어려워 개발자의 생산성이 저하되었고, 문제를 신속하게 파악하기 어려웠습니다.
해결책은 불필요한 JPA 설정을 선택적으로 활성화하고, 읽기 전용 작업에서 불필요한 엔티티 변환을 제거하는 것이었습니다.
이를 위해 다음과 같은 방안을 적용했습니다.
JPA 설정이 필요 없는 환경에서는 설정을 비활성화하고, 읽기 전용 모드에서는 JPA를 활성화하여 불필요한 리소스 소모를 줄였습니다.
읽기 전용 API에서는 DTO 직접 조회 방식을 사용하여 엔티티 변환을 피하고, 필요한 데이터만을 빠르게 조회할 수 있도록 최적화했습니다.
기존 Repository를 최적화하여, 읽기 전용 작업에 맞는 별도의 구현을 추가했습니다.
최적화된 코드 예시:
@Configuration
@Profile("persistence")
public class OptimizedJpaConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.jpa.enabled", havingValue = "true")
public OrderReadRepository orderReadRepository() {
return new OptimizedOrderReadRepository();
}
@Bean
public QueryOptimizer queryOptimizer() {
return new QueryOptimizer(1000, true); // 캐시 크기 및 읽기 전용 모드 설정
}
}
@Repository
public class OptimizedOrderReadRepository {
@Cacheable(cacheNames = "orders")
public OrderReadDTO findOrderById(Long id) {
return entityManager
.createQuery("SELECT NEW com.example.OrderReadDTO(o.id, o.status) FROM Order o WHERE o.id = :id", OrderReadDTO.class)
.setParameter("id", id)
.setHint(QueryHints.HINT_READONLY, true)
.getSingleResult();
}
}
성능 개선 시각화

위 그래프는 성능 최적화 전후의 응답 시간 및 TPS 변화를 보여줍니다.
이번 최적화 작업은 특정 대형 이커머스 프로젝트에 적용되었습니다.
이 프로젝트는 블랙프라이데이 세일 기간 동안 트래픽이 급증했으나, 성능 최적화 후 시스템은 안정적으로 운영되었습니다.
성능 최적화는 단순히 아키텍처 원칙을 따르는 것이 아니라, 실제 사용 케이스에 맞는 전략을 선택하는 것이 중요합니다.
읽기 전용 작업에서는 불필요한 객체 변환을 제거하고, JPA 설정을 최적화함으로써 큰 성능 향상을 얻을 수 있었습니다.
이와 같은 최적화 작업은 성능 개선뿐만 아니라, 유지보수성과 테스트 용이성을 함께 향상시킬 수 있었습니다.
이러한 접근 방식은 대규모 마이크로서비스 환경에서의 시스템 안정성 및 효율성 향상에 크게 기여할 수 있습니다.