QueryDSL과 캐싱을 활용하면 데이터 조회 성능을 극대화할 수 있습니다. 이번 포스팅에서는 실제 프로젝트에서 QueryDSL과 Redis 캐싱을 적용하는 방법을 다루며, 최적화를 위한 다양한 전략을 소개합니다.
1. QueryDSL 기반의 고성능 데이터 조회 적용
1) 대량 데이터 조회 시 Streaming 사용
JPA는 대량 데이터를 한 번에 조회하면 메모리 문제를 유발할 수 있습니다. 이를 해결하기 위해 stream()을 사용할 수 있습니다.
Stream<Member> memberStream = queryFactory
.selectFrom(member)
.where(member.age.gt(20))
.fetch().stream();
memberStream.forEach(System.out::println);
💡 stream()을 활용하면 대량 데이터를 한 번에 로딩하지 않고 순차적으로 처리할 수 있습니다.
2) 페이지네이션 최적화
페이징 조회 시 fetch()와 count()를 분리하여 불필요한 데이터 로딩을 줄일 수 있습니다.
public Page<MemberDto> findMembers(Pageable pageable) {
List<MemberDto> content = queryFactory
.select(Projections.constructor(MemberDto.class, member.name, member.age))
.from(member)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
long total = queryFactory
.select(member.count())
.from(member)
.fetchOne();
return new PageImpl<>(content, pageable, total);
}
💡 데이터 수를 조회하는 쿼리를 별도로 실행하면 성능을 개선할 수 있습니다.
3) 인덱스 활용 및 튜닝
데이터 조회 속도를 향상시키기 위해 적절한 인덱스를 적용하는 것이 중요합니다.
@Entity
@Table(indexes = {@Index(name = "idx_member_name", columnList = "name")})
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
}
💡 인덱스를 추가하면 조회 성능이 크게 개선될 수 있습니다.
2. Redis 캐싱을 활용한 조회 성능 최적화
1) Spring Boot에서 Redis 설정
Redis는 높은 성능을 제공하는 인메모리 데이터 저장소로, 자주 조회하는 데이터를 캐싱하는 데 유용합니다.
spring.redis.host=localhost
spring.redis.port=6379
2) 캐시 적용 (@Cacheable)
Redis를 활용하여 자주 조회하는 데이터를 캐싱하면 DB 부하를 줄일 수 있습니다.
@Cacheable(value = "memberCache", key = "#id")
public MemberDto getMember(Long id) {
return queryFactory
.select(Projections.constructor(MemberDto.class, member.name, member.age))
.from(member)
.where(member.id.eq(id))
.fetchOne();
}
💡 @Cacheable을 적용하면 동일한 요청에 대해 Redis에서 데이터를 조회하여 성능을 개선할 수 있습니다.
3) 캐시 무효화 (@CacheEvict)
데이터가 변경될 경우 기존 캐시를 무효화하여 최신 데이터를 유지할 수 있습니다.
@CacheEvict(value = "memberCache", key = "#id")
public void updateMember(Long id, String name, int age) {
queryFactory.update(member)
.set(member.name, name)
.set(member.age, age)
.where(member.id.eq(id))
.execute();
}
💡 @CacheEvict를 사용하면 데이터가 변경될 때 자동으로 캐시를 삭제할 수 있습니다.
4) 캐시 만료 시간 설정
캐싱된 데이터가 오래 유지되지 않도록 TTL(Time-To-Live) 값을 설정할 수 있습니다.
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10));
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(config)
.build();
}
💡 TTL을 설정하면 오래된 데이터가 자동으로 삭제되어 최신 데이터를 유지할 수 있습니다.
5) 캐싱을 활용한 API 성능 개선
API 응답 속도를 높이기 위해 Redis 캐싱을 적용하면 빠른 데이터 제공이 가능합니다.
@GetMapping("/members/{id}")
public ResponseEntity<MemberDto> getMember(@PathVariable Long id) {
MemberDto member = memberService.getMember(id);
return ResponseEntity.ok(member);
}
💡 DB를 직접 조회하는 대신 캐싱된 데이터를 반환하면 API 성능이 크게 향상됩니다.
3. QueryDSL과 캐싱을 활용한 최적화 전략 정리
✅ 대량 데이터 조회 시 Streaming을 활용하여 메모리 사용 최적화
✅ 페이지네이션 최적화를 통해 불필요한 데이터 로딩 방지
✅ 적절한 인덱스를 추가하여 검색 성능 향상
✅ Redis 캐싱을 적용하여 반복적인 조회 성능 향상
✅ 캐시 무효화 및 TTL 설정으로 최신 데이터 유지
✅ API 응답 속도를 높이기 위해 캐싱을 적극 활용
'BackEND > Java' 카테고리의 다른 글
Spring Boot에서 REST API 설계 및 개발하기 (0) | 2025.04.06 |
---|---|
QueryDSL과 JPA 성능 튜닝 전략 (0) | 2025.04.04 |
QueryDSL을 활용한 동적 쿼리 작성 및 성능 개선 (0) | 2025.04.03 |
JPA의 기본 조회 성능 최적화 기법 (0) | 2025.04.02 |
JPA와 QueryDSL 소개 및 비교 (0) | 2025.04.01 |