From 4c6d6fa03372a7365973bac6be194f88f54b4512 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 10:00:44 +0900 Subject: [PATCH 01/16] =?UTF-8?q?feat:=20redis=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B0=B0=EC=B9=98=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=BA=90=EC=8B=B1=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 3 + .../scheduler/AuctionHistoryScheduler.java | 8 +- .../AuctionHistoryCacheWarmupService.java | 100 +++++++++++++++++ .../service/AuctionHistoryService.java | 22 ++++ .../scheduler/AuctionRealtimeScheduler.java | 5 + .../service/AuctionRealtimeService.java | 23 ++++ .../service/AuctionSearchOptionService.java | 3 + .../until/the/eternity/config/CacheNames.java | 55 +++++++++ .../the/eternity/config/RedisConfig.java | 104 ++++++++++++++++++ .../service/EnchantInfoService.java | 15 +++ .../application/service/ItemInfoService.java | 30 ++++- .../MetalwareAttributeInfoService.java | 7 ++ .../service/MetalwareInfoService.java | 12 ++ .../service/AllTimeRankingService.java | 6 +- .../service/CategoryRankingService.java | 8 ++ .../service/PriceChangeRankingService.java | 5 + .../service/PriceRankingService.java | 5 + .../service/VolumeRankingService.java | 4 + .../service/ItemDailyStatisticsService.java | 25 +++-- .../service/ItemWeeklyStatisticsService.java | 25 +++-- .../SubcategoryDailyStatisticsService.java | 23 ++-- .../SubcategoryWeeklyStatisticsService.java | 23 ++-- .../TopCategoryDailyStatisticsService.java | 19 ++-- .../TopCategoryWeeklyStatisticsService.java | 19 ++-- .../service/DailyStatisticsService.java | 77 +++++++++++++ .../service/WeeklyStatisticsService.java | 23 ++++ src/main/resources/application.yml | 14 +++ 27 files changed, 612 insertions(+), 51 deletions(-) create mode 100644 src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java create mode 100644 src/main/java/until/the/eternity/config/CacheNames.java create mode 100644 src/main/java/until/the/eternity/config/RedisConfig.java diff --git a/build.gradle.kts b/build.gradle.kts index 68ef752b..a8950869 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,9 @@ dependencies { // Spring Boot implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-aop") + + // Redis + implementation("org.springframework.boot:spring-boot-starter-data-redis") implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-data-jpa") diff --git a/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java b/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java index 141e6b1a..b4c857c0 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java @@ -8,6 +8,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import until.the.eternity.auctionhistory.application.service.AuctionHistoryCacheWarmupService; import until.the.eternity.auctionhistory.application.service.AuctionHistoryService; import until.the.eternity.auctionhistory.application.service.fetcher.AuctionHistoryFetcher; import until.the.eternity.auctionhistory.application.service.persister.AuctionHistoryPersister; @@ -27,6 +28,7 @@ public class AuctionHistoryScheduler { private final AuctionHistoryFetcher fetcher; private final AuctionHistoryPersister persister; private final ApplicationEventPublisher eventPublisher; + private final AuctionHistoryCacheWarmupService cacheWarmupService; @Value("${openapi.auction-history.delay-ms}") private long delayMs; @@ -114,12 +116,16 @@ public int fetchAndSaveAuctionHistoryAll() { "> [SCHEDULE] AuctionHistoryScheduler saved [{}] new auction history records complete", totalSavedCount); - // 통계 업데이트를 위한 이벤트 발행 + // 통계 업데이트를 위한 이벤트 발행 (DailyStatisticsService가 일간/랭킹 캐시를 함께 무효화) log.debug( "> [SCHEDULE] Publishing AuctionHistorySavedEvent with {} records", totalSavedCount); eventPublisher.publishEvent(new AuctionHistorySavedEvent(totalSavedCount)); + // 경매 거래 내역 캐시 무효화 + 역대 랭킹 캐시 무효화 + 30가지 조합 워밍업 + log.info("> [SCHEDULE] Starting cache eviction and warmup"); + cacheWarmupService.evictAndWarm(); + return totalSavedCount; } } diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java new file mode 100644 index 00000000..bafd0a49 --- /dev/null +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java @@ -0,0 +1,100 @@ +package until.the.eternity.auctionhistory.application.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Service; +import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; +import until.the.eternity.common.enums.SortDirection; +import until.the.eternity.common.enums.SortField; +import until.the.eternity.common.request.PageRequestDto; +import until.the.eternity.config.CacheNames; + +/** + * 경매 거래 내역 캐시 워밍업 서비스. + * + *

AuctionHistoryScheduler 배치 완료 후 호출되어 다음 작업을 수행한다. + * + *

    + *
  1. auction-history:search 캐시 전체 무효화 + *
  2. auction_history 기반 역대 랭킹 캐시 무효화 (ALLTIME_HIGHEST, ALLTIME_MONTH_VOLUME) + *
  3. page 1~5 × size 20 × sortField 3종 × direction 2종 = 30가지 조합 캐시 워밍 + *
+ */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AuctionHistoryCacheWarmupService { + + private static final int WARMUP_SIZE = 20; + private static final int WARMUP_MAX_PAGE = 5; + + private final AuctionHistoryService auctionHistoryService; + private final CacheManager cacheManager; + + /** + * 캐시 무효화 후 기본 30가지 조합을 선제적으로 워밍한다. + * + *

빈 검색 조건(필터 없음) 기준으로 워밍하므로, 단순 목록 조회 요청에 즉시 캐시 히트가 발생한다. + */ + public void evictAndWarm() { + evictCaches(); + warmup(); + } + + private void evictCaches() { + clearCache(CacheNames.AUCTION_HISTORY_SEARCH); + // auction_history 전체를 직접 쿼리하는 역대 랭킹도 함께 무효화 + clearCache(CacheNames.RANKING_ALLTIME_HIGHEST); + clearCache(CacheNames.RANKING_ALLTIME_MONTH_VOLUME); + log.info("[Cache Warmup] Evicted: {}, {}, {}", + CacheNames.AUCTION_HISTORY_SEARCH, + CacheNames.RANKING_ALLTIME_HIGHEST, + CacheNames.RANKING_ALLTIME_MONTH_VOLUME); + } + + private void warmup() { + // 옵션 필터가 모두 null인 빈 검색 조건 (캐싱 condition 충족) + AuctionHistorySearchRequest emptyRequest = + new AuctionHistorySearchRequest( + null, null, null, null, null, null, null, null, null); + + int successCount = 0; + int failCount = 0; + + for (int page = 1; page <= WARMUP_MAX_PAGE; page++) { + for (SortField sortField : SortField.values()) { + for (SortDirection direction : SortDirection.values()) { + PageRequestDto pageRequest = + new PageRequestDto(page, WARMUP_SIZE, sortField, direction); + try { + auctionHistoryService.search(emptyRequest, pageRequest); + successCount++; + } catch (Exception e) { + failCount++; + log.warn( + "[Cache Warmup] Failed: page={}, sortField={}, direction={}", + page, + sortField, + direction, + e); + } + } + } + } + + log.info( + "[Cache Warmup] Completed: success={}, fail={} (total={})", + successCount, + failCount, + WARMUP_MAX_PAGE * SortField.values().length * SortDirection.values().length); + } + + private void clearCache(String cacheName) { + Cache cache = cacheManager.getCache(cacheName); + if (cache != null) { + cache.clear(); + } + } +} diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java index cc15bfd1..c6adf6da 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java @@ -4,6 +4,7 @@ import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,6 +16,7 @@ import until.the.eternity.auctionhistory.interfaces.rest.dto.response.ItemOptionResponse; import until.the.eternity.common.request.PageRequestDto; import until.the.eternity.common.response.PageResponseDto; +import until.the.eternity.config.CacheNames; @Service @RequiredArgsConstructor @@ -25,6 +27,26 @@ public class AuctionHistoryService { private final AuctionHistoryMapper mapper; private final EntityManager entityManager; + /** + * 경매 거래 내역을 검색한다. + * + *

단순 검색(가격/옵션/인챈트/세공 필터 없음)에 한해 캐싱을 적용한다. TTL 2시간, 배치 완료 시 전체 무효화 + 워밍업. + */ + @Cacheable( + cacheNames = CacheNames.AUCTION_HISTORY_SEARCH, + key = + "#pageRequestDto.page() + ':'" + + " + #pageRequestDto.size() + ':'" + + " + (#pageRequestDto.sortBy() != null ? #pageRequestDto.sortBy().fieldName : 'dateAuctionBuy') + ':'" + + " + (#pageRequestDto.direction() != null ? #pageRequestDto.direction().code : 'DESC') + ':'" + + " + (#requestDto.itemName() ?: '') + ':'" + + " + (#requestDto.itemTopCategory() ?: '') + ':'" + + " + (#requestDto.itemSubCategory() ?: '')", + condition = + "#requestDto.itemOptionSearchRequest() == null" + + " and #requestDto.enchantSearchRequest() == null" + + " and (#requestDto.metalwareSearchRequests() == null or #requestDto.metalwareSearchRequests().isEmpty())" + + " and #requestDto.priceSearchRequest() == null") @Transactional(readOnly = true) public PageResponseDto> search( AuctionHistorySearchRequest requestDto, PageRequestDto pageRequestDto) { diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java b/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java index 1adc8e93..74296a41 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java @@ -21,6 +21,8 @@ *

10분 간격으로 Nexon Open API /auction/list를 호출하여 현재 판매 중인 아이템 정보를 수집한다. * *

각 서브 카테고리별로 전체 데이터를 수집한 뒤, 기존 데이터를 삭제하고 새 데이터로 교체한다. (Full Refresh) + * + *

Full Refresh 완료 후 auction-realtime:search 캐시 전체를 무효화한다. */ @Slf4j @Component @@ -130,5 +132,8 @@ public void fetchAndSaveAuctionRealtimeAll() { totalSavedCount, totalFailedCount, deletedExpired); + + // Full Refresh 완료 후 실시간 경매 검색 캐시 전체 무효화 + service.evictSearchCache(); } } diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java b/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java index c34da333..5de388b0 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java @@ -4,6 +4,8 @@ import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -16,6 +18,7 @@ import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.RealtimeItemOptionResponse; import until.the.eternity.common.enums.ItemCategory; import until.the.eternity.common.response.PageResponseDto; +import until.the.eternity.config.CacheNames; /** 실시간 경매장 데이터 Service. */ @Slf4j @@ -29,10 +32,20 @@ public class AuctionRealtimeService { /** * 실시간 경매장 아이템을 검색한다. * + *

캐시 키: 주요 검색 파라미터 조합. 10분 배치 완료 시 전체 무효화된다. + * * @param requestDto 검색 조건 * @param pageable 페이지 정보 * @return 검색 결과 */ + @Cacheable( + cacheNames = CacheNames.AUCTION_REALTIME_SEARCH, + key = + "(#requestDto.itemTopCategory() ?: '_') + ':'" + + " + (#requestDto.itemSubCategory() ?: '_') + ':'" + + " + (#requestDto.itemName() ?: '_') + ':'" + + " + (#requestDto.isExactItemName() ?: false) + ':'" + + " + #pageable.pageNumber + ':' + #pageable.pageSize + ':' + #pageable.sort") @Transactional(readOnly = true) public PageResponseDto> search( AuctionRealtimeSearchRequest requestDto, Pageable pageable) { @@ -91,4 +104,14 @@ public int deleteExpiredItems(Instant now) { log.info("[REALTIME] Deleted {} expired auction realtime items", deleted); return deleted; } + + /** + * 실시간 경매 검색 캐시 전체를 무효화한다. + * + *

AuctionRealtimeScheduler에서 Full Refresh 완료 후 호출한다. + */ + @CacheEvict(cacheNames = CacheNames.AUCTION_REALTIME_SEARCH, allEntries = true) + public void evictSearchCache() { + log.info("[REALTIME] Cache evicted: {}", CacheNames.AUCTION_REALTIME_SEARCH); + } } diff --git a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java index aec4e464..95a7e73f 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java @@ -6,8 +6,10 @@ import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.auctionsearchoption.domain.entity.AuctionSearchOptionMetadata; import until.the.eternity.auctionsearchoption.domain.repository.AuctionSearchOptionRepositoryPort; import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.FieldMetadata; @@ -26,6 +28,7 @@ public class AuctionSearchOptionService { * * @return 검색 옵션 메타데이터 리스트 */ + @Cacheable(cacheNames = CacheNames.SEARCH_OPTION_ALL_ACTIVE, key = "'all'") @Transactional(readOnly = true) public List getAllActiveSearchOptions() { List entities = repositoryPort.findAllActive(); diff --git a/src/main/java/until/the/eternity/config/CacheNames.java b/src/main/java/until/the/eternity/config/CacheNames.java new file mode 100644 index 00000000..be962568 --- /dev/null +++ b/src/main/java/until/the/eternity/config/CacheNames.java @@ -0,0 +1,55 @@ +package until.the.eternity.config; + +/** Redis 캐시 이름 상수 클래스. */ +public final class CacheNames { + + private CacheNames() {} + + // ===== 랭킹 ===== + public static final String RANKING_PRICE_TODAY_HIGHEST = "ranking:price:today:highest"; + public static final String RANKING_PRICE_WEEK_HIGHEST = "ranking:price:week:highest"; + public static final String RANKING_PRICE_TODAY_VOLUME = "ranking:price:today:volume"; + public static final String RANKING_VOLUME_TODAY_POPULAR = "ranking:volume:today:popular"; + public static final String RANKING_VOLUME_WEEK_POPULAR = "ranking:volume:week:popular"; + public static final String RANKING_CHANGE_PRICE_SURGE = "ranking:change:price:surge"; + public static final String RANKING_CHANGE_PRICE_DROP = "ranking:change:price:drop"; + public static final String RANKING_CHANGE_VOLUME_SURGE = "ranking:change:volume:surge"; + public static final String RANKING_CATEGORY_HIGHEST = "ranking:category:highest"; + public static final String RANKING_CATEGORY_POPULAR = "ranking:category:popular"; + public static final String RANKING_ALLTIME_HIGHEST = "ranking:alltime:highest"; + public static final String RANKING_ALLTIME_MONTH_VOLUME = "ranking:alltime:month:volume"; + + // ===== 검색 옵션 메타데이터 ===== + public static final String SEARCH_OPTION_ALL_ACTIVE = "search-option:all-active"; + + // ===== 아이템 마스터 ===== + public static final String ITEM_INFO_ALL = "item-info:all"; + public static final String ITEM_INFO_BY_TOP_CATEGORY = "item-info:by-top-category"; + public static final String ITEM_INFO_BY_SUB_CATEGORY = "item-info:by-sub-category"; + public static final String ITEM_INFO_DETAIL = "item-info:detail"; + public static final String ITEM_INFO_SUMMARY = "item-info:summary"; + + // ===== 인챈트 마스터 ===== + public static final String ENCHANT_INFO_ALL = "enchant-info:all"; + public static final String ENCHANT_INFO_FULLNAMES = "enchant-info:fullnames"; + + // ===== 세공 마스터 ===== + public static final String METALWARE_INFO_ALL = "metalware-info:all"; + public static final String METALWARE_ATTRIBUTE_INFO_SEARCH = "metalware-attribute-info:search"; + + // ===== 통계 (일간) ===== + public static final String STATISTICS_ITEM_DAILY = "statistics:item:daily"; + public static final String STATISTICS_SUBCATEGORY_DAILY = "statistics:subcategory:daily"; + public static final String STATISTICS_TOPCATEGORY_DAILY = "statistics:topcategory:daily"; + + // ===== 통계 (주간) ===== + public static final String STATISTICS_ITEM_WEEKLY = "statistics:item:weekly"; + public static final String STATISTICS_SUBCATEGORY_WEEKLY = "statistics:subcategory:weekly"; + public static final String STATISTICS_TOPCATEGORY_WEEKLY = "statistics:topcategory:weekly"; + + // ===== 실시간 경매 ===== + public static final String AUCTION_REALTIME_SEARCH = "auction-realtime:search"; + + // ===== 경매 거래 내역 ===== + public static final String AUCTION_HISTORY_SEARCH = "auction-history:search"; +} diff --git a/src/main/java/until/the/eternity/config/RedisConfig.java b/src/main/java/until/the/eternity/config/RedisConfig.java new file mode 100644 index 00000000..c7c473fc --- /dev/null +++ b/src/main/java/until/the/eternity/config/RedisConfig.java @@ -0,0 +1,104 @@ +package until.the.eternity.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableCaching +public class RedisConfig { + + @Bean + public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { + ObjectMapper objectMapper = + new ObjectMapper() + .registerModule(new JavaTimeModule()) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + GenericJackson2JsonRedisSerializer jsonSerializer = + new GenericJackson2JsonRedisSerializer(objectMapper); + + RedisCacheConfiguration defaultConfig = + RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(10)) + .serializeKeysWith( + RedisSerializationContext.SerializationPair.fromSerializer( + new StringRedisSerializer())) + .serializeValuesWith( + RedisSerializationContext.SerializationPair.fromSerializer( + jsonSerializer)) + .disableCachingNullValues(); + + Map configs = new HashMap<>(); + + // 랭킹 - 10분 TTL (이벤트 기반 eviction으로 실시간 반영) + Duration rankingTtl = Duration.ofMinutes(10); + configs.put(CacheNames.RANKING_PRICE_TODAY_HIGHEST, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_PRICE_WEEK_HIGHEST, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_PRICE_TODAY_VOLUME, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_VOLUME_TODAY_POPULAR, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_VOLUME_WEEK_POPULAR, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_CHANGE_PRICE_SURGE, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_CHANGE_PRICE_DROP, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_CHANGE_VOLUME_SURGE, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_CATEGORY_HIGHEST, defaultConfig.entryTtl(rankingTtl)); + configs.put(CacheNames.RANKING_CATEGORY_POPULAR, defaultConfig.entryTtl(rankingTtl)); + // 역대 최고가 - 1시간 TTL (auction_history 전체 스캔, 잘 바뀌지 않음) + configs.put( + CacheNames.RANKING_ALLTIME_HIGHEST, defaultConfig.entryTtl(Duration.ofHours(1))); + configs.put(CacheNames.RANKING_ALLTIME_MONTH_VOLUME, defaultConfig.entryTtl(rankingTtl)); + + // 검색 옵션 메타데이터 - 24시간 TTL (사실상 정적 데이터) + configs.put( + CacheNames.SEARCH_OPTION_ALL_ACTIVE, + defaultConfig.entryTtl(Duration.ofHours(24))); + + // 마스터 데이터 - 1시간 TTL (sync API 호출 시 evict) + Duration masterTtl = Duration.ofHours(1); + configs.put(CacheNames.ITEM_INFO_ALL, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.ITEM_INFO_BY_TOP_CATEGORY, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.ITEM_INFO_BY_SUB_CATEGORY, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.ITEM_INFO_DETAIL, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.ITEM_INFO_SUMMARY, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.ENCHANT_INFO_ALL, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.ENCHANT_INFO_FULLNAMES, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.METALWARE_INFO_ALL, defaultConfig.entryTtl(masterTtl)); + configs.put( + CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, defaultConfig.entryTtl(masterTtl)); + + // 통계 - 30분 TTL (이벤트 기반 eviction으로 실시간 반영) + Duration statsTtl = Duration.ofMinutes(30); + configs.put(CacheNames.STATISTICS_ITEM_DAILY, defaultConfig.entryTtl(statsTtl)); + configs.put(CacheNames.STATISTICS_SUBCATEGORY_DAILY, defaultConfig.entryTtl(statsTtl)); + configs.put(CacheNames.STATISTICS_TOPCATEGORY_DAILY, defaultConfig.entryTtl(statsTtl)); + configs.put(CacheNames.STATISTICS_ITEM_WEEKLY, defaultConfig.entryTtl(statsTtl)); + configs.put(CacheNames.STATISTICS_SUBCATEGORY_WEEKLY, defaultConfig.entryTtl(statsTtl)); + configs.put(CacheNames.STATISTICS_TOPCATEGORY_WEEKLY, defaultConfig.entryTtl(statsTtl)); + + // 실시간 경매 - 12분 TTL (10분 배치 + 여유 2분) + configs.put( + CacheNames.AUCTION_REALTIME_SEARCH, + defaultConfig.entryTtl(Duration.ofMinutes(12))); + + // 경매 거래 내역 - 2시간 TTL (배치 완료 시 evict + warmup) + configs.put( + CacheNames.AUCTION_HISTORY_SEARCH, defaultConfig.entryTtl(Duration.ofHours(2))); + + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(defaultConfig) + .withInitialCacheConfigurations(configs) + .build(); + } +} diff --git a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java index 396b8811..74dbe94f 100644 --- a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java +++ b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java @@ -3,11 +3,15 @@ import java.util.List; import java.util.Set; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import until.the.eternity.common.exception.CustomException; +import until.the.eternity.config.CacheNames; import until.the.eternity.enchantinfo.domain.exception.EnchantInfoExceptionCode; import until.the.eternity.enchantinfo.domain.repository.EnchantInfoRepositoryPort; import until.the.eternity.enchantinfo.interfaces.rest.dto.response.EnchantInfoResponse; @@ -22,10 +26,16 @@ public class EnchantInfoService { private final EnchantInfoRepositoryPort enchantInfoRepository; + @Cacheable( + cacheNames = CacheNames.ENCHANT_INFO_ALL, + key = "#pageable.pageNumber + ':' + #pageable.pageSize") public Page findAll(Pageable pageable) { return enchantInfoRepository.findAll(pageable).map(EnchantInfoResponse::from); } + @Cacheable( + cacheNames = CacheNames.ENCHANT_INFO_FULLNAMES, + key = "#affixPosition ?: 'all'") public List findAllFullnames(String affixPosition) { if (affixPosition != null) { if (!ALLOWED_AFFIX_POSITIONS.contains(affixPosition)) { @@ -36,6 +46,11 @@ public List findAllFullnames(String affixPosition) { return enchantInfoRepository.findAllFullnames(); } + @Caching( + evict = { + @CacheEvict(cacheNames = CacheNames.ENCHANT_INFO_ALL, allEntries = true), + @CacheEvict(cacheNames = CacheNames.ENCHANT_INFO_FULLNAMES, allEntries = true) + }) @Transactional public EnchantInfoSyncResponse syncFromAuctionHistory() { int upserted = enchantInfoRepository.upsertFromAuctionHistory(); diff --git a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java index f1022c51..ab7c5bb4 100644 --- a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java +++ b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java @@ -6,6 +6,9 @@ import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -13,6 +16,7 @@ import until.the.eternity.auctionhistory.domain.repository.AuctionHistoryRepositoryPort; import until.the.eternity.batchlog.domain.enums.BatchType; import until.the.eternity.common.annotation.BatchLog; +import until.the.eternity.config.CacheNames; import until.the.eternity.iteminfo.domain.entity.ItemInfo; import until.the.eternity.iteminfo.domain.entity.ItemInfoId; import until.the.eternity.iteminfo.domain.repository.ItemInfoRepositoryPort; @@ -35,21 +39,31 @@ public List findItemCategories() { return ItemCategoryResponse.from(); } + @Cacheable(cacheNames = CacheNames.ITEM_INFO_ALL, key = "'all'") public List findAll() { List itemInfos = itemInfoRepository.findAll(); return ItemInfoResponse.from(itemInfos); } + @Cacheable(cacheNames = CacheNames.ITEM_INFO_BY_TOP_CATEGORY, key = "#topCategory") public List findByTopCategory(String topCategory) { List itemInfos = itemInfoRepository.findByTopCategory(topCategory); return ItemInfoResponse.from(itemInfos); } + @Cacheable(cacheNames = CacheNames.ITEM_INFO_BY_SUB_CATEGORY, key = "#subCategory") public List findBySubCategory(String subCategory) { List itemInfos = itemInfoRepository.findBySubCategory(subCategory); return ItemInfoResponse.from(itemInfos); } + @Cacheable( + cacheNames = CacheNames.ITEM_INFO_DETAIL, + key = + "(#searchRequest.itemName() ?: '') + ':'" + + " + (#searchRequest.itemTopCategory() ?: '') + ':'" + + " + (#searchRequest.itemSubCategory() ?: '') + ':'" + + " + #pageable.pageNumber + ':' + #pageable.pageSize") public Page findAllDetail( ItemInfoSearchRequest searchRequest, Pageable pageable) { Page itemInfoPage = @@ -57,10 +71,16 @@ public Page findAllDetail( return itemInfoPage.map(ItemInfoResponse::from); } + @Cacheable( + cacheNames = CacheNames.ITEM_INFO_SUMMARY, + key = + "(#searchRequest.itemName() ?: '') + ':'" + + " + (#searchRequest.itemTopCategory() ?: '') + ':'" + + " + (#searchRequest.itemSubCategory() ?: '') + ':'" + + " + #direction.name()") public List findAllSummary( ItemInfoSearchRequest searchRequest, org.springframework.data.domain.Sort.Direction direction) { - // direction을 Pageable로 변환 Pageable pageable = org.springframework.data.domain.PageRequest.of( 0, @@ -70,6 +90,14 @@ public List findAllSummary( return ItemInfoSummaryResponse.from(itemInfos); } + @Caching( + evict = { + @CacheEvict(cacheNames = CacheNames.ITEM_INFO_ALL, allEntries = true), + @CacheEvict(cacheNames = CacheNames.ITEM_INFO_BY_TOP_CATEGORY, allEntries = true), + @CacheEvict(cacheNames = CacheNames.ITEM_INFO_BY_SUB_CATEGORY, allEntries = true), + @CacheEvict(cacheNames = CacheNames.ITEM_INFO_DETAIL, allEntries = true), + @CacheEvict(cacheNames = CacheNames.ITEM_INFO_SUMMARY, allEntries = true) + }) @BatchLog(type = BatchType.ITEM_INFO_SYNC) @Transactional public ItemInfoSyncResponse syncItemInfoFromAuctionHistory() { diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java index 2816d4fa..8e8adf7a 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java @@ -1,11 +1,14 @@ package until.the.eternity.metalwareinfo.application.service; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import until.the.eternity.batchlog.domain.enums.BatchType; import until.the.eternity.common.annotation.BatchLog; +import until.the.eternity.config.CacheNames; import until.the.eternity.metalwareinfo.domain.repository.MetalwareAttributeInfoRepositoryPort; import until.the.eternity.metalwareinfo.interfaces.rest.dto.request.MetalwareAttributeInfoSearchRequest; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareAttributeInfoResponse; @@ -16,6 +19,7 @@ public class MetalwareAttributeInfoService { private final MetalwareAttributeInfoRepositoryPort metalwareAttributeInfoRepository; + @CacheEvict(cacheNames = CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, allEntries = true) @BatchLog(type = BatchType.METALWARE_ATTRIBUTE_SYNC) @Transactional public int sync() { @@ -27,6 +31,9 @@ public int sync() { return inserted + updated; } + @Cacheable( + cacheNames = CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, + key = "#request.metalware() + ':' + #request.toPageable().pageNumber + ':' + #request.toPageable().pageSize") @Transactional(readOnly = true) public Page search( MetalwareAttributeInfoSearchRequest request) { diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java index fdc99fbd..aa909d6f 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java @@ -2,8 +2,12 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.metalwareinfo.domain.repository.MetalwareInfoRepositoryPort; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoSyncResponse; @@ -15,11 +19,19 @@ public class MetalwareInfoService { private final MetalwareInfoRepositoryPort metalwareInfoRepository; + @Cacheable(cacheNames = CacheNames.METALWARE_INFO_ALL, key = "'all'") public List findAll() { List metalwares = metalwareInfoRepository.findAllMetalwares(); return MetalwareInfoResponse.from(metalwares); } + @Caching( + evict = { + @CacheEvict(cacheNames = CacheNames.METALWARE_INFO_ALL, allEntries = true), + @CacheEvict( + cacheNames = CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, + allEntries = true) + }) @Transactional public MetalwareInfoSyncResponse syncFromAttributeInfo() { int levelAttributeUpserted = diff --git a/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java index 1fb59d6d..ac95269f 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java @@ -2,8 +2,10 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.ranking.domain.mapper.RankingMapper; import until.the.eternity.ranking.interfaces.rest.dto.response.AllTimeRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; @@ -16,13 +18,15 @@ public class AllTimeRankingService { private final RankingRepository rankingRepository; private final RankingMapper rankingMapper; - /** 역대 최고가 거래 TOP N (API 11) */ + /** 역대 최고가 거래 TOP N (API 11) - auction_history 전체 스캔, 1시간 TTL */ + @Cacheable(cacheNames = CacheNames.RANKING_ALLTIME_HIGHEST, key = "#limit") public List getAllTimeHighestPrice(int limit) { List results = rankingRepository.findAllTimeHighestPrice(limit); return rankingMapper.toAllTimeRankingResponses(results); } /** 이번 달 최대 거래액 TOP N (API 12) */ + @Cacheable(cacheNames = CacheNames.RANKING_ALLTIME_MONTH_VOLUME, key = "#limit") public List getMonthLargestVolume(int limit) { List results = rankingRepository.findMonthLargestVolume(limit); return rankingMapper.toAllTimeRankingResponses(results); diff --git a/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java index f70c98e0..194e2a30 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java @@ -2,8 +2,10 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.ranking.domain.mapper.RankingMapper; import until.the.eternity.ranking.interfaces.rest.dto.response.PriceRankingResponse; import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeRankingResponse; @@ -18,6 +20,9 @@ public class CategoryRankingService { private final RankingMapper rankingMapper; /** 카테고리별 최고가 TOP N (API 9) */ + @Cacheable( + cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, + key = "#topCategory + ':' + #subCategory + ':' + #limit") public List getCategoryTopPriced( String topCategory, String subCategory, int limit) { List results = @@ -26,6 +31,9 @@ public List getCategoryTopPriced( } /** 카테고리별 인기 아이템 TOP N (API 10) */ + @Cacheable( + cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, + key = "#topCategory + ':' + #subCategory + ':' + #limit") public List getCategoryPopular( String topCategory, String subCategory, int limit) { List results = diff --git a/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java index be0cd184..1296d9b5 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java @@ -2,8 +2,10 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.ranking.domain.mapper.RankingMapper; import until.the.eternity.ranking.interfaces.rest.dto.response.PriceChangeRankingResponse; import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeChangeRankingResponse; @@ -18,18 +20,21 @@ public class PriceChangeRankingService { private final RankingMapper rankingMapper; /** 가격 급등 TOP N (API 6) */ + @Cacheable(cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, key = "#limit") public List getPriceSurge(int limit) { List results = rankingRepository.findPriceSurge(limit); return rankingMapper.toPriceChangeRankingResponses(results); } /** 가격 급락 TOP N (API 7) */ + @Cacheable(cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, key = "#limit") public List getPriceDrop(int limit) { List results = rankingRepository.findPriceDrop(limit); return rankingMapper.toPriceChangeRankingResponses(results); } /** 거래량 급증 TOP N (API 8) */ + @Cacheable(cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, key = "#limit") public List getVolumeSurge(int limit) { List results = rankingRepository.findVolumeSurge(limit); return rankingMapper.toVolumeChangeRankingResponses(results); diff --git a/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java index 757d9cf7..fa81b45e 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java @@ -2,8 +2,10 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.ranking.domain.mapper.RankingMapper; import until.the.eternity.ranking.interfaces.rest.dto.response.PriceRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; @@ -17,18 +19,21 @@ public class PriceRankingService { private final RankingMapper rankingMapper; /** 오늘의 최고가 거래 TOP N (API 1) */ + @Cacheable(cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, key = "#limit") public List getTodayHighestPrice(int limit) { List results = rankingRepository.findTodayHighestPrice(limit); return rankingMapper.toPriceRankingResponses(results); } /** 이번 주 최고가 아이템 TOP N (API 2) */ + @Cacheable(cacheNames = CacheNames.RANKING_PRICE_WEEK_HIGHEST, key = "#limit") public List getWeekHighestPrice(int limit) { List results = rankingRepository.findWeekHighestPrice(limit); return rankingMapper.toPriceRankingResponses(results); } /** 오늘의 최대 거래액 TOP N (API 3) */ + @Cacheable(cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, key = "#limit") public List getTodayLargestVolume(int limit) { List results = rankingRepository.findTodayLargestVolume(limit); return rankingMapper.toPriceRankingResponses(results); diff --git a/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java index 033a61bb..9d593054 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java @@ -2,8 +2,10 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.ranking.domain.mapper.RankingMapper; import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; @@ -17,12 +19,14 @@ public class VolumeRankingService { private final RankingMapper rankingMapper; /** 오늘의 인기 아이템 TOP N (API 4) */ + @Cacheable(cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, key = "#limit") public List getTodayPopular(int limit) { List results = rankingRepository.findTodayPopular(limit); return rankingMapper.toVolumeRankingResponses(results); } /** 이번 주 인기 아이템 TOP N (API 5) */ + @Cacheable(cacheNames = CacheNames.RANKING_VOLUME_WEEK_POPULAR, key = "#limit") public List getWeekPopular(int limit) { List results = rankingRepository.findWeekPopular(limit); return rankingMapper.toVolumeRankingResponses(results); diff --git a/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java index a2d7e8ec..c765967d 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java @@ -1,9 +1,14 @@ package until.the.eternity.statistics.application.service; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.domain.entity.daily.ItemDailyStatistics; import until.the.eternity.statistics.domain.mapper.ItemDailyStatisticsMapper; import until.the.eternity.statistics.interfaces.rest.dto.response.ItemDailyStatisticsResponse; @@ -18,23 +23,27 @@ public class ItemDailyStatisticsService { private final ItemDailyStatisticsMapper mapper; /** 아이템별 일간 통계 조회 (itemName, subCategory, topCategory, 날짜 범위) */ + @Cacheable( + cacheNames = CacheNames.STATISTICS_ITEM_DAILY, + key = + "(#itemName ?: '') + ':'" + + " + (#subCategory ?: '') + ':'" + + " + (#topCategory ?: '') + ':'" + + " + #startDate + ':' + #endDate") @Transactional(readOnly = true) - public java.util.List search( + public List search( String itemName, String subCategory, String topCategory, - java.time.LocalDate startDate, - java.time.LocalDate endDate) { - // 날짜 범위 검증 (최대 30일) + LocalDate startDate, + LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateDailyDateRange( startDate, endDate); - // 조회 - java.util.List results = + List results = repository.findByItemAndDateRange( itemName, subCategory, topCategory, startDate, endDate); - // DTO 변환 - return results.stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList()); + return results.stream().map(mapper::toDto).collect(Collectors.toList()); } } diff --git a/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java index 8cc8677d..d40850c4 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java @@ -1,9 +1,14 @@ package until.the.eternity.statistics.application.service; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.domain.entity.weekly.ItemWeeklyStatistics; import until.the.eternity.statistics.domain.mapper.ItemWeeklyStatisticsMapper; import until.the.eternity.statistics.interfaces.rest.dto.response.ItemWeeklyStatisticsResponse; @@ -18,23 +23,27 @@ public class ItemWeeklyStatisticsService { private final ItemWeeklyStatisticsMapper mapper; /** 아이템별 주간 통계 조회 (itemName, subCategory, topCategory, 날짜 범위) */ + @Cacheable( + cacheNames = CacheNames.STATISTICS_ITEM_WEEKLY, + key = + "(#itemName ?: '') + ':'" + + " + (#subCategory ?: '') + ':'" + + " + (#topCategory ?: '') + ':'" + + " + #startDate + ':' + #endDate") @Transactional(readOnly = true) - public java.util.List search( + public List search( String itemName, String subCategory, String topCategory, - java.time.LocalDate startDate, - java.time.LocalDate endDate) { - // 날짜 범위 검증 (최대 4개월) + LocalDate startDate, + LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateWeeklyDateRange( startDate, endDate); - // 조회 - java.util.List results = + List results = repository.findByItemAndDateRange( itemName, subCategory, topCategory, startDate, endDate); - // DTO 변환 - return results.stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList()); + return results.stream().map(mapper::toDto).collect(Collectors.toList()); } } diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java index 1038bcd5..93135629 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java @@ -1,9 +1,14 @@ package until.the.eternity.statistics.application.service; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.domain.entity.daily.SubcategoryDailyStatistics; import until.the.eternity.statistics.domain.mapper.SubcategoryDailyStatisticsMapper; import until.the.eternity.statistics.interfaces.rest.dto.response.SubcategoryDailyStatisticsResponse; @@ -18,21 +23,21 @@ public class SubcategoryDailyStatisticsService { private final SubcategoryDailyStatisticsMapper mapper; /** 서브카테고리별 일간 통계 조회 (subCategory, 날짜 범위) */ + @Cacheable( + cacheNames = CacheNames.STATISTICS_SUBCATEGORY_DAILY, + key = "(#topCategory ?: '') + ':' + (#subCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) - public java.util.List search( - String topCategory, // topCategory는 파라미터로 받지만 조회에는 사용하지 않음 (DB 구조상) + public List search( + String topCategory, String subCategory, - java.time.LocalDate startDate, - java.time.LocalDate endDate) { - // 날짜 범위 검증 (최대 30일) + LocalDate startDate, + LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateDailyDateRange( startDate, endDate); - // 조회 - java.util.List results = + List results = repository.findBySubcategoryAndDateRange(subCategory, startDate, endDate); - // DTO 변환 - return results.stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList()); + return results.stream().map(mapper::toDto).collect(Collectors.toList()); } } diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java index e4d0b5ed..84391115 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java @@ -1,9 +1,14 @@ package until.the.eternity.statistics.application.service; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.domain.entity.weekly.SubcategoryWeeklyStatistics; import until.the.eternity.statistics.domain.mapper.SubcategoryWeeklyStatisticsMapper; import until.the.eternity.statistics.interfaces.rest.dto.response.SubcategoryWeeklyStatisticsResponse; @@ -18,21 +23,21 @@ public class SubcategoryWeeklyStatisticsService { private final SubcategoryWeeklyStatisticsMapper mapper; /** 서브카테고리별 주간 통계 조회 (subCategory, 날짜 범위) */ + @Cacheable( + cacheNames = CacheNames.STATISTICS_SUBCATEGORY_WEEKLY, + key = "(#topCategory ?: '') + ':' + (#subCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) - public java.util.List search( - String topCategory, // topCategory는 파라미터로 받지만 조회에는 사용하지 않음 (DB 구조상) + public List search( + String topCategory, String subCategory, - java.time.LocalDate startDate, - java.time.LocalDate endDate) { - // 날짜 범위 검증 (최대 4개월) + LocalDate startDate, + LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateWeeklyDateRange( startDate, endDate); - // 조회 - java.util.List results = + List results = repository.findBySubcategoryAndDateRange(subCategory, startDate, endDate); - // DTO 변환 - return results.stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList()); + return results.stream().map(mapper::toDto).collect(Collectors.toList()); } } diff --git a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java index d150b7a6..3aabdee4 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java @@ -1,9 +1,14 @@ package until.the.eternity.statistics.application.service; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.domain.entity.daily.TopCategoryDailyStatistics; import until.the.eternity.statistics.domain.mapper.TopCategoryDailyStatisticsMapper; import until.the.eternity.statistics.interfaces.rest.dto.response.TopCategoryDailyStatisticsResponse; @@ -18,18 +23,18 @@ public class TopCategoryDailyStatisticsService { private final TopCategoryDailyStatisticsMapper mapper; /** 탑카테고리별 일간 통계 조회 (topCategory, 날짜 범위) */ + @Cacheable( + cacheNames = CacheNames.STATISTICS_TOPCATEGORY_DAILY, + key = "(#topCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) - public java.util.List search( - String topCategory, java.time.LocalDate startDate, java.time.LocalDate endDate) { - // 날짜 범위 검증 (최대 30일) + public List search( + String topCategory, LocalDate startDate, LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateDailyDateRange( startDate, endDate); - // 조회 - java.util.List results = + List results = repository.findByTopCategoryAndDateRange(topCategory, startDate, endDate); - // DTO 변환 - return results.stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList()); + return results.stream().map(mapper::toDto).collect(Collectors.toList()); } } diff --git a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java index 5d1e7b3c..9717d7ba 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java @@ -1,9 +1,14 @@ package until.the.eternity.statistics.application.service; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.domain.entity.weekly.TopCategoryWeeklyStatistics; import until.the.eternity.statistics.domain.mapper.TopCategoryWeeklyStatisticsMapper; import until.the.eternity.statistics.interfaces.rest.dto.response.TopCategoryWeeklyStatisticsResponse; @@ -18,18 +23,18 @@ public class TopCategoryWeeklyStatisticsService { private final TopCategoryWeeklyStatisticsMapper mapper; /** 탑카테고리별 주간 통계 조회 (topCategory, 날짜 범위) */ + @Cacheable( + cacheNames = CacheNames.STATISTICS_TOPCATEGORY_WEEKLY, + key = "(#topCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) - public java.util.List search( - String topCategory, java.time.LocalDate startDate, java.time.LocalDate endDate) { - // 날짜 범위 검증 (최대 4개월) + public List search( + String topCategory, LocalDate startDate, LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateWeeklyDateRange( startDate, endDate); - // 조회 - java.util.List results = + List results = repository.findByTopCategoryAndDateRange(topCategory, startDate, endDate); - // DTO 변환 - return results.stream().map(mapper::toDto).collect(java.util.stream.Collectors.toList()); + return results.stream().map(mapper::toDto).collect(Collectors.toList()); } } diff --git a/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java index 6f09dffc..94fd0c9c 100644 --- a/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java @@ -2,8 +2,11 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.repository.daily.ItemDailyStatisticsRepository; import until.the.eternity.statistics.repository.daily.SubcategoryDailyStatisticsRepository; import until.the.eternity.statistics.repository.daily.TopCategoryDailyStatisticsRepository; @@ -20,7 +23,45 @@ public class DailyStatisticsService { /** * 당일의 경매 거래 내역을 기반으로 일간 통계를 업데이트 AuctionHistoryScheduler가 실행될 때마다 호출되어 당일 통계만 갱신 순서: * auction_history → ItemDaily → SubcategoryDaily → TopCategoryDaily + * + *

통계 계산 완료 후 일간 통계 캐시 + 오늘/카테고리 기반 랭킹 캐시를 무효화한다. */ + @Caching( + evict = { + // 일간 통계 캐시 + @CacheEvict(cacheNames = CacheNames.STATISTICS_ITEM_DAILY, allEntries = true), + @CacheEvict( + cacheNames = CacheNames.STATISTICS_SUBCATEGORY_DAILY, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.STATISTICS_TOPCATEGORY_DAILY, + allEntries = true), + // 오늘 기준 랭킹 캐시 (item_daily_statistics 기반) + @CacheEvict( + cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, + allEntries = true), + }) @Transactional public void calculateAndSaveCurrentDayStatistics() { log.info("[Current Day Statistics] Starting current day statistics calculation..."); @@ -58,7 +99,43 @@ public void calculateAndSaveCurrentDayStatistics() { /** * 전날의 경매 거래 내역을 기반으로 일간 통계를 최종 확정 매일 새벽 한 번 실행되어 전날 23시대 거래까지 포함한 통계를 완성 순서: auction_history → * ItemDaily → SubcategoryDaily → TopCategoryDaily + * + *

전날 통계 확정 후 변동률 랭킹(어제 대비 오늘)도 함께 무효화한다. */ + @Caching( + evict = { + @CacheEvict(cacheNames = CacheNames.STATISTICS_ITEM_DAILY, allEntries = true), + @CacheEvict( + cacheNames = CacheNames.STATISTICS_SUBCATEGORY_DAILY, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.STATISTICS_TOPCATEGORY_DAILY, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, + allEntries = true), + }) @Transactional public void calculateAndSavePreviousDayStatistics() { log.info("[Previous Day Statistics] Starting previous day statistics finalization..."); diff --git a/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java index 5c5ca2b7..5c5d6a47 100644 --- a/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java @@ -2,8 +2,11 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import until.the.eternity.config.CacheNames; import until.the.eternity.statistics.repository.weekly.ItemWeeklyStatisticsRepository; import until.the.eternity.statistics.repository.weekly.SubcategoryWeeklyStatisticsRepository; import until.the.eternity.statistics.repository.weekly.TopCategoryWeeklyStatisticsRepository; @@ -20,7 +23,27 @@ public class WeeklyStatisticsService { /** * 전주(지난 주 월~일)의 일간 통계를 기반으로 주간 통계를 계산하여 저장 순서: ItemDaily → ItemWeekly → SubcategoryWeekly → * TopCategoryWeekly + * + *

주간 통계 계산 완료 후 주간 통계 캐시 + 주간 랭킹 캐시를 무효화한다. */ + @Caching( + evict = { + // 주간 통계 캐시 + @CacheEvict(cacheNames = CacheNames.STATISTICS_ITEM_WEEKLY, allEntries = true), + @CacheEvict( + cacheNames = CacheNames.STATISTICS_SUBCATEGORY_WEEKLY, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.STATISTICS_TOPCATEGORY_WEEKLY, + allEntries = true), + // 주간 기준 랭킹 캐시 (item_weekly_statistics 기반) + @CacheEvict( + cacheNames = CacheNames.RANKING_PRICE_WEEK_HIGHEST, + allEntries = true), + @CacheEvict( + cacheNames = CacheNames.RANKING_VOLUME_WEEK_POPULAR, + allEntries = true), + }) @Transactional public void calculateAndSaveWeeklyStatistics() { log.info("[Weekly Statistics] Starting weekly statistics calculation..."); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c8fbd4d8..67bf6a9e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -18,6 +18,20 @@ management: spring: application: name: open-api-batch-server + data: + redis: + host: ${REDIS_HOST:localhost} + port: ${REDIS_PORT:6379} + password: ${REDIS_PASSWORD:} + timeout: 3000ms + lettuce: + pool: + max-active: 10 + max-idle: 5 + min-idle: 2 + max-wait: 1000ms + cache: + type: redis elasticsearch: uris: ${ELASTICSEARCH_URIS:http://localhost:9200} username: ${ELASTICSEARCH_USERNAME:} From 363090103f679d8098e565b5fab9ace4753b0043 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 10:24:20 +0900 Subject: [PATCH 02/16] =?UTF-8?q?chore:=20docker-compose=20redis=20?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose-prod.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml index d0917839..97a316c5 100644 --- a/docker-compose-prod.yml +++ b/docker-compose-prod.yml @@ -32,6 +32,11 @@ services: DB_USER: ${DB_USER} DB_PASSWORD: ${DB_PASSWORD} + # === Redis Configuration === + REDIS_HOST: ${REDIS_HOST} + REDIS_PORT: ${REDIS_PORT} + REDIS_PASSWORD: ${REDIS_PASSWORD} + # === Security Configuration === JWT_SECRET_KEY: ${JWT_SECRET_KEY} JWT_ACCESS_TOKEN_VALIDITY: ${JWT_ACCESS_TOKEN_VALIDITY} From 04293786883a4c8a2e301e1ab470ce3898e58a68 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 11:16:41 +0900 Subject: [PATCH 03/16] =?UTF-8?q?fix:=20=EC=9D=B8=EC=B1=88=ED=8A=B8,=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=ED=85=9C,=20=EC=84=B8=EA=B3=B5=20=EC=86=8D?= =?UTF-8?q?=EC=84=B1=20=EC=A0=95=EB=B3=B4=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20redis=20key=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/EnchantInfoService.java | 2 +- .../application/service/ItemInfoService.java | 15 ++++++++------- .../service/MetalwareAttributeInfoService.java | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java index 74dbe94f..2d3f7127 100644 --- a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java +++ b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java @@ -28,7 +28,7 @@ public class EnchantInfoService { @Cacheable( cacheNames = CacheNames.ENCHANT_INFO_ALL, - key = "#pageable.pageNumber + ':' + #pageable.pageSize") + key = "#pageable.pageNumber + ':' + #pageable.pageSize + ':' + #pageable.sort") public Page findAll(Pageable pageable) { return enchantInfoRepository.findAll(pageable).map(EnchantInfoResponse::from); } diff --git a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java index ab7c5bb4..5e7491e4 100644 --- a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java +++ b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java @@ -60,10 +60,11 @@ public List findBySubCategory(String subCategory) { @Cacheable( cacheNames = CacheNames.ITEM_INFO_DETAIL, key = - "(#searchRequest.itemName() ?: '') + ':'" - + " + (#searchRequest.itemTopCategory() ?: '') + ':'" - + " + (#searchRequest.itemSubCategory() ?: '') + ':'" - + " + #pageable.pageNumber + ':' + #pageable.pageSize") + "(#searchRequest.name() ?: '') + ':'" + + " + (#searchRequest.topCategory() ?: '') + ':'" + + " + (#searchRequest.subCategory() ?: '') + ':'" + + " + #pageable.pageNumber + ':' + #pageable.pageSize" + + " + ':' + #pageable.sort") public Page findAllDetail( ItemInfoSearchRequest searchRequest, Pageable pageable) { Page itemInfoPage = @@ -74,9 +75,9 @@ public Page findAllDetail( @Cacheable( cacheNames = CacheNames.ITEM_INFO_SUMMARY, key = - "(#searchRequest.itemName() ?: '') + ':'" - + " + (#searchRequest.itemTopCategory() ?: '') + ':'" - + " + (#searchRequest.itemSubCategory() ?: '') + ':'" + "(#searchRequest.name() ?: '') + ':'" + + " + (#searchRequest.topCategory() ?: '') + ':'" + + " + (#searchRequest.subCategory() ?: '') + ':'" + " + #direction.name()") public List findAllSummary( ItemInfoSearchRequest searchRequest, diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java index 8e8adf7a..eb421905 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java @@ -33,7 +33,7 @@ public int sync() { @Cacheable( cacheNames = CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, - key = "#request.metalware() + ':' + #request.toPageable().pageNumber + ':' + #request.toPageable().pageSize") + key = "#request.metalware() + ':' + (#request.page ?: 1) + ':' + (#request.size ?: 25) + ':' + (#request.direction?.name() ?: 'ASC')") @Transactional(readOnly = true) public Page search( MetalwareAttributeInfoSearchRequest request) { From 6044e4142777659997c97436b2b1eeb592e76e54 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 11:25:01 +0900 Subject: [PATCH 04/16] =?UTF-8?q?fix:=20auction=20history=20search=20redis?= =?UTF-8?q?=20key=20=EC=83=9D=EC=84=B1=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=EC=97=90=20dataTo,=20dateFrom=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/AuctionHistoryService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java index c6adf6da..30a9460e 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java @@ -40,8 +40,11 @@ public class AuctionHistoryService { + " + (#pageRequestDto.sortBy() != null ? #pageRequestDto.sortBy().fieldName : 'dateAuctionBuy') + ':'" + " + (#pageRequestDto.direction() != null ? #pageRequestDto.direction().code : 'DESC') + ':'" + " + (#requestDto.itemName() ?: '') + ':'" + + " + (#requestDto.isExactItemName() ?: false) + ':'" + " + (#requestDto.itemTopCategory() ?: '') + ':'" - + " + (#requestDto.itemSubCategory() ?: '')", + + " + (#requestDto.itemSubCategory() ?: '') + ':'" + + " + (#requestDto.dateAuctionBuyRequest()?.dateAuctionBuyFrom() ?: '') + ':'" + + " + (#requestDto.dateAuctionBuyRequest()?.dateAuctionBuyTo() ?: '')", condition = "#requestDto.itemOptionSearchRequest() == null" + " and #requestDto.enchantSearchRequest() == null" From 2c08b90eab6adb44b10146849d538af7768fdd8f Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 14:15:51 +0900 Subject: [PATCH 05/16] =?UTF-8?q?feat:=20redis=20=EC=9E=A5=EC=95=A0=20?= =?UTF-8?q?=EC=8B=9C=20db=20=EC=A7=81=EC=A0=91=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/RedisCacheErrorHandler.java | 48 +++++++++++++++++++ .../the/eternity/config/RedisConfig.java | 9 +++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java diff --git a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java new file mode 100644 index 00000000..77186301 --- /dev/null +++ b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java @@ -0,0 +1,48 @@ +package until.the.eternity.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.cache.interceptor.CacheErrorHandler; + +/** + * Redis 장애 시 캐시 오류를 로깅만 하고 예외를 전파하지 않는 핸들러. + * + *

Redis가 다운되어도 캐시를 건너뛰고 실제 메서드(DB 조회 등)를 실행해 서비스를 유지한다. + */ +@Slf4j +public class RedisCacheErrorHandler implements CacheErrorHandler { + + @Override + public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { + log.warn( + "[Cache] GET 실패 - cache={}, key={}, error={}", + cache.getName(), + key, + exception.getMessage()); + } + + @Override + public void handleCachePutError( + RuntimeException exception, Cache cache, Object key, Object value) { + log.warn( + "[Cache] PUT 실패 - cache={}, key={}, error={}", + cache.getName(), + key, + exception.getMessage()); + } + + @Override + public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { + log.warn( + "[Cache] EVICT 실패 - cache={}, key={}, error={}", + cache.getName(), + key, + exception.getMessage()); + } + + @Override + public void handleCacheClearError(RuntimeException exception, Cache cache) { + log.warn( + "[Cache] CLEAR 실패 - cache={}, error={}", cache.getName(), exception.getMessage()); + } +} diff --git a/src/main/java/until/the/eternity/config/RedisConfig.java b/src/main/java/until/the/eternity/config/RedisConfig.java index c7c473fc..05f1a8b9 100644 --- a/src/main/java/until/the/eternity/config/RedisConfig.java +++ b/src/main/java/until/the/eternity/config/RedisConfig.java @@ -7,6 +7,8 @@ import java.util.HashMap; import java.util.Map; import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.CacheErrorHandler; +import org.springframework.cache.interceptor.CachingConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; @@ -18,7 +20,12 @@ @Configuration @EnableCaching -public class RedisConfig { +public class RedisConfig implements CachingConfigurer { + + @Override + public CacheErrorHandler errorHandler() { + return new RedisCacheErrorHandler(); + } @Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { From dcfdb290696275f4aa132fbc3e22c49ddab5bc68 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 14:21:35 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat:=20auction=20history=20redis=20warm?= =?UTF-8?q?=20up=20page=20=EB=B2=94=EC=9C=84=201~2=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/AuctionHistoryCacheWarmupService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java index bafd0a49..4d56d246 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java @@ -19,7 +19,7 @@ *

    *
  1. auction-history:search 캐시 전체 무효화 *
  2. auction_history 기반 역대 랭킹 캐시 무효화 (ALLTIME_HIGHEST, ALLTIME_MONTH_VOLUME) - *
  3. page 1~5 × size 20 × sortField 3종 × direction 2종 = 30가지 조합 캐시 워밍 + *
  4. page 1~2 × size 20 × sortField 3종 × direction 2종 = 12가지 조합 캐시 워밍 *
*/ @Slf4j @@ -28,7 +28,7 @@ public class AuctionHistoryCacheWarmupService { private static final int WARMUP_SIZE = 20; - private static final int WARMUP_MAX_PAGE = 5; + private static final int WARMUP_MAX_PAGE = 2; private final AuctionHistoryService auctionHistoryService; private final CacheManager cacheManager; From 90a29f353617293a2db4bcad36ea9ebd95b07fb9 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Sat, 28 Feb 2026 14:22:10 +0900 Subject: [PATCH 07/16] =?UTF-8?q?fix:=20=ED=86=B5=EA=B3=84=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=ED=95=A8=EC=88=98=20=EC=BA=90=EC=8B=B1=20?= =?UTF-8?q?=ED=82=A4=EC=97=90=EC=84=9C=20topcategory=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/SubcategoryDailyStatisticsService.java | 2 +- .../application/service/SubcategoryWeeklyStatisticsService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java index 93135629..7845aecf 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java @@ -25,7 +25,7 @@ public class SubcategoryDailyStatisticsService { /** 서브카테고리별 일간 통계 조회 (subCategory, 날짜 범위) */ @Cacheable( cacheNames = CacheNames.STATISTICS_SUBCATEGORY_DAILY, - key = "(#topCategory ?: '') + ':' + (#subCategory ?: '') + ':' + #startDate + ':' + #endDate") + key = "(#subCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) public List search( String topCategory, diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java index 84391115..95616c4e 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java @@ -25,7 +25,7 @@ public class SubcategoryWeeklyStatisticsService { /** 서브카테고리별 주간 통계 조회 (subCategory, 날짜 범위) */ @Cacheable( cacheNames = CacheNames.STATISTICS_SUBCATEGORY_WEEKLY, - key = "(#topCategory ?: '') + ':' + (#subCategory ?: '') + ':' + #startDate + ':' + #endDate") + key = "(#subCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) public List search( String topCategory, From 594f72d3ee7f717a1ca29a0fa19a4e1cc1ea4545 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Tue, 3 Mar 2026 12:44:12 +0900 Subject: [PATCH 08/16] =?UTF-8?q?fix:=20CachingConfigurer=20Import=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuctionHistoryCacheWarmupService.java | 3 +- .../AuctionHistoryQueryDslRepository.java | 4 +- .../controller/AuctionHistoryController.java | 2 +- .../request/AuctionHistorySearchRequest.java | 6 +- .../dto/request/MetalwareSearchRequest.java | 3 +- .../controller/AuctionRealtimeController.java | 2 +- .../request/AuctionRealtimeSearchRequest.java | 6 +- .../service/AuctionSearchOptionService.java | 2 +- .../config/RedisCacheErrorHandler.java | 3 +- .../service/EnchantInfoService.java | 4 +- .../MetalwareAttributeInfoService.java | 3 +- .../SubcategoryDailyStatisticsService.java | 5 +- .../SubcategoryWeeklyStatisticsService.java | 5 +- .../service/DailyStatisticsService.java | 56 +++++-------------- .../service/WeeklyStatisticsService.java | 8 +-- .../service/AuctionHistoryServiceTest.java | 3 +- 16 files changed, 41 insertions(+), 74 deletions(-) diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java index 4d56d246..24ad80f7 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java @@ -48,7 +48,8 @@ private void evictCaches() { // auction_history 전체를 직접 쿼리하는 역대 랭킹도 함께 무효화 clearCache(CacheNames.RANKING_ALLTIME_HIGHEST); clearCache(CacheNames.RANKING_ALLTIME_MONTH_VOLUME); - log.info("[Cache Warmup] Evicted: {}, {}, {}", + log.info( + "[Cache Warmup] Evicted: {}, {}, {}", CacheNames.AUCTION_HISTORY_SEARCH, CacheNames.RANKING_ALLTIME_HIGHEST, CacheNames.RANKING_ALLTIME_MONTH_VOLUME); diff --git a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java index 17850b42..0deb6dfc 100644 --- a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java @@ -203,7 +203,9 @@ private BooleanBuilder buildHistoryPredicate( QAuctionHistoryItemOption mwOpt = new QAuctionHistoryItemOption("mw" + i); NumberTemplate mwLevel = Expressions.numberTemplate( - Integer.class, "CAST(NULLIF({0}, '') AS integer)", mwOpt.optionValue2); + Integer.class, + "CAST(NULLIF({0}, '') AS integer)", + mwOpt.optionValue2); var mwSubQuery = JPAExpressions.select(mwOpt.auctionHistory.auctionBuyId) diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/controller/AuctionHistoryController.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/controller/AuctionHistoryController.java index 67ee1885..e741c7ce 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/controller/AuctionHistoryController.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/controller/AuctionHistoryController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import until.the.eternity.common.annotation.MetalwareParameters; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; @@ -15,6 +14,7 @@ import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; import until.the.eternity.auctionhistory.interfaces.rest.dto.response.AuctionHistoryDetailResponse; import until.the.eternity.auctionhistory.interfaces.rest.dto.response.ItemOptionResponse; +import until.the.eternity.common.annotation.MetalwareParameters; import until.the.eternity.common.request.PageRequestDto; import until.the.eternity.common.response.PageResponseDto; diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java index 87c01cf1..80b12c29 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java @@ -7,7 +7,8 @@ @Schema(description = "경매 거래내역 검색 조건") public record AuctionHistorySearchRequest( @Schema(description = "아이템 이름 (like 검색)", example = "페러시우스 타이탄 블레이드") String itemName, - @Schema(description = "아이템 이름 완전 일치 검색 여부 (true: eq, false: like)", + @Schema( + description = "아이템 이름 완전 일치 검색 여부 (true: eq, false: like)", requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "false", example = "false") @@ -18,7 +19,8 @@ public record AuctionHistorySearchRequest( @Schema(description = "가격 검색 조건") PriceSearchRequest priceSearchRequest, @Schema(description = "아이템 옵션 검색 조건") ItemOptionSearchRequest itemOptionSearchRequest, @Schema(description = "인챈트 검색 조건") EnchantSearchRequest enchantSearchRequest, - @Schema(description = "세공 검색 조건 목록 (최대 3개, AND 조건으로 검색)", + @Schema( + description = "세공 검색 조건 목록 (최대 3개, AND 조건으로 검색)", requiredMode = Schema.RequiredMode.NOT_REQUIRED, hidden = true) List metalwareSearchRequests) {} diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/MetalwareSearchRequest.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/MetalwareSearchRequest.java index d0b3c64d..37f7e63a 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/MetalwareSearchRequest.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/MetalwareSearchRequest.java @@ -6,8 +6,7 @@ public record MetalwareSearchRequest( @Schema(description = "세공 이름 (완전 일치)", example = "불의 연성술") String metalware, @Schema(description = "세공 레벨 시작값 (null이면 1로 처리)", example = "1") Integer levelFrom, - @Schema(description = "세공 레벨 종료값 (null이면 30으로 처리)", example = "30") - Integer levelTo) { + @Schema(description = "세공 레벨 종료값 (null이면 30으로 처리)", example = "30") Integer levelTo) { public int resolvedLevelFrom() { return levelFrom != null ? levelFrom : 1; diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/controller/AuctionRealtimeController.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/controller/AuctionRealtimeController.java index e13725d3..bc025406 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/controller/AuctionRealtimeController.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/controller/AuctionRealtimeController.java @@ -2,7 +2,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import until.the.eternity.common.annotation.MetalwareParameters; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; @@ -13,6 +12,7 @@ import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.RealtimePageRequestDto; import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.AuctionRealtimeDetailResponse; import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.RealtimeItemOptionResponse; +import until.the.eternity.common.annotation.MetalwareParameters; import until.the.eternity.common.response.PageResponseDto; @RequestMapping("/auction-realtime") diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java index df2d1f0b..3c66e56b 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java @@ -11,7 +11,8 @@ @Schema(description = "실시간 경매장 검색 조건") public record AuctionRealtimeSearchRequest( @Schema(description = "아이템 이름 (like 검색)", example = "페러시우스 타이탄 블레이드") String itemName, - @Schema(description = "아이템 이름 완전 일치 검색 여부 (true: eq, false: like)", + @Schema( + description = "아이템 이름 완전 일치 검색 여부 (true: eq, false: like)", requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "false", example = "false") @@ -21,7 +22,8 @@ public record AuctionRealtimeSearchRequest( @Schema(description = "가격 검색 조건") PriceSearchRequest priceSearchRequest, @Schema(description = "아이템 옵션 검색 조건") ItemOptionSearchRequest itemOptionSearchRequest, @Schema(description = "인챈트 검색 조건") EnchantSearchRequest enchantSearchRequest, - @Schema(description = "세공 검색 조건 목록 (최대 3개, AND 조건으로 검색)", + @Schema( + description = "세공 검색 조건 목록 (최대 3개, AND 조건으로 검색)", requiredMode = Schema.RequiredMode.NOT_REQUIRED, hidden = true) List metalwareSearchRequests) {} diff --git a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java index 95a7e73f..0c3dca98 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java @@ -9,11 +9,11 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import until.the.eternity.config.CacheNames; import until.the.eternity.auctionsearchoption.domain.entity.AuctionSearchOptionMetadata; import until.the.eternity.auctionsearchoption.domain.repository.AuctionSearchOptionRepositoryPort; import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.FieldMetadata; import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.SearchOptionMetadataResponse; +import until.the.eternity.config.CacheNames; @Slf4j @Service diff --git a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java index 77186301..8ce10832 100644 --- a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java +++ b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java @@ -42,7 +42,6 @@ public void handleCacheEvictError(RuntimeException exception, Cache cache, Objec @Override public void handleCacheClearError(RuntimeException exception, Cache cache) { - log.warn( - "[Cache] CLEAR 실패 - cache={}, error={}", cache.getName(), exception.getMessage()); + log.warn("[Cache] CLEAR 실패 - cache={}, error={}", cache.getName(), exception.getMessage()); } } diff --git a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java index 2d3f7127..edf03138 100644 --- a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java +++ b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java @@ -33,9 +33,7 @@ public Page findAll(Pageable pageable) { return enchantInfoRepository.findAll(pageable).map(EnchantInfoResponse::from); } - @Cacheable( - cacheNames = CacheNames.ENCHANT_INFO_FULLNAMES, - key = "#affixPosition ?: 'all'") + @Cacheable(cacheNames = CacheNames.ENCHANT_INFO_FULLNAMES, key = "#affixPosition ?: 'all'") public List findAllFullnames(String affixPosition) { if (affixPosition != null) { if (!ALLOWED_AFFIX_POSITIONS.contains(affixPosition)) { diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java index eb421905..aed51db2 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java @@ -33,7 +33,8 @@ public int sync() { @Cacheable( cacheNames = CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, - key = "#request.metalware() + ':' + (#request.page ?: 1) + ':' + (#request.size ?: 25) + ':' + (#request.direction?.name() ?: 'ASC')") + key = + "#request.metalware() + ':' + (#request.page ?: 1) + ':' + (#request.size ?: 25) + ':' + (#request.direction?.name() ?: 'ASC')") @Transactional(readOnly = true) public Page search( MetalwareAttributeInfoSearchRequest request) { diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java index 7845aecf..02b3d4ca 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java @@ -28,10 +28,7 @@ public class SubcategoryDailyStatisticsService { key = "(#subCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) public List search( - String topCategory, - String subCategory, - LocalDate startDate, - LocalDate endDate) { + String topCategory, String subCategory, LocalDate startDate, LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateDailyDateRange( startDate, endDate); diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java index 95616c4e..62c7bf00 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java @@ -28,10 +28,7 @@ public class SubcategoryWeeklyStatisticsService { key = "(#subCategory ?: '') + ':' + #startDate + ':' + #endDate") @Transactional(readOnly = true) public List search( - String topCategory, - String subCategory, - LocalDate startDate, - LocalDate endDate) { + String topCategory, String subCategory, LocalDate startDate, LocalDate endDate) { until.the.eternity.statistics.util.DateRangeValidator.validateWeeklyDateRange( startDate, endDate); diff --git a/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java index 94fd0c9c..2769ed4e 100644 --- a/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/service/DailyStatisticsService.java @@ -37,30 +37,16 @@ public class DailyStatisticsService { cacheNames = CacheNames.STATISTICS_TOPCATEGORY_DAILY, allEntries = true), // 오늘 기준 랭킹 캐시 (item_daily_statistics 기반) - @CacheEvict( - cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, - allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, allEntries = true), @CacheEvict( cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, - allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, allEntries = true), }) @Transactional public void calculateAndSaveCurrentDayStatistics() { @@ -111,30 +97,16 @@ public void calculateAndSaveCurrentDayStatistics() { @CacheEvict( cacheNames = CacheNames.STATISTICS_TOPCATEGORY_DAILY, allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, - allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, allEntries = true), @CacheEvict( cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, - allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, allEntries = true), }) @Transactional public void calculateAndSavePreviousDayStatistics() { diff --git a/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java index 5c5d6a47..ca191803 100644 --- a/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/service/WeeklyStatisticsService.java @@ -37,12 +37,8 @@ public class WeeklyStatisticsService { cacheNames = CacheNames.STATISTICS_TOPCATEGORY_WEEKLY, allEntries = true), // 주간 기준 랭킹 캐시 (item_weekly_statistics 기반) - @CacheEvict( - cacheNames = CacheNames.RANKING_PRICE_WEEK_HIGHEST, - allEntries = true), - @CacheEvict( - cacheNames = CacheNames.RANKING_VOLUME_WEEK_POPULAR, - allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_PRICE_WEEK_HIGHEST, allEntries = true), + @CacheEvict(cacheNames = CacheNames.RANKING_VOLUME_WEEK_POPULAR, allEntries = true), }) @Transactional public void calculateAndSaveWeeklyStatistics() { diff --git a/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java b/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java index b9ea3a5f..3d60f033 100644 --- a/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java +++ b/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java @@ -42,7 +42,8 @@ class AuctionHistoryServiceTest { void search_should_return_paged_response() { // given AuctionHistorySearchRequest searchRequest = - new AuctionHistorySearchRequest(null, null, null, null, null, null, null, null, null); + new AuctionHistorySearchRequest( + null, null, null, null, null, null, null, null, null); PageRequestDto pageRequestDto = mock(PageRequestDto.class); Pageable pageable = PageRequest.of(0, 10); when(pageRequestDto.toPageable()).thenReturn(pageable); From e8c2359f114dbd13992f89bc922b683403512a7b Mon Sep 17 00:00:00 2001 From: dev-ant Date: Tue, 3 Mar 2026 12:59:09 +0900 Subject: [PATCH 09/16] =?UTF-8?q?fix:=20RedisConfig=20Import=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../until/the/eternity/config/RedisConfig.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/until/the/eternity/config/RedisConfig.java b/src/main/java/until/the/eternity/config/RedisConfig.java index 05f1a8b9..965b9506 100644 --- a/src/main/java/until/the/eternity/config/RedisConfig.java +++ b/src/main/java/until/the/eternity/config/RedisConfig.java @@ -6,9 +6,9 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import org.springframework.cache.annotation.CachingConfigurer; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheErrorHandler; -import org.springframework.cache.interceptor.CachingConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; @@ -69,8 +69,7 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) // 검색 옵션 메타데이터 - 24시간 TTL (사실상 정적 데이터) configs.put( - CacheNames.SEARCH_OPTION_ALL_ACTIVE, - defaultConfig.entryTtl(Duration.ofHours(24))); + CacheNames.SEARCH_OPTION_ALL_ACTIVE, defaultConfig.entryTtl(Duration.ofHours(24))); // 마스터 데이터 - 1시간 TTL (sync API 호출 시 evict) Duration masterTtl = Duration.ofHours(1); @@ -82,8 +81,7 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) configs.put(CacheNames.ENCHANT_INFO_ALL, defaultConfig.entryTtl(masterTtl)); configs.put(CacheNames.ENCHANT_INFO_FULLNAMES, defaultConfig.entryTtl(masterTtl)); configs.put(CacheNames.METALWARE_INFO_ALL, defaultConfig.entryTtl(masterTtl)); - configs.put( - CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, defaultConfig.entryTtl(masterTtl)); + configs.put(CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, defaultConfig.entryTtl(masterTtl)); // 통계 - 30분 TTL (이벤트 기반 eviction으로 실시간 반영) Duration statsTtl = Duration.ofMinutes(30); @@ -96,12 +94,10 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) // 실시간 경매 - 12분 TTL (10분 배치 + 여유 2분) configs.put( - CacheNames.AUCTION_REALTIME_SEARCH, - defaultConfig.entryTtl(Duration.ofMinutes(12))); + CacheNames.AUCTION_REALTIME_SEARCH, defaultConfig.entryTtl(Duration.ofMinutes(12))); // 경매 거래 내역 - 2시간 TTL (배치 완료 시 evict + warmup) - configs.put( - CacheNames.AUCTION_HISTORY_SEARCH, defaultConfig.entryTtl(Duration.ofHours(2))); + configs.put(CacheNames.AUCTION_HISTORY_SEARCH, defaultConfig.entryTtl(Duration.ofHours(2))); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(defaultConfig) From 703eaff6712db3225bec2b5f45854765ecee7f8a Mon Sep 17 00:00:00 2001 From: dev-ant Date: Thu, 5 Mar 2026 08:14:43 +0900 Subject: [PATCH 10/16] =?UTF-8?q?feat:=20=EA=B2=BD=EB=A7=A4=EC=9E=A5=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EC=8B=9C=20=EA=B8=B0=EB=B3=B8=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=20only=EB=A9=B4=20=EA=B3=A0=EA=B8=89=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EB=A1=9C=EC=A7=81=20=EC=8A=A4=ED=82=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuctionHistoryCacheWarmupService.java | 3 +- .../AuctionHistoryQueryDslRepository.java | 77 +++++++++++---- .../AuctionRealtimeQueryDslRepository.java | 97 ++++++++++++++++--- .../request/AuctionRealtimeSearchRequest.java | 1 + .../dto/request/DateAuctionExpireRequest.java | 10 ++ 5 files changed, 150 insertions(+), 38 deletions(-) create mode 100644 src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/DateAuctionExpireRequest.java diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java index 24ad80f7..c87cf7e4 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java @@ -34,7 +34,8 @@ public class AuctionHistoryCacheWarmupService { private final CacheManager cacheManager; /** - * 캐시 무효화 후 기본 30가지 조합을 선제적으로 워밍한다. + * <<<<<<< HEAD 캐시 무효화 후 기본 30가지 조합을 선제적으로 워밍한다. ======= 캐시 무효화 후 기본 12가지 조합(page 1~2 × size 20 + * × sortField 3종 × direction 2종)을 선제적으로 워밍한다. >>>>>>> 40261cb1cdfa017f341bfbde515c64716860b68f * *

빈 검색 조건(필터 없음) 기준으로 워밍하므로, 단순 목록 조회 요청에 즉시 캐시 히트가 발생한다. */ diff --git a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java index 0deb6dfc..f88d73f8 100644 --- a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java @@ -43,30 +43,27 @@ public Page search(AuctionHistorySearchRequest condition, Pageab QAuctionHistory ah = QAuctionHistory.auctionHistory; QAuctionHistoryItemOption aio = QAuctionHistoryItemOption.auctionHistoryItemOption; + OptionConditionResult optionResult = buildOptionConditionResult(condition); + boolean hasItemOptionFilter = hasEffectiveItemOptionFilter(optionResult); + boolean hasEnchantFilter = hasEnchantFilter(condition); + boolean hasMetalwareFilter = hasMetalwareFilter(condition); + boolean isBasicSearchOnly = + !(hasItemOptionFilter || hasEnchantFilter || hasMetalwareFilter); + // 1단계: 거래내역 조건 빌드 - BooleanBuilder historyBuilder = buildHistoryPredicate(condition, ah); + BooleanBuilder historyBuilder = buildHistoryPredicate(condition, ah, !isBasicSearchOnly); // 2단계: 옵션 조건이 있으면 서브쿼리 추가 - if (condition.itemOptionSearchRequest() != null) { - // 서브쿼리용 별도 QAuctionHistoryItemOption 인스턴스 + if (hasItemOptionFilter) { QAuctionHistoryItemOption subOption = new QAuctionHistoryItemOption("subOption"); - OptionConditionResult optionResult = - buildItemOptionConditions(condition.itemOptionSearchRequest(), subOption); - - // 옵션 조건이 실제로 있는 경우에만 서브쿼리 추가 - if (optionResult.builder().hasValue() && optionResult.count() > 0) { - // 서브쿼리: 옵션 조건을 만족하는 auction_history_id 찾기 - // GROUP BY + HAVING COUNT로 모든 조건을 만족하는 거래내역만 필터링 - var subQuery = - JPAExpressions.select(subOption.auctionHistory.auctionBuyId) - .from(subOption) - .where(optionResult.builder()) - .groupBy(subOption.auctionHistory.auctionBuyId) - .having(subOption.count().eq((long) optionResult.count())); - - // 메인 쿼리에 서브쿼리 결과 적용 - historyBuilder.and(ah.auctionBuyId.in(subQuery)); - } + var subQuery = + JPAExpressions.select(subOption.auctionHistory.auctionBuyId) + .from(subOption) + .where(optionResult.builder()) + .groupBy(subOption.auctionHistory.auctionBuyId) + .having(subOption.count().eq((long) optionResult.count())); + + historyBuilder.and(ah.auctionBuyId.in(subQuery)); } // 3단계: 정렬 조건 빌드 @@ -109,7 +106,7 @@ public Page search(AuctionHistorySearchRequest condition, Pageab /** 거래내역 기본 조건 빌드 (카테고리, 아이템명, 가격, 거래일자) */ private BooleanBuilder buildHistoryPredicate( - AuctionHistorySearchRequest c, QAuctionHistory ah) { + AuctionHistorySearchRequest c, QAuctionHistory ah, boolean includeAdvancedFilters) { BooleanBuilder builder = new BooleanBuilder(); // 기본 조건들 @@ -158,6 +155,10 @@ private BooleanBuilder buildHistoryPredicate( } } + if (!includeAdvancedFilters) { + return builder; + } + // 인챈트 검색 조건 if (c.enchantSearchRequest() != null) { String enchantPrefix = c.enchantSearchRequest().enchantPrefix(); @@ -225,6 +226,40 @@ private BooleanBuilder buildHistoryPredicate( return builder; } + private OptionConditionResult buildOptionConditionResult( + AuctionHistorySearchRequest condition) { + if (condition.itemOptionSearchRequest() == null) { + return null; + } + QAuctionHistoryItemOption subOption = new QAuctionHistoryItemOption("subOption"); + return buildItemOptionConditions(condition.itemOptionSearchRequest(), subOption); + } + + private boolean hasEffectiveItemOptionFilter(OptionConditionResult optionResult) { + return optionResult != null + && optionResult.builder().hasValue() + && optionResult.count() > 0; + } + + private boolean hasEnchantFilter(AuctionHistorySearchRequest condition) { + if (condition.enchantSearchRequest() == null) { + return false; + } + String prefix = condition.enchantSearchRequest().enchantPrefix(); + String suffix = condition.enchantSearchRequest().enchantSuffix(); + return (prefix != null && !prefix.isBlank()) || (suffix != null && !suffix.isBlank()); + } + + private boolean hasMetalwareFilter(AuctionHistorySearchRequest condition) { + return condition.metalwareSearchRequests() != null + && condition.metalwareSearchRequests().stream() + .anyMatch( + mw -> + mw != null + && mw.metalware() != null + && !mw.metalware().isBlank()); + } + /** 옵션 검색 조건 빌드 (서브쿼리용) */ private OptionConditionResult buildItemOptionConditions( ItemOptionSearchRequest opt, QAuctionHistoryItemOption aio) { diff --git a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java index 3819543e..d6ce8ded 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java @@ -8,6 +8,9 @@ import com.querydsl.core.types.dsl.NumberTemplate; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; @@ -24,6 +27,7 @@ import until.the.eternity.auctionitem.domain.entity.QAuctionRealtimeItem; import until.the.eternity.auctionitem.domain.entity.QAuctionRealtimeItemOption; import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.DateAuctionExpireRequest; @Component @RequiredArgsConstructor @@ -40,25 +44,27 @@ public Page search( QAuctionRealtimeItem ar = QAuctionRealtimeItem.auctionRealtimeItem; QAuctionRealtimeItemOption aro = QAuctionRealtimeItemOption.auctionRealtimeItemOption; + OptionConditionResult optionResult = buildOptionConditionResult(condition); + boolean hasItemOptionFilter = hasEffectiveItemOptionFilter(optionResult); + boolean hasEnchantFilter = hasEnchantFilter(condition); + boolean hasMetalwareFilter = hasMetalwareFilter(condition); + boolean isBasicSearchOnly = + !(hasItemOptionFilter || hasEnchantFilter || hasMetalwareFilter); + // 1단계: 기본 조건 빌드 - BooleanBuilder itemBuilder = buildItemPredicate(condition, ar); + BooleanBuilder itemBuilder = buildItemPredicate(condition, ar, !isBasicSearchOnly); // 2단계: 옵션 조건이 있으면 서브쿼리 추가 - if (condition.itemOptionSearchRequest() != null) { + if (hasItemOptionFilter) { QAuctionRealtimeItemOption subOption = new QAuctionRealtimeItemOption("subOption"); - OptionConditionResult optionResult = - buildItemOptionConditions(condition.itemOptionSearchRequest(), subOption); - - if (optionResult.builder().hasValue() && optionResult.count() > 0) { - var subQuery = - JPAExpressions.select(subOption.auctionRealtimeItem.id) - .from(subOption) - .where(optionResult.builder()) - .groupBy(subOption.auctionRealtimeItem.id) - .having(subOption.count().eq((long) optionResult.count())); - - itemBuilder.and(ar.id.in(subQuery)); - } + var subQuery = + JPAExpressions.select(subOption.auctionRealtimeItem.id) + .from(subOption) + .where(optionResult.builder()) + .groupBy(subOption.auctionRealtimeItem.id) + .having(subOption.count().eq((long) optionResult.count())); + + itemBuilder.and(ar.id.in(subQuery)); } // 3단계: 정렬 조건 빌드 @@ -99,7 +105,9 @@ public Page search( /** 기본 조건 빌드 (카테고리, 아이템명, 가격) */ private BooleanBuilder buildItemPredicate( - AuctionRealtimeSearchRequest c, QAuctionRealtimeItem ar) { + AuctionRealtimeSearchRequest c, + QAuctionRealtimeItem ar, + boolean includeAdvancedFilters) { BooleanBuilder builder = new BooleanBuilder(); if (c.itemTopCategory() != null && !c.itemTopCategory().isBlank()) { @@ -126,6 +134,29 @@ private BooleanBuilder buildItemPredicate( } } + if (c.dateAuctionExpireRequest() != null) { + DateAuctionExpireRequest date = c.dateAuctionExpireRequest(); + if (date.dateAuctionExpireFrom() != null && !date.dateAuctionExpireFrom().isBlank()) { + Instant fromInstant = + LocalDate.parse(date.dateAuctionExpireFrom()) + .atStartOfDay(ZoneId.systemDefault()) + .toInstant(); + builder.and(ar.dateAuctionExpire.goe(fromInstant)); + } + if (date.dateAuctionExpireTo() != null && !date.dateAuctionExpireTo().isBlank()) { + Instant toInstant = + LocalDate.parse(date.dateAuctionExpireTo()) + .plusDays(1) + .atStartOfDay(ZoneId.systemDefault()) + .toInstant(); + builder.and(ar.dateAuctionExpire.lt(toInstant)); + } + } + + if (!includeAdvancedFilters) { + return builder; + } + // 인챈트 검색 조건 if (c.enchantSearchRequest() != null) { String enchantPrefix = c.enchantSearchRequest().enchantPrefix(); @@ -193,6 +224,40 @@ private BooleanBuilder buildItemPredicate( return builder; } + private OptionConditionResult buildOptionConditionResult( + AuctionRealtimeSearchRequest condition) { + if (condition.itemOptionSearchRequest() == null) { + return null; + } + QAuctionRealtimeItemOption subOption = new QAuctionRealtimeItemOption("subOption"); + return buildItemOptionConditions(condition.itemOptionSearchRequest(), subOption); + } + + private boolean hasEffectiveItemOptionFilter(OptionConditionResult optionResult) { + return optionResult != null + && optionResult.builder().hasValue() + && optionResult.count() > 0; + } + + private boolean hasEnchantFilter(AuctionRealtimeSearchRequest condition) { + if (condition.enchantSearchRequest() == null) { + return false; + } + String prefix = condition.enchantSearchRequest().enchantPrefix(); + String suffix = condition.enchantSearchRequest().enchantSuffix(); + return (prefix != null && !prefix.isBlank()) || (suffix != null && !suffix.isBlank()); + } + + private boolean hasMetalwareFilter(AuctionRealtimeSearchRequest condition) { + return condition.metalwareSearchRequests() != null + && condition.metalwareSearchRequests().stream() + .anyMatch( + mw -> + mw != null + && mw.metalware() != null + && !mw.metalware().isBlank()); + } + /** 옵션 검색 조건 빌드 (서브쿼리용) */ private OptionConditionResult buildItemOptionConditions( ItemOptionSearchRequest opt, QAuctionRealtimeItemOption aro) { diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java index 3c66e56b..52c78b90 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java @@ -20,6 +20,7 @@ public record AuctionRealtimeSearchRequest( @Schema(description = "대분류 카테고리", example = "근거리 장비") String itemTopCategory, @Schema(description = "소분류 카테고리", example = "검") String itemSubCategory, @Schema(description = "가격 검색 조건") PriceSearchRequest priceSearchRequest, + @Schema(description = "거래 마감 일시 조건") DateAuctionExpireRequest dateAuctionExpireRequest, @Schema(description = "아이템 옵션 검색 조건") ItemOptionSearchRequest itemOptionSearchRequest, @Schema(description = "인챈트 검색 조건") EnchantSearchRequest enchantSearchRequest, @Schema( diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/DateAuctionExpireRequest.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/DateAuctionExpireRequest.java new file mode 100644 index 00000000..ed2bcdc5 --- /dev/null +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/DateAuctionExpireRequest.java @@ -0,0 +1,10 @@ +package until.the.eternity.auctionrealtime.interfaces.rest.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "거래 마감 일시 조건") +public record DateAuctionExpireRequest( + @Schema(description = "거래 마감 일시 시작 범위", example = "2026-02-01") + String dateAuctionExpireFrom, + @Schema(description = "거래 마감 일시 종료 범위", example = "2026-02-11") + String dateAuctionExpireTo) {} From 96602f2f353ab9f3ba729febf60c3dd619e8b8e3 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Thu, 5 Mar 2026 08:56:49 +0900 Subject: [PATCH 11/16] =?UTF-8?q?fix:=20auction=20request=20dto=EC=97=90?= =?UTF-8?q?=20date=20=EA=B8=B0=EB=B3=B8=EA=B0=92=20=ED=95=9C=EB=8B=AC?= =?UTF-8?q?=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuctionHistoryQueryDslRepository.java | 3 +- .../request/AuctionHistorySearchRequest.java | 16 +++- .../AuctionRealtimeQueryDslRepository.java | 2 +- src/main/resources/application.yml | 2 +- .../service/AuctionRealtimeServiceTest.java | 82 +++++++++++++++++++ 5 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java diff --git a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java index f88d73f8..d61e3a06 100644 --- a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java @@ -98,8 +98,7 @@ public Page search(AuctionHistorySearchRequest condition, Pageab .fetch(); // Count 쿼리 (JOIN 없이 실행) - Long total = - queryFactory.select(ah.countDistinct()).from(ah).where(historyBuilder).fetchOne(); + Long total = queryFactory.select(ah.count()).from(ah).where(historyBuilder).fetchOne(); return new PageImpl<>(content, pageable, total == null ? 0L : total); } diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java index 80b12c29..1b616f5d 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionhistory.interfaces.rest.dto.request; import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDate; import java.util.List; /** 경매 히스토리 검색 조건 DTO - 페이지네이션 포함 */ @@ -23,4 +24,17 @@ public record AuctionHistorySearchRequest( description = "세공 검색 조건 목록 (최대 3개, AND 조건으로 검색)", requiredMode = Schema.RequiredMode.NOT_REQUIRED, hidden = true) - List metalwareSearchRequests) {} + List metalwareSearchRequests) { + + public AuctionHistorySearchRequest { + if (dateAuctionBuyRequest == null + || ((dateAuctionBuyRequest.dateAuctionBuyFrom() == null + || dateAuctionBuyRequest.dateAuctionBuyFrom().isBlank()) + && (dateAuctionBuyRequest.dateAuctionBuyTo() == null + || dateAuctionBuyRequest.dateAuctionBuyTo().isBlank()))) { + dateAuctionBuyRequest = + new DateAuctionBuyRequest( + LocalDate.now().minusMonths(1).toString(), LocalDate.now().toString()); + } + } +} diff --git a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java index d6ce8ded..50e9d8fd 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java @@ -98,7 +98,7 @@ public Page search( .fetch(); // Count 쿼리 - Long total = queryFactory.select(ar.countDistinct()).from(ar).where(itemBuilder).fetchOne(); + Long total = queryFactory.select(ar.count()).from(ar).where(itemBuilder).fetchOne(); return new PageImpl<>(content, pageable, total == null ? 0L : total); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 67bf6a9e..c982b93a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -94,7 +94,7 @@ springdoc: decorator: datasource: p6spy: - enable-logging: false + enable-logging: true logging: config: classpath:logback/logback-display.xml diff --git a/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java b/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java new file mode 100644 index 00000000..1ef2f79b --- /dev/null +++ b/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java @@ -0,0 +1,82 @@ +package until.the.eternity.auctionrealtime.application.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import until.the.eternity.auctionhistory.interfaces.rest.dto.request.PriceSearchRequest; +import until.the.eternity.auctionitem.domain.entity.AuctionRealtimeItem; +import until.the.eternity.auctionrealtime.domain.mapper.AuctionRealtimeMapper; +import until.the.eternity.auctionrealtime.domain.repository.AuctionRealtimeItemRepositoryPort; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.DateAuctionExpireRequest; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.AuctionRealtimeDetailResponse; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.RealtimeItemOptionResponse; +import until.the.eternity.common.response.PageResponseDto; + +@ExtendWith(MockitoExtension.class) +class AuctionRealtimeServiceTest { + + @Mock private AuctionRealtimeItemRepositoryPort repository; + @Mock private AuctionRealtimeMapper mapper; + + @InjectMocks private AuctionRealtimeService service; + + @Test + @DisplayName("검색은 페이지 응답을 반환한다") + void search_should_return_paged_response() { + AuctionRealtimeSearchRequest request = + new AuctionRealtimeSearchRequest( + "테스트 아이템", + false, + "근거리 장비", + "검", + new PriceSearchRequest(1000L, 5000L), + new DateAuctionExpireRequest("2026-03-01", "2026-03-05"), + null, + null, + null); + Pageable pageable = PageRequest.of(0, 10); + + AuctionRealtimeItem entity = new AuctionRealtimeItem(); + AuctionRealtimeDetailResponse detailDto = + mock(AuctionRealtimeDetailResponse.class); + Page entityPage = new PageImpl<>(List.of(entity), pageable, 1); + + when(repository.search(request, pageable)).thenReturn(entityPage); + when(mapper.toDto(entity)).thenReturn(detailDto); + + PageResponseDto> result = + service.search(request, pageable); + + assertThat(result.items()).hasSize(1).contains(detailDto); + verify(repository).search(request, pageable); + verify(mapper).toDto(entity); + } + + @Test + @DisplayName("데이터가 없으면 findByIdOrElseThrow는 예외를 던진다") + void findByIdOrElseThrow_should_throw_exception_when_not_found() { + Long id = 999L; + when(repository.findById(id)).thenReturn(Optional.empty()); + + assertThrows(IllegalArgumentException.class, () -> service.findByIdOrElseThrow(id)); + verify(repository).findById(id); + verifyNoInteractions(mapper); + } +} From a66402fd46836132b17c7e74d5a63f9b3b2ea62d Mon Sep 17 00:00:00 2001 From: dev-ant Date: Thu, 5 Mar 2026 12:10:48 +0900 Subject: [PATCH 12/16] =?UTF-8?q?fix:=20docker-compose-prod=EC=97=90=20red?= =?UTF-8?q?is=20env=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose-prod.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml index 97a316c5..a6ae8fb7 100644 --- a/docker-compose-prod.yml +++ b/docker-compose-prod.yml @@ -32,16 +32,16 @@ services: DB_USER: ${DB_USER} DB_PASSWORD: ${DB_PASSWORD} - # === Redis Configuration === - REDIS_HOST: ${REDIS_HOST} - REDIS_PORT: ${REDIS_PORT} - REDIS_PASSWORD: ${REDIS_PASSWORD} - # === Security Configuration === JWT_SECRET_KEY: ${JWT_SECRET_KEY} JWT_ACCESS_TOKEN_VALIDITY: ${JWT_ACCESS_TOKEN_VALIDITY} JWT_REFRESH_TOKEN_VALIDITY: ${JWT_REFRESH_TOKEN_VALIDITY} + # === Redis Configuration === + REDIS_HOST: ${REDIS_HOST} + REDIS_PORT: ${REDIS_PORT} + REDIS_PASSWORD: ${REDIS_PASSWORD} + # === External API Configuration === NEXON_OPEN_API_KEY: ${NEXON_OPEN_API_KEY} AUCTION_HISTORY_DELAY_MS: ${AUCTION_HISTORY_DELAY_MS} From 4136d92152ad1d014d6c305f5de4556db8f1dc19 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Thu, 5 Mar 2026 12:15:57 +0900 Subject: [PATCH 13/16] =?UTF-8?q?feat:=20cache=20builder=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20auction=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EC=97=90=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuctionHistoryCacheWarmupService.java | 11 + .../service/AuctionHistoryService.java | 12 +- .../service/AuctionRealtimeService.java | 12 +- .../eternity/common/util/CacheKeyBuilder.java | 76 +++++++ .../config/CacheStartupWarmupRunner.java | 197 ++++++++++++++++++ .../config/RedisCacheErrorHandler.java | 80 +++++-- src/main/resources/application.yml | 12 ++ 7 files changed, 369 insertions(+), 31 deletions(-) create mode 100644 src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java create mode 100644 src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java index c87cf7e4..f2e1ab8f 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java @@ -44,6 +44,17 @@ public void evictAndWarm() { warmup(); } + /** 앱 시작 시 기본 화면 1개 키만 경량 워밍업한다. */ + public void warmupForStartup() { + AuctionHistorySearchRequest emptyRequest = + new AuctionHistorySearchRequest( + null, null, null, null, null, null, null, null, null); + PageRequestDto pageRequest = + new PageRequestDto(1, WARMUP_SIZE, SortField.DATE_AUCTION_BUY, SortDirection.DESC); + auctionHistoryService.search(emptyRequest, pageRequest); + log.info("[Cache Warmup] Startup warmup completed: auction-history default key"); + } + private void evictCaches() { clearCache(CacheNames.AUCTION_HISTORY_SEARCH); // auction_history 전체를 직접 쿼리하는 역대 랭킹도 함께 무효화 diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java index 30a9460e..cc896233 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java @@ -35,16 +35,8 @@ public class AuctionHistoryService { @Cacheable( cacheNames = CacheNames.AUCTION_HISTORY_SEARCH, key = - "#pageRequestDto.page() + ':'" - + " + #pageRequestDto.size() + ':'" - + " + (#pageRequestDto.sortBy() != null ? #pageRequestDto.sortBy().fieldName : 'dateAuctionBuy') + ':'" - + " + (#pageRequestDto.direction() != null ? #pageRequestDto.direction().code : 'DESC') + ':'" - + " + (#requestDto.itemName() ?: '') + ':'" - + " + (#requestDto.isExactItemName() ?: false) + ':'" - + " + (#requestDto.itemTopCategory() ?: '') + ':'" - + " + (#requestDto.itemSubCategory() ?: '') + ':'" - + " + (#requestDto.dateAuctionBuyRequest()?.dateAuctionBuyFrom() ?: '') + ':'" - + " + (#requestDto.dateAuctionBuyRequest()?.dateAuctionBuyTo() ?: '')", + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildAuctionHistorySearchKey(#requestDto, #pageRequestDto)", condition = "#requestDto.itemOptionSearchRequest() == null" + " and #requestDto.enchantSearchRequest() == null" diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java b/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java index 5de388b0..07b1b2a5 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java @@ -41,11 +41,13 @@ public class AuctionRealtimeService { @Cacheable( cacheNames = CacheNames.AUCTION_REALTIME_SEARCH, key = - "(#requestDto.itemTopCategory() ?: '_') + ':'" - + " + (#requestDto.itemSubCategory() ?: '_') + ':'" - + " + (#requestDto.itemName() ?: '_') + ':'" - + " + (#requestDto.isExactItemName() ?: false) + ':'" - + " + #pageable.pageNumber + ':' + #pageable.pageSize + ':' + #pageable.sort") + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildAuctionRealtimeSearchKey(#requestDto, #pageable)", + condition = + "#requestDto.itemOptionSearchRequest() == null" + + " and #requestDto.enchantSearchRequest() == null" + + " and (#requestDto.metalwareSearchRequests() == null or #requestDto.metalwareSearchRequests().isEmpty())" + + " and #requestDto.priceSearchRequest() == null") @Transactional(readOnly = true) public PageResponseDto> search( AuctionRealtimeSearchRequest requestDto, Pageable pageable) { diff --git a/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java b/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java new file mode 100644 index 00000000..0834bb29 --- /dev/null +++ b/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java @@ -0,0 +1,76 @@ +package until.the.eternity.common.util; + +import org.springframework.data.domain.Pageable; +import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; +import until.the.eternity.common.request.PageRequestDto; + +public final class CacheKeyBuilder { + + private CacheKeyBuilder() {} + + public static String buildAuctionHistorySearchKey( + AuctionHistorySearchRequest requestDto, PageRequestDto pageRequestDto) { + Pageable pageable = pageRequestDto.toPageable(); + String dateFrom = ""; + String dateTo = ""; + if (requestDto.dateAuctionBuyRequest() != null) { + dateFrom = normalize(requestDto.dateAuctionBuyRequest().dateAuctionBuyFrom()); + dateTo = normalize(requestDto.dateAuctionBuyRequest().dateAuctionBuyTo()); + } + + return pageable.getPageNumber() + + ":" + + pageable.getPageSize() + + ":" + + pageable.getSort() + + ":" + + normalize(requestDto.itemName()) + + ":" + + Boolean.TRUE.equals(requestDto.isExactItemName()) + + ":" + + normalize(requestDto.itemTopCategory()) + + ":" + + normalize(requestDto.itemSubCategory()) + + ":" + + dateFrom + + ":" + + dateTo; + } + + public static String buildAuctionRealtimeSearchKey( + AuctionRealtimeSearchRequest requestDto, Pageable pageable) { + String dateFrom = ""; + String dateTo = ""; + if (requestDto.dateAuctionExpireRequest() != null) { + dateFrom = normalize(requestDto.dateAuctionExpireRequest().dateAuctionExpireFrom()); + dateTo = normalize(requestDto.dateAuctionExpireRequest().dateAuctionExpireTo()); + } + + return normalize(requestDto.itemTopCategory()) + + ":" + + normalize(requestDto.itemSubCategory()) + + ":" + + normalize(requestDto.itemName()) + + ":" + + Boolean.TRUE.equals(requestDto.isExactItemName()) + + ":" + + dateFrom + + ":" + + dateTo + + ":" + + pageable.getPageNumber() + + ":" + + pageable.getPageSize() + + ":" + + pageable.getSort(); + } + + private static String normalize(String value) { + if (value == null) { + return ""; + } + String trimmed = value.trim(); + return trimmed.isEmpty() ? "" : trimmed; + } +} diff --git a/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java b/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java new file mode 100644 index 00000000..e22299ac --- /dev/null +++ b/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java @@ -0,0 +1,197 @@ +package until.the.eternity.config; + +import java.time.LocalDate; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.annotation.Order; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Component; +import until.the.eternity.auctionhistory.application.service.AuctionHistoryCacheWarmupService; +import until.the.eternity.auctionrealtime.application.service.AuctionRealtimeService; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; +import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.DateAuctionExpireRequest; +import until.the.eternity.auctionsearchoption.application.service.AuctionSearchOptionService; +import until.the.eternity.common.enums.ItemCategory; +import until.the.eternity.common.enums.SortDirection; +import until.the.eternity.enchantinfo.application.service.EnchantInfoService; +import until.the.eternity.iteminfo.application.service.ItemInfoService; +import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest; +import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoResponse; +import until.the.eternity.metalwareinfo.application.service.MetalwareAttributeInfoService; +import until.the.eternity.metalwareinfo.application.service.MetalwareInfoService; +import until.the.eternity.metalwareinfo.interfaces.rest.dto.request.MetalwareAttributeInfoSearchRequest; +import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse; +import until.the.eternity.ranking.application.service.AllTimeRankingService; +import until.the.eternity.ranking.application.service.CategoryRankingService; +import until.the.eternity.ranking.application.service.PriceChangeRankingService; +import until.the.eternity.ranking.application.service.PriceRankingService; +import until.the.eternity.ranking.application.service.VolumeRankingService; +import until.the.eternity.ranking.util.RankingConstants; +import until.the.eternity.statistics.application.service.ItemDailyStatisticsService; +import until.the.eternity.statistics.application.service.ItemWeeklyStatisticsService; +import until.the.eternity.statistics.application.service.SubcategoryDailyStatisticsService; +import until.the.eternity.statistics.application.service.SubcategoryWeeklyStatisticsService; +import until.the.eternity.statistics.application.service.TopCategoryDailyStatisticsService; +import until.the.eternity.statistics.application.service.TopCategoryWeeklyStatisticsService; + +@Slf4j +@Component +@Order(200) +@RequiredArgsConstructor +@ConditionalOnProperty( + name = "app.cache.warmup.enabled", + havingValue = "true", + matchIfMissing = true) +public class CacheStartupWarmupRunner implements ApplicationRunner { + + private final AuctionHistoryCacheWarmupService auctionHistoryCacheWarmupService; + private final AuctionRealtimeService auctionRealtimeService; + private final AuctionSearchOptionService auctionSearchOptionService; + private final ItemInfoService itemInfoService; + private final EnchantInfoService enchantInfoService; + private final MetalwareInfoService metalwareInfoService; + private final MetalwareAttributeInfoService metalwareAttributeInfoService; + private final PriceRankingService priceRankingService; + private final VolumeRankingService volumeRankingService; + private final PriceChangeRankingService priceChangeRankingService; + private final CategoryRankingService categoryRankingService; + private final AllTimeRankingService allTimeRankingService; + private final ItemDailyStatisticsService itemDailyStatisticsService; + private final SubcategoryDailyStatisticsService subcategoryDailyStatisticsService; + private final TopCategoryDailyStatisticsService topCategoryDailyStatisticsService; + private final ItemWeeklyStatisticsService itemWeeklyStatisticsService; + private final SubcategoryWeeklyStatisticsService subcategoryWeeklyStatisticsService; + private final TopCategoryWeeklyStatisticsService topCategoryWeeklyStatisticsService; + + @Value("${app.cache.warmup.ranking-limit:50}") + private int startupRankingLimit; + + @Override + public void run(ApplicationArguments args) { + log.info("[Cache Warmup] Startup warmup started"); + + tryWarm("auction-history", auctionHistoryCacheWarmupService::evictAndWarm); + tryWarm("auction-realtime", this::warmAuctionRealtime); + tryWarm("search-option", auctionSearchOptionService::getAllActiveSearchOptions); + tryWarm("item-info", this::warmItemInfoCaches); + tryWarm("enchant-info", this::warmEnchantCaches); + tryWarm("metalware-info", this::warmMetalwareCaches); + tryWarm("ranking", this::warmRankingCaches); + tryWarm("statistics", this::warmStatisticsCaches); + + log.info("[Cache Warmup] Startup warmup finished"); + } + + private void warmAuctionRealtime() { + AuctionRealtimeSearchRequest request = + new AuctionRealtimeSearchRequest( + null, + false, + null, + null, + null, + new DateAuctionExpireRequest( + LocalDate.now().minusMonths(1).toString(), + LocalDate.now().toString()), + null, + null, + null); + auctionRealtimeService.search( + request, PageRequest.of(0, 20, Sort.by(Sort.Direction.DESC, "dateAuctionExpire"))); + } + + private void warmItemInfoCaches() { + List all = itemInfoService.findAll(); + itemInfoService.findAllDetail( + new ItemInfoSearchRequest(null, null, null), PageRequest.of(0, 20)); + itemInfoService.findAllSummary( + new ItemInfoSearchRequest(null, null, null), Sort.Direction.ASC); + + if (!all.isEmpty()) { + ItemInfoResponse sample = all.get(0); + itemInfoService.findByTopCategory(sample.topCategory()); + itemInfoService.findBySubCategory(sample.subCategory()); + } + } + + private void warmEnchantCaches() { + enchantInfoService.findAll(PageRequest.of(0, 20)); + enchantInfoService.findAllFullnames(null); + enchantInfoService.findAllFullnames("접두"); + enchantInfoService.findAllFullnames("접미"); + } + + private void warmMetalwareCaches() { + List metalwares = metalwareInfoService.findAll(); + if (!metalwares.isEmpty()) { + String sample = metalwares.get(0).metalware(); + metalwareAttributeInfoService.search( + new MetalwareAttributeInfoSearchRequest(sample, 1, 25, SortDirection.ASC)); + } + } + + private void warmRankingCaches() { + int limit = + startupRankingLimit > 0 + ? Math.min(startupRankingLimit, RankingConstants.MAX_LIMIT) + : RankingConstants.DEFAULT_LIMIT; + priceRankingService.getTodayHighestPrice(limit); + priceRankingService.getWeekHighestPrice(limit); + priceRankingService.getTodayLargestVolume(limit); + + volumeRankingService.getTodayPopular(limit); + volumeRankingService.getWeekPopular(limit); + + priceChangeRankingService.getPriceSurge(limit); + priceChangeRankingService.getPriceDrop(limit); + priceChangeRankingService.getVolumeSurge(limit); + + String defaultTopCategory = ItemCategory.ONE_HANDED_WEAPON.getTopCategory(); + String defaultSubCategory = ItemCategory.ONE_HANDED_WEAPON.getSubCategory(); + categoryRankingService.getCategoryTopPriced(defaultTopCategory, defaultSubCategory, limit); + categoryRankingService.getCategoryPopular(defaultTopCategory, defaultSubCategory, limit); + + allTimeRankingService.getAllTimeHighestPrice(limit); + allTimeRankingService.getMonthLargestVolume(limit); + } + + private void warmStatisticsCaches() { + List items = itemInfoService.findAll(); + if (items.isEmpty()) { + log.info("[Cache Warmup] statistics skipped: no item info sample"); + return; + } + + ItemInfoResponse sample = items.get(0); + LocalDate dailyStart = LocalDate.now().minusDays(14); + LocalDate weeklyStart = LocalDate.now().minusMonths(2); + LocalDate end = LocalDate.now(); + + itemDailyStatisticsService.search( + sample.name(), sample.subCategory(), sample.topCategory(), dailyStart, end); + subcategoryDailyStatisticsService.search( + sample.topCategory(), sample.subCategory(), dailyStart, end); + topCategoryDailyStatisticsService.search(sample.topCategory(), dailyStart, end); + + itemWeeklyStatisticsService.search( + sample.name(), sample.subCategory(), sample.topCategory(), weeklyStart, end); + subcategoryWeeklyStatisticsService.search( + sample.topCategory(), sample.subCategory(), weeklyStart, end); + topCategoryWeeklyStatisticsService.search(sample.topCategory(), weeklyStart, end); + } + + private void tryWarm(String domain, Runnable runnable) { + try { + runnable.run(); + log.info("[Cache Warmup] {} warmup completed", domain); + } catch (Exception e) { + log.warn("[Cache Warmup] {} warmup failed: {}", domain, e.getMessage(), e); + } + } +} diff --git a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java index 8ce10832..ca5c391f 100644 --- a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java +++ b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java @@ -1,5 +1,6 @@ package until.the.eternity.config; +import java.net.ConnectException; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.Cache; import org.springframework.cache.interceptor.CacheErrorHandler; @@ -14,34 +15,81 @@ public class RedisCacheErrorHandler implements CacheErrorHandler { @Override public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { - log.warn( - "[Cache] GET 실패 - cache={}, key={}, error={}", - cache.getName(), - key, - exception.getMessage()); + logCacheError("GET", exception, cache, key); } @Override public void handleCachePutError( RuntimeException exception, Cache cache, Object key, Object value) { - log.warn( - "[Cache] PUT 실패 - cache={}, key={}, error={}", - cache.getName(), - key, - exception.getMessage()); + logCacheError("PUT", exception, cache, key); } @Override public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { - log.warn( - "[Cache] EVICT 실패 - cache={}, key={}, error={}", - cache.getName(), - key, - exception.getMessage()); + logCacheError("EVICT", exception, cache, key); } @Override public void handleCacheClearError(RuntimeException exception, Cache cache) { - log.warn("[Cache] CLEAR 실패 - cache={}, error={}", cache.getName(), exception.getMessage()); + logCacheError("CLEAR", exception, cache, null); + } + + private void logCacheError(String action, RuntimeException exception, Cache cache, Object key) { + Throwable root = getRootCause(exception); + String cacheName = cache != null ? cache.getName() : "unknown"; + String keyText = key != null ? truncate(String.valueOf(key), 120) : "-"; + String causeType = + root != null + ? root.getClass().getSimpleName() + : exception.getClass().getSimpleName(); + String message = root != null ? root.getMessage() : exception.getMessage(); + + if (isRedisConnectionFailure(root, message)) { + log.warn( + "[Cache][RedisUnavailable] action={}, cache={}, key={}, cause={}, message={}", + action, + cacheName, + keyText, + causeType, + sanitize(message)); + return; + } + + log.warn( + "[Cache][OperationFailed] action={}, cache={}, key={}, cause={}, message={}", + action, + cacheName, + keyText, + causeType, + sanitize(message)); + } + + private boolean isRedisConnectionFailure(Throwable root, String message) { + if (root instanceof ConnectException) { + return true; + } + String normalized = message == null ? "" : message.toLowerCase(); + return normalized.contains("connection refused") + || normalized.contains("unable to connect to redis") + || normalized.contains("redisconnectionfailureexception"); + } + + private Throwable getRootCause(Throwable throwable) { + Throwable current = throwable; + while (current != null && current.getCause() != null && current.getCause() != current) { + current = current.getCause(); + } + return current; + } + + private String sanitize(String message) { + return message == null ? "-" : message.replaceAll("\\s+", " ").trim(); + } + + private String truncate(String value, int maxLength) { + if (value == null || value.length() <= maxLength) { + return value; + } + return value.substring(0, maxLength) + "..."; } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c982b93a..b5c4efe0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -14,6 +14,9 @@ management: web: exposure: include: [ "health" ] + health: + redis: + enabled: ${MANAGEMENT_HEALTH_REDIS_ENABLED:false} spring: application: @@ -100,6 +103,11 @@ logging: config: classpath:logback/logback-display.xml level: until.the.eternity: INFO + org.springframework.data.redis: WARN + org.springframework.boot.actuate.autoconfigure.data.redis: ERROR + org.springframework.boot.actuate.data.redis: ERROR + io.lettuce.core: WARN + io.netty: WARN openapi: nexon: @@ -137,6 +145,10 @@ elasticsearch: enabled: ${ELASTICSEARCH_INDEX_ENABLED:true} app: + cache: + warmup: + enabled: ${APP_CACHE_WARMUP_ENABLED:true} + ranking-limit: ${APP_CACHE_WARMUP_RANKING_LIMIT:50} kafka: topics: user-verification-verify: ${KAFKA_TOPIC_USER_VERIFICATION_VERIFY:USER_VERIFICATION_VERIFY_EVENT} From 931ed9d5b5ae9d0cc3a6023faf8ab404815a95d5 Mon Sep 17 00:00:00 2001 From: dev-ant Date: Thu, 5 Mar 2026 12:24:05 +0900 Subject: [PATCH 14/16] =?UTF-8?q?feat:=20Cacheable=EC=9D=98=20=EB=AA=A8?= =?UTF-8?q?=EB=93=A0=20key=20=EC=83=9D=EC=84=B1=EC=9D=84=20CacheKeyBuilder?= =?UTF-8?q?=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/AuctionSearchOptionService.java | 4 +- .../eternity/common/util/CacheKeyBuilder.java | 102 ++++++++++++++++++ .../service/EnchantInfoService.java | 10 +- .../application/service/ItemInfoService.java | 25 ++--- .../MetalwareAttributeInfoService.java | 3 +- .../service/MetalwareInfoService.java | 4 +- .../service/AllTimeRankingService.java | 8 +- .../service/CategoryRankingService.java | 8 +- .../service/PriceChangeRankingService.java | 12 ++- .../service/PriceRankingService.java | 12 ++- .../service/VolumeRankingService.java | 8 +- .../service/ItemDailyStatisticsService.java | 6 +- .../service/ItemWeeklyStatisticsService.java | 6 +- .../SubcategoryDailyStatisticsService.java | 4 +- .../SubcategoryWeeklyStatisticsService.java | 4 +- .../TopCategoryDailyStatisticsService.java | 4 +- .../TopCategoryWeeklyStatisticsService.java | 4 +- 17 files changed, 183 insertions(+), 41 deletions(-) diff --git a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java index 0c3dca98..25e9f1be 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java @@ -28,7 +28,9 @@ public class AuctionSearchOptionService { * * @return 검색 옵션 메타데이터 리스트 */ - @Cacheable(cacheNames = CacheNames.SEARCH_OPTION_ALL_ACTIVE, key = "'all'") + @Cacheable( + cacheNames = CacheNames.SEARCH_OPTION_ALL_ACTIVE, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).all()") @Transactional(readOnly = true) public List getAllActiveSearchOptions() { List entities = repositoryPort.findAllActive(); diff --git a/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java b/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java index 0834bb29..d1d72674 100644 --- a/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java +++ b/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java @@ -1,14 +1,116 @@ package until.the.eternity.common.util; +import java.time.LocalDate; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; import until.the.eternity.common.request.PageRequestDto; +import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest; +import until.the.eternity.metalwareinfo.interfaces.rest.dto.request.MetalwareAttributeInfoSearchRequest; public final class CacheKeyBuilder { private CacheKeyBuilder() {} + public static String all() { + return "all"; + } + + public static String byText(String value) { + return normalize(value); + } + + public static String byLimit(int limit) { + return String.valueOf(limit); + } + + public static String pageable(Pageable pageable) { + return pageable.getPageNumber() + ":" + pageable.getPageSize() + ":" + pageable.getSort(); + } + + public static String buildItemInfoDetailKey(ItemInfoSearchRequest request, Pageable pageable) { + return normalize(request.name()) + + ":" + + normalize(request.topCategory()) + + ":" + + normalize(request.subCategory()) + + ":" + + pageable.getPageNumber() + + ":" + + pageable.getPageSize() + + ":" + + pageable.getSort(); + } + + public static String buildItemInfoSummaryKey( + ItemInfoSearchRequest request, Sort.Direction direction) { + return normalize(request.name()) + + ":" + + normalize(request.topCategory()) + + ":" + + normalize(request.subCategory()) + + ":" + + direction.name(); + } + + public static String buildEnchantInfoAllKey(Pageable pageable) { + return pageable(pageable); + } + + public static String buildEnchantInfoFullnamesKey(String affixPosition) { + String normalized = normalize(affixPosition); + return normalized.isEmpty() ? "all" : normalized; + } + + public static String buildMetalwareAttributeInfoSearchKey( + MetalwareAttributeInfoSearchRequest request) { + int page = request.page() != null ? request.page() : 1; + int size = request.size() != null ? request.size() : 25; + String direction = request.direction() != null ? request.direction().name() : "ASC"; + return normalize(request.metalware()) + ":" + page + ":" + size + ":" + direction; + } + + public static String buildRankingCategoryKey( + String topCategory, String subCategory, int limit) { + return normalize(topCategory) + ":" + normalize(subCategory) + ":" + limit; + } + + public static String buildStatisticsItemKey( + String itemName, + String subCategory, + String topCategory, + LocalDate startDate, + LocalDate endDate) { + return normalize(itemName) + + ":" + + normalize(subCategory) + + ":" + + normalize(topCategory) + + ":" + + String.valueOf(startDate) + + ":" + + String.valueOf(endDate); + } + + public static String buildStatisticsSubcategoryKey( + String subCategory, LocalDate startDate, LocalDate endDate) { + return normalize(subCategory) + + ":" + + String.valueOf(startDate) + + ":" + + String.valueOf(endDate); + } + + public static String buildStatisticsTopCategoryKey( + String topCategory, LocalDate startDate, LocalDate endDate) { + return normalize(topCategory) + + ":" + + String.valueOf(startDate) + + ":" + + String.valueOf(endDate); + } + public static String buildAuctionHistorySearchKey( AuctionHistorySearchRequest requestDto, PageRequestDto pageRequestDto) { Pageable pageable = pageRequestDto.toPageable(); diff --git a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java index edf03138..5d672321 100644 --- a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java +++ b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java @@ -28,12 +28,18 @@ public class EnchantInfoService { @Cacheable( cacheNames = CacheNames.ENCHANT_INFO_ALL, - key = "#pageable.pageNumber + ':' + #pageable.pageSize + ':' + #pageable.sort") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildEnchantInfoAllKey(#pageable)") public Page findAll(Pageable pageable) { return enchantInfoRepository.findAll(pageable).map(EnchantInfoResponse::from); } - @Cacheable(cacheNames = CacheNames.ENCHANT_INFO_FULLNAMES, key = "#affixPosition ?: 'all'") + @Cacheable( + cacheNames = CacheNames.ENCHANT_INFO_FULLNAMES, + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildEnchantInfoFullnamesKey(#affixPosition)") public List findAllFullnames(String affixPosition) { if (affixPosition != null) { if (!ALLOWED_AFFIX_POSITIONS.contains(affixPosition)) { diff --git a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java index 5e7491e4..6275c02d 100644 --- a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java +++ b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java @@ -39,19 +39,25 @@ public List findItemCategories() { return ItemCategoryResponse.from(); } - @Cacheable(cacheNames = CacheNames.ITEM_INFO_ALL, key = "'all'") + @Cacheable( + cacheNames = CacheNames.ITEM_INFO_ALL, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).all()") public List findAll() { List itemInfos = itemInfoRepository.findAll(); return ItemInfoResponse.from(itemInfos); } - @Cacheable(cacheNames = CacheNames.ITEM_INFO_BY_TOP_CATEGORY, key = "#topCategory") + @Cacheable( + cacheNames = CacheNames.ITEM_INFO_BY_TOP_CATEGORY, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byText(#topCategory)") public List findByTopCategory(String topCategory) { List itemInfos = itemInfoRepository.findByTopCategory(topCategory); return ItemInfoResponse.from(itemInfos); } - @Cacheable(cacheNames = CacheNames.ITEM_INFO_BY_SUB_CATEGORY, key = "#subCategory") + @Cacheable( + cacheNames = CacheNames.ITEM_INFO_BY_SUB_CATEGORY, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byText(#subCategory)") public List findBySubCategory(String subCategory) { List itemInfos = itemInfoRepository.findBySubCategory(subCategory); return ItemInfoResponse.from(itemInfos); @@ -60,11 +66,8 @@ public List findBySubCategory(String subCategory) { @Cacheable( cacheNames = CacheNames.ITEM_INFO_DETAIL, key = - "(#searchRequest.name() ?: '') + ':'" - + " + (#searchRequest.topCategory() ?: '') + ':'" - + " + (#searchRequest.subCategory() ?: '') + ':'" - + " + #pageable.pageNumber + ':' + #pageable.pageSize" - + " + ':' + #pageable.sort") + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildItemInfoDetailKey(#searchRequest, #pageable)") public Page findAllDetail( ItemInfoSearchRequest searchRequest, Pageable pageable) { Page itemInfoPage = @@ -75,10 +78,8 @@ public Page findAllDetail( @Cacheable( cacheNames = CacheNames.ITEM_INFO_SUMMARY, key = - "(#searchRequest.name() ?: '') + ':'" - + " + (#searchRequest.topCategory() ?: '') + ':'" - + " + (#searchRequest.subCategory() ?: '') + ':'" - + " + #direction.name()") + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildItemInfoSummaryKey(#searchRequest, #direction)") public List findAllSummary( ItemInfoSearchRequest searchRequest, org.springframework.data.domain.Sort.Direction direction) { diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java index aed51db2..719ecbd2 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareAttributeInfoService.java @@ -34,7 +34,8 @@ public int sync() { @Cacheable( cacheNames = CacheNames.METALWARE_ATTRIBUTE_INFO_SEARCH, key = - "#request.metalware() + ':' + (#request.page ?: 1) + ':' + (#request.size ?: 25) + ':' + (#request.direction?.name() ?: 'ASC')") + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildMetalwareAttributeInfoSearchKey(#request)") @Transactional(readOnly = true) public Page search( MetalwareAttributeInfoSearchRequest request) { diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java index aa909d6f..7c734b4d 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java @@ -19,7 +19,9 @@ public class MetalwareInfoService { private final MetalwareInfoRepositoryPort metalwareInfoRepository; - @Cacheable(cacheNames = CacheNames.METALWARE_INFO_ALL, key = "'all'") + @Cacheable( + cacheNames = CacheNames.METALWARE_INFO_ALL, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).all()") public List findAll() { List metalwares = metalwareInfoRepository.findAllMetalwares(); return MetalwareInfoResponse.from(metalwares); diff --git a/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java index ac95269f..e8703336 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java @@ -19,14 +19,18 @@ public class AllTimeRankingService { private final RankingMapper rankingMapper; /** 역대 최고가 거래 TOP N (API 11) - auction_history 전체 스캔, 1시간 TTL */ - @Cacheable(cacheNames = CacheNames.RANKING_ALLTIME_HIGHEST, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_ALLTIME_HIGHEST, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getAllTimeHighestPrice(int limit) { List results = rankingRepository.findAllTimeHighestPrice(limit); return rankingMapper.toAllTimeRankingResponses(results); } /** 이번 달 최대 거래액 TOP N (API 12) */ - @Cacheable(cacheNames = CacheNames.RANKING_ALLTIME_MONTH_VOLUME, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_ALLTIME_MONTH_VOLUME, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getMonthLargestVolume(int limit) { List results = rankingRepository.findMonthLargestVolume(limit); return rankingMapper.toAllTimeRankingResponses(results); diff --git a/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java index 194e2a30..1f4c2d80 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java @@ -22,7 +22,9 @@ public class CategoryRankingService { /** 카테고리별 최고가 TOP N (API 9) */ @Cacheable( cacheNames = CacheNames.RANKING_CATEGORY_HIGHEST, - key = "#topCategory + ':' + #subCategory + ':' + #limit") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildRankingCategoryKey(#topCategory, #subCategory, #limit)") public List getCategoryTopPriced( String topCategory, String subCategory, int limit) { List results = @@ -33,7 +35,9 @@ public List getCategoryTopPriced( /** 카테고리별 인기 아이템 TOP N (API 10) */ @Cacheable( cacheNames = CacheNames.RANKING_CATEGORY_POPULAR, - key = "#topCategory + ':' + #subCategory + ':' + #limit") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildRankingCategoryKey(#topCategory, #subCategory, #limit)") public List getCategoryPopular( String topCategory, String subCategory, int limit) { List results = diff --git a/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java index 1296d9b5..a3ae944e 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java @@ -20,21 +20,27 @@ public class PriceChangeRankingService { private final RankingMapper rankingMapper; /** 가격 급등 TOP N (API 6) */ - @Cacheable(cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_CHANGE_PRICE_SURGE, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getPriceSurge(int limit) { List results = rankingRepository.findPriceSurge(limit); return rankingMapper.toPriceChangeRankingResponses(results); } /** 가격 급락 TOP N (API 7) */ - @Cacheable(cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_CHANGE_PRICE_DROP, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getPriceDrop(int limit) { List results = rankingRepository.findPriceDrop(limit); return rankingMapper.toPriceChangeRankingResponses(results); } /** 거래량 급증 TOP N (API 8) */ - @Cacheable(cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_CHANGE_VOLUME_SURGE, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getVolumeSurge(int limit) { List results = rankingRepository.findVolumeSurge(limit); return rankingMapper.toVolumeChangeRankingResponses(results); diff --git a/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java index fa81b45e..3db9873a 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java @@ -19,21 +19,27 @@ public class PriceRankingService { private final RankingMapper rankingMapper; /** 오늘의 최고가 거래 TOP N (API 1) */ - @Cacheable(cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_PRICE_TODAY_HIGHEST, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getTodayHighestPrice(int limit) { List results = rankingRepository.findTodayHighestPrice(limit); return rankingMapper.toPriceRankingResponses(results); } /** 이번 주 최고가 아이템 TOP N (API 2) */ - @Cacheable(cacheNames = CacheNames.RANKING_PRICE_WEEK_HIGHEST, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_PRICE_WEEK_HIGHEST, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getWeekHighestPrice(int limit) { List results = rankingRepository.findWeekHighestPrice(limit); return rankingMapper.toPriceRankingResponses(results); } /** 오늘의 최대 거래액 TOP N (API 3) */ - @Cacheable(cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_PRICE_TODAY_VOLUME, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getTodayLargestVolume(int limit) { List results = rankingRepository.findTodayLargestVolume(limit); return rankingMapper.toPriceRankingResponses(results); diff --git a/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java index 9d593054..b778e573 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java @@ -19,14 +19,18 @@ public class VolumeRankingService { private final RankingMapper rankingMapper; /** 오늘의 인기 아이템 TOP N (API 4) */ - @Cacheable(cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_VOLUME_TODAY_POPULAR, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getTodayPopular(int limit) { List results = rankingRepository.findTodayPopular(limit); return rankingMapper.toVolumeRankingResponses(results); } /** 이번 주 인기 아이템 TOP N (API 5) */ - @Cacheable(cacheNames = CacheNames.RANKING_VOLUME_WEEK_POPULAR, key = "#limit") + @Cacheable( + cacheNames = CacheNames.RANKING_VOLUME_WEEK_POPULAR, + key = "T(until.the.eternity.common.util.CacheKeyBuilder).byLimit(#limit)") public List getWeekPopular(int limit) { List results = rankingRepository.findWeekPopular(limit); return rankingMapper.toVolumeRankingResponses(results); diff --git a/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java index c765967d..641d9981 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java @@ -26,10 +26,8 @@ public class ItemDailyStatisticsService { @Cacheable( cacheNames = CacheNames.STATISTICS_ITEM_DAILY, key = - "(#itemName ?: '') + ':'" - + " + (#subCategory ?: '') + ':'" - + " + (#topCategory ?: '') + ':'" - + " + #startDate + ':' + #endDate") + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildStatisticsItemKey(#itemName, #subCategory, #topCategory, #startDate, #endDate)") @Transactional(readOnly = true) public List search( String itemName, diff --git a/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java index d40850c4..ee53d2a1 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java @@ -26,10 +26,8 @@ public class ItemWeeklyStatisticsService { @Cacheable( cacheNames = CacheNames.STATISTICS_ITEM_WEEKLY, key = - "(#itemName ?: '') + ':'" - + " + (#subCategory ?: '') + ':'" - + " + (#topCategory ?: '') + ':'" - + " + #startDate + ':' + #endDate") + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildStatisticsItemKey(#itemName, #subCategory, #topCategory, #startDate, #endDate)") @Transactional(readOnly = true) public List search( String itemName, diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java index 02b3d4ca..ea3c74ff 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java @@ -25,7 +25,9 @@ public class SubcategoryDailyStatisticsService { /** 서브카테고리별 일간 통계 조회 (subCategory, 날짜 범위) */ @Cacheable( cacheNames = CacheNames.STATISTICS_SUBCATEGORY_DAILY, - key = "(#subCategory ?: '') + ':' + #startDate + ':' + #endDate") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildStatisticsSubcategoryKey(#subCategory, #startDate, #endDate)") @Transactional(readOnly = true) public List search( String topCategory, String subCategory, LocalDate startDate, LocalDate endDate) { diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java index 62c7bf00..7445ba04 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java @@ -25,7 +25,9 @@ public class SubcategoryWeeklyStatisticsService { /** 서브카테고리별 주간 통계 조회 (subCategory, 날짜 범위) */ @Cacheable( cacheNames = CacheNames.STATISTICS_SUBCATEGORY_WEEKLY, - key = "(#subCategory ?: '') + ':' + #startDate + ':' + #endDate") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildStatisticsSubcategoryKey(#subCategory, #startDate, #endDate)") @Transactional(readOnly = true) public List search( String topCategory, String subCategory, LocalDate startDate, LocalDate endDate) { diff --git a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java index 3aabdee4..a7ca0697 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java @@ -25,7 +25,9 @@ public class TopCategoryDailyStatisticsService { /** 탑카테고리별 일간 통계 조회 (topCategory, 날짜 범위) */ @Cacheable( cacheNames = CacheNames.STATISTICS_TOPCATEGORY_DAILY, - key = "(#topCategory ?: '') + ':' + #startDate + ':' + #endDate") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildStatisticsTopCategoryKey(#topCategory, #startDate, #endDate)") @Transactional(readOnly = true) public List search( String topCategory, LocalDate startDate, LocalDate endDate) { diff --git a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java index 9717d7ba..7ecbe622 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java @@ -25,7 +25,9 @@ public class TopCategoryWeeklyStatisticsService { /** 탑카테고리별 주간 통계 조회 (topCategory, 날짜 범위) */ @Cacheable( cacheNames = CacheNames.STATISTICS_TOPCATEGORY_WEEKLY, - key = "(#topCategory ?: '') + ':' + #startDate + ':' + #endDate") + key = + "T(until.the.eternity.common.util.CacheKeyBuilder)" + + ".buildStatisticsTopCategoryKey(#topCategory, #startDate, #endDate)") @Transactional(readOnly = true) public List search( String topCategory, LocalDate startDate, LocalDate endDate) { From f6889d70c9be5252d44bfbd32106d9e14a75bf3d Mon Sep 17 00:00:00 2001 From: dev-ant Date: Thu, 5 Mar 2026 12:41:01 +0900 Subject: [PATCH 15/16] fix: optimize imports --- .../scheduler/AuctionHistoryScheduler.java | 5 +++-- .../service/AuctionHistoryService.java | 3 ++- .../service/fetcher/AuctionHistoryFetcher.java | 7 ++++--- .../persister/AuctionHistoryPersister.java | 3 ++- .../domain/entity/AuctionHistory.java | 5 +++-- .../domain/event/AuctionHistorySavedEvent.java | 3 ++- .../domain/mapper/AuctionHistoryMapper.java | 3 ++- .../mapper/OpenApiAuctionHistoryMapper.java | 5 +++-- .../AuctionHistoryRepositoryPort.java | 9 +++++---- .../AuctionHistoryDuplicateChecker.java | 9 +++++---- .../fetcher/AuctionHistoryFetcherPort.java | 3 ++- .../persister/AuctionHistoryPersisterPort.java | 3 ++- .../AuctionHistoryJpaRepository.java | 7 ++++--- .../AuctionHistoryQueryDslRepository.java | 17 +++++++---------- .../AuctionHistoryRepositoryPortImpl.java | 9 +++++---- .../dto/OpenApiAuctionHistoryListResponse.java | 1 + .../dto/OpenApiAuctionHistoryResponse.java | 3 ++- .../rest/dto/enums/SearchStandard.java | 1 + .../rest/dto/enums/SortDirection.java | 1 + .../request/AuctionHistorySearchRequest.java | 1 + .../response/AuctionHistoryDetailResponse.java | 1 + .../domain/entity/AuctionRealtimeItem.java | 3 ++- .../entity/AuctionRealtimeItemOption.java | 3 ++- .../entity/AuctionHistoryItemOption.java | 3 ++- .../scheduler/AuctionRealtimeScheduler.java | 7 ++++--- .../service/AuctionRealtimeService.java | 5 +++-- .../fetcher/AuctionRealtimeFetcher.java | 5 +++-- .../persister/AuctionRealtimePersister.java | 3 ++- .../domain/mapper/AuctionRealtimeMapper.java | 3 ++- .../mapper/OpenApiAuctionRealtimeMapper.java | 7 ++++--- .../AuctionRealtimeItemRepositoryPort.java | 7 ++++--- .../fetcher/AuctionRealtimeFetcherPort.java | 3 ++- .../AuctionRealtimePersisterPort.java | 3 ++- .../AuctionRealtimeItemRepository.java | 3 ++- .../AuctionRealtimeItemRepositoryPortImpl.java | 7 ++++--- .../AuctionRealtimeQueryDslRepository.java | 11 ++++++----- .../OpenApiAuctionRealtimeListResponse.java | 1 + .../dto/OpenApiAuctionRealtimeResponse.java | 3 ++- .../request/AuctionRealtimeSearchRequest.java | 3 ++- .../rest/dto/request/RealtimeSortField.java | 1 + .../AuctionRealtimeDetailResponse.java | 1 + .../service/AuctionSearchOptionService.java | 5 +++-- .../entity/AuctionSearchOptionMetadata.java | 3 ++- .../AuctionSearchOptionRepositoryPort.java | 3 ++- .../AuctionSearchOptionJpaRepository.java | 3 ++- .../AuctionSearchOptionRepositoryPortImpl.java | 3 ++- .../rest/AuctionSearchOptionController.java | 3 ++- .../rest/dto/response/FieldMetadata.java | 1 + .../response/SearchOptionMetadataResponse.java | 1 + .../service/BatchExecutionLogService.java | 5 +++-- .../domain/entity/BatchExecutionLog.java | 3 ++- .../BatchExecutionLogRepositoryPort.java | 3 ++- .../BatchExecutionLogJpaRepository.java | 3 ++- .../BatchExecutionLogRepositoryPortImpl.java | 7 ++++--- .../BatchExecutionLogController.java | 3 ++- .../response/BatchExecutionLogResponse.java | 3 ++- .../eternity/common/annotation/BatchLog.java | 3 ++- .../common/annotation/MetalwareParameters.java | 1 + .../aspect/BatchExecutionLoggingAspect.java | 3 ++- .../eternity/common/enums/ItemCategory.java | 5 +++-- .../eternity/common/enums/SortDirection.java | 3 ++- .../the/eternity/common/enums/SortField.java | 1 + .../the/eternity/common/enums/UserRole.java | 5 +++-- .../common/exception/GlobalExceptionCode.java | 4 ++-- .../exception/GlobalExceptionHandler.java | 4 ++-- .../common/filter/GatewayAuthFilter.java | 7 ++++--- .../eternity/common/response/ApiResponse.java | 3 ++- .../common/response/PageResponseDto.java | 1 + .../eternity/common/util/CacheKeyBuilder.java | 3 ++- .../common/util/SegongOptionParser.java | 3 ++- .../config/CacheStartupWarmupRunner.java | 18 +++++------------- .../config/RedisCacheErrorHandler.java | 3 ++- .../until/the/eternity/config/RedisConfig.java | 7 ++++--- .../config/openapi/OpenApiFilters.java | 3 ++- .../config/openapi/OpenApiRetryPolicy.java | 3 ++- .../openapi/OpenApiWebClientProperties.java | 3 ++- .../service/EnchantInfoService.java | 5 +++-- .../exception/EnchantInfoExceptionCode.java | 4 ++-- .../repository/EnchantInfoRepositoryPort.java | 3 ++- .../persistence/EnchantInfoEntity.java | 7 +------ .../persistence/EnchantInfoJpaRepository.java | 3 ++- .../EnchantInfoRepositoryPortImpl.java | 3 ++- .../rest/controller/EnchantInfoController.java | 10 +++------- .../runner/HornBugleIndexRunner.java | 3 ++- .../scheduler/HornBugleScheduler.java | 11 ++++++----- .../application/service/HornBugleService.java | 7 ++++--- .../domain/entity/HornBugleWorldHistory.java | 3 ++- .../domain/enums/HornBugleServer.java | 5 +++-- .../domain/mapper/HornBugleMapper.java | 3 ++- .../repository/HornBugleRepositoryPort.java | 7 ++++--- .../service/HornBugleDuplicateChecker.java | 11 ++++++----- .../elasticsearch/HornBugleDocument.java | 3 ++- .../elasticsearch/HornBugleIndexService.java | 3 ++- .../persistence/HornBugleJpaRepository.java | 7 ++++--- .../HornBugleRepositoryPortImpl.java | 7 ++++--- .../OpenApiHornBugleHistoryListResponse.java | 1 + .../dto/OpenApiHornBugleHistoryResponse.java | 1 + .../dto/response/HornBugleHistoryResponse.java | 1 + .../HornBugleKafkaProducerService.java | 3 ++- .../application/service/ItemInfoService.java | 9 +++++---- .../iteminfo/domain/entity/ItemInfoId.java | 3 ++- .../exception/ItemInfoExceptionCode.java | 4 ++-- .../repository/ItemInfoRepositoryPort.java | 3 ++- .../persistence/ItemInfoJpaRepository.java | 3 ++- .../ItemInfoQueryDslRepository.java | 3 ++- .../ItemInfoRepositoryPortImpl.java | 3 ++- .../rest/controller/ItemInfoController.java | 3 ++- .../dto/response/ItemCategoryResponse.java | 7 ++++--- .../rest/dto/response/ItemInfoResponse.java | 5 +++-- .../dto/response/ItemInfoSummaryResponse.java | 5 +++-- .../dto/response/ItemInfoSyncResponse.java | 3 ++- .../service/ItemOptionInfoService.java | 3 ++- .../domain/entity/ItemOptionInfoId.java | 5 +++-- .../ItemOptionInfoRepositoryPort.java | 5 +++-- .../ItemOptionInfoRepositoryPortImpl.java | 5 +++-- .../controller/ItemOptionInfoController.java | 5 +++-- .../service/MetalwareInfoService.java | 3 ++- .../MetalwareInfoJpaRepository.java | 3 ++- .../MetalwareInfoRepositoryPortImpl.java | 3 ++- .../controller/MetalwareInfoController.java | 3 ++- .../dto/response/MetalwareInfoResponse.java | 3 ++- .../service/AllTimeRankingService.java | 3 ++- .../service/CategoryRankingService.java | 3 ++- .../service/PriceChangeRankingService.java | 3 ++- .../service/PriceRankingService.java | 3 ++- .../service/VolumeRankingService.java | 3 ++- .../ranking/domain/mapper/RankingMapper.java | 5 +++-- .../controller/AllTimeRankingController.java | 3 ++- .../controller/CategoryRankingController.java | 3 ++- .../PriceChangeRankingController.java | 3 ++- .../controller/PriceRankingController.java | 3 ++- .../controller/VolumeRankingController.java | 3 ++- .../dto/response/AllTimeRankingResponse.java | 1 + .../response/PriceChangeRankingResponse.java | 1 + .../dto/response/PriceRankingResponse.java | 1 + .../response/VolumeChangeRankingResponse.java | 1 + .../dto/response/VolumeRankingResponse.java | 1 + .../ranking/repository/RankingRepository.java | 3 ++- .../service/ItemDailyStatisticsService.java | 7 ++++--- .../service/ItemWeeklyStatisticsService.java | 7 ++++--- .../SubcategoryDailyStatisticsService.java | 7 ++++--- .../SubcategoryWeeklyStatisticsService.java | 7 ++++--- .../TopCategoryDailyStatisticsService.java | 7 ++++--- .../TopCategoryWeeklyStatisticsService.java | 7 ++++--- .../entity/daily/ItemDailyStatistics.java | 3 ++- .../daily/SubcategoryDailyStatistics.java | 3 ++- .../daily/TopCategoryDailyStatistics.java | 3 ++- .../entity/weekly/ItemWeeklyStatistics.java | 3 ++- .../weekly/SubcategoryWeeklyStatistics.java | 3 ++- .../weekly/TopCategoryWeeklyStatistics.java | 3 ++- .../request/DailyStatisticsSearchRequest.java | 3 ++- .../ItemDailyStatisticsSearchRequest.java | 3 ++- .../ItemWeeklyStatisticsSearchRequest.java | 3 ++- ...ubcategoryDailyStatisticsSearchRequest.java | 3 ++- ...bcategoryWeeklyStatisticsSearchRequest.java | 3 ++- ...opCategoryDailyStatisticsSearchRequest.java | 3 ++- ...pCategoryWeeklyStatisticsSearchRequest.java | 3 ++- .../response/ItemDailyStatisticsResponse.java | 1 + .../response/ItemWeeklyStatisticsResponse.java | 1 + .../SubcategoryDailyStatisticsResponse.java | 1 + .../SubcategoryWeeklyStatisticsResponse.java | 1 + .../TopCategoryDailyStatisticsResponse.java | 1 + .../TopCategoryWeeklyStatisticsResponse.java | 1 + .../daily/ItemDailyStatisticsRepository.java | 5 +++-- .../SubcategoryDailyStatisticsRepository.java | 5 +++-- .../TopCategoryDailyStatisticsRepository.java | 5 +++-- .../weekly/ItemWeeklyStatisticsRepository.java | 3 ++- .../SubcategoryWeeklyStatisticsRepository.java | 3 ++- .../TopCategoryWeeklyStatisticsRepository.java | 3 ++- .../service/AuctionHistoryServiceTest.java | 13 +++++++------ .../fetcher/AuctionHistoryFetcherTest.java | 17 +++++++++-------- .../persister/AuctionHistoryPersisterTest.java | 13 +++++++------ .../AuctionHistoryDuplicateCheckerTest.java | 17 +++++++++-------- .../service/AuctionRealtimeServiceTest.java | 16 +++++++--------- .../fetcher/AuctionRealtimeFetcherTest.java | 15 ++++++++------- .../AuctionSearchOptionServiceTest.java | 11 ++++++----- .../common/util/SegongOptionParserTest.java | 4 ++-- .../service/ItemInfoServiceTest.java | 11 ++++++----- .../service/MetalwareInfoServiceTest.java | 9 +++++---- 179 files changed, 470 insertions(+), 323 deletions(-) diff --git a/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java b/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java index b4c857c0..64930e73 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java @@ -1,7 +1,5 @@ package until.the.eternity.auctionhistory.application.scheduler; -import java.util.*; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -19,6 +17,9 @@ import until.the.eternity.common.annotation.BatchLog; import until.the.eternity.common.enums.ItemCategory; +import java.util.*; +import java.util.stream.Collectors; + @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java index cc896233..032a46cc 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryService.java @@ -1,7 +1,6 @@ package until.the.eternity.auctionhistory.application.service; import jakarta.persistence.EntityManager; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -18,6 +17,8 @@ import until.the.eternity.common.response.PageResponseDto; import until.the.eternity.config.CacheNames; +import java.util.List; + @Service @RequiredArgsConstructor @Slf4j diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcher.java b/src/main/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcher.java index 4c0e05ad..3aa40844 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcher.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcher.java @@ -1,8 +1,5 @@ package until.the.eternity.auctionhistory.application.service.fetcher; -import java.util.ArrayList; -import java.util.List; -import java.util.OptionalInt; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -12,6 +9,10 @@ import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalInt; + @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersister.java b/src/main/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersister.java index 8112b804..ee426dd5 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersister.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersister.java @@ -1,6 +1,5 @@ package until.the.eternity.auctionhistory.application.service.persister; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -11,6 +10,8 @@ import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.List; + @Slf4j @RequiredArgsConstructor @Component diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/entity/AuctionHistory.java b/src/main/java/until/the/eternity/auctionhistory/domain/entity/AuctionHistory.java index af355e14..6f4cd7d8 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/entity/AuctionHistory.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/entity/AuctionHistory.java @@ -1,11 +1,12 @@ package until.the.eternity.auctionhistory.domain.entity; import jakarta.persistence.*; -import java.time.Instant; -import java.util.List; import lombok.*; import until.the.eternity.auctionitemoption.domain.entity.AuctionHistoryItemOption; +import java.time.Instant; +import java.util.List; + @Entity @Table(name = "auction_history") @Getter diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/event/AuctionHistorySavedEvent.java b/src/main/java/until/the/eternity/auctionhistory/domain/event/AuctionHistorySavedEvent.java index 213706e6..fe8f771f 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/event/AuctionHistorySavedEvent.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/event/AuctionHistorySavedEvent.java @@ -1,8 +1,9 @@ package until.the.eternity.auctionhistory.domain.event; -import java.time.LocalDateTime; import lombok.Getter; +import java.time.LocalDateTime; + /** 경매장 거래 내역 저장 완료 이벤트 AuctionHistoryScheduler가 거래 내역을 성공적으로 저장한 후 발행됩니다. */ @Getter public class AuctionHistorySavedEvent { diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/mapper/AuctionHistoryMapper.java b/src/main/java/until/the/eternity/auctionhistory/domain/mapper/AuctionHistoryMapper.java index 93a6fcaa..083ea00f 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/mapper/AuctionHistoryMapper.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/mapper/AuctionHistoryMapper.java @@ -1,6 +1,5 @@ package until.the.eternity.auctionhistory.domain.mapper; -import java.util.List; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; @@ -8,6 +7,8 @@ import until.the.eternity.auctionhistory.interfaces.rest.dto.response.ItemOptionResponse; import until.the.eternity.auctionitemoption.domain.entity.AuctionHistoryItemOption; +import java.util.List; + /** * AuctionHistory Entity to internal.responseDto transfer mapper class 데이터 흐름은 external.responseDto * -> entity -> internal.responseDto 단방향으로 흐름 diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/mapper/OpenApiAuctionHistoryMapper.java b/src/main/java/until/the/eternity/auctionhistory/domain/mapper/OpenApiAuctionHistoryMapper.java index 51f3748e..0b2b3bf9 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/mapper/OpenApiAuctionHistoryMapper.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/mapper/OpenApiAuctionHistoryMapper.java @@ -1,12 +1,13 @@ package until.the.eternity.auctionhistory.domain.mapper; -import java.time.Instant; -import java.util.List; import org.mapstruct.*; import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; + @Mapper(componentModel = "spring", uses = OpenApiItemOptionMapper.class) public interface OpenApiAuctionHistoryMapper { diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/repository/AuctionHistoryRepositoryPort.java b/src/main/java/until/the/eternity/auctionhistory/domain/repository/AuctionHistoryRepositoryPort.java index ca490fa1..f8a19073 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/repository/AuctionHistoryRepositoryPort.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/repository/AuctionHistoryRepositoryPort.java @@ -1,15 +1,16 @@ package until.the.eternity.auctionhistory.domain.repository; -import java.time.Instant; -import java.util.List; -import java.util.Optional; -import java.util.Set; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.Set; + /** 경매장 거래 내역 POJO Repository - Mock 또는 Stub 으로 대체해 단위 테스트 용이성 확보 */ public interface AuctionHistoryRepositoryPort { diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateChecker.java b/src/main/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateChecker.java index bb844332..dd43726c 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateChecker.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateChecker.java @@ -1,9 +1,5 @@ package until.the.eternity.auctionhistory.domain.service; -import java.time.Instant; -import java.util.List; -import java.util.OptionalInt; -import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -12,6 +8,11 @@ import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; +import java.util.OptionalInt; +import java.util.Set; + @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/service/fetcher/AuctionHistoryFetcherPort.java b/src/main/java/until/the/eternity/auctionhistory/domain/service/fetcher/AuctionHistoryFetcherPort.java index 5b649be4..cf00412a 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/service/fetcher/AuctionHistoryFetcherPort.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/service/fetcher/AuctionHistoryFetcherPort.java @@ -1,9 +1,10 @@ package until.the.eternity.auctionhistory.domain.service.fetcher; -import java.util.List; import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.List; + public interface AuctionHistoryFetcherPort { List fetch(ItemCategory category); } diff --git a/src/main/java/until/the/eternity/auctionhistory/domain/service/persister/AuctionHistoryPersisterPort.java b/src/main/java/until/the/eternity/auctionhistory/domain/service/persister/AuctionHistoryPersisterPort.java index 636f4c2d..44f59205 100644 --- a/src/main/java/until/the/eternity/auctionhistory/domain/service/persister/AuctionHistoryPersisterPort.java +++ b/src/main/java/until/the/eternity/auctionhistory/domain/service/persister/AuctionHistoryPersisterPort.java @@ -1,10 +1,11 @@ package until.the.eternity.auctionhistory.domain.service.persister; -import java.util.List; import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.List; + public interface AuctionHistoryPersisterPort { List filterOutExisting( diff --git a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryJpaRepository.java b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryJpaRepository.java index 4215b1f2..bdb982ab 100644 --- a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryJpaRepository.java +++ b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryJpaRepository.java @@ -1,8 +1,5 @@ package until.the.eternity.auctionhistory.infrastructure.persistence; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -10,6 +7,10 @@ import org.springframework.stereotype.Repository; import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + @Repository public interface AuctionHistoryJpaRepository extends JpaRepository, JpaSpecificationExecutor { diff --git a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java index d61e3a06..398e93cc 100644 --- a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java @@ -8,11 +8,6 @@ import com.querydsl.core.types.dsl.NumberTemplate; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -22,13 +17,15 @@ import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; import until.the.eternity.auctionhistory.domain.entity.QAuctionHistory; import until.the.eternity.auctionhistory.interfaces.rest.dto.enums.SearchStandard; -import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; -import until.the.eternity.auctionhistory.interfaces.rest.dto.request.DateAuctionBuyRequest; -import until.the.eternity.auctionhistory.interfaces.rest.dto.request.ItemOptionSearchRequest; -import until.the.eternity.auctionhistory.interfaces.rest.dto.request.MetalwareSearchRequest; -import until.the.eternity.auctionhistory.interfaces.rest.dto.request.PriceSearchRequest; +import until.the.eternity.auctionhistory.interfaces.rest.dto.request.*; import until.the.eternity.auctionitemoption.domain.entity.QAuctionHistoryItemOption; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; + @Component @RequiredArgsConstructor class AuctionHistoryQueryDslRepository { diff --git a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryRepositoryPortImpl.java b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryRepositoryPortImpl.java index 2b0cdf4d..65428ed2 100644 --- a/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryRepositoryPortImpl.java @@ -1,10 +1,6 @@ package until.the.eternity.auctionhistory.infrastructure.persistence; import jakarta.persistence.EntityManager; -import java.time.Instant; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; @@ -16,6 +12,11 @@ import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; + /** AuctionHistoryRepository Interface 구현체 */ @Repository @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryListResponse.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryListResponse.java index e194aeb7..c49a6b2b 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryListResponse.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryListResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionhistory.interfaces.external.dto; import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.List; public record OpenApiAuctionHistoryListResponse( diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryResponse.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryResponse.java index f41eb460..65b73ca5 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryResponse.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/external/dto/OpenApiAuctionHistoryResponse.java @@ -2,9 +2,10 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; +import until.the.eternity.auctionitemoption.domain.dto.external.OpenApiAuctionItemOptionResponse; + import java.time.Instant; import java.util.List; -import until.the.eternity.auctionitemoption.domain.dto.external.OpenApiAuctionItemOptionResponse; public record OpenApiAuctionHistoryResponse( @JsonProperty("item_name") String itemName, diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SearchStandard.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SearchStandard.java index ef005676..feb2c35e 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SearchStandard.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SearchStandard.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.Arrays; /** 검색 기준 (이상/이하/같음) */ diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SortDirection.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SortDirection.java index 82666061..e6aacf98 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SortDirection.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/enums/SortDirection.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.Arrays; /** 정렬 방향 (오름차순/내림차순) */ diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java index 1b616f5d..fcc2c3bd 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/request/AuctionHistorySearchRequest.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionhistory.interfaces.rest.dto.request; import io.swagger.v3.oas.annotations.media.Schema; + import java.time.LocalDate; import java.util.List; diff --git a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/response/AuctionHistoryDetailResponse.java b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/response/AuctionHistoryDetailResponse.java index 082c562f..d694c60c 100644 --- a/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/response/AuctionHistoryDetailResponse.java +++ b/src/main/java/until/the/eternity/auctionhistory/interfaces/rest/dto/response/AuctionHistoryDetailResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionhistory.interfaces.rest.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; + import java.time.Instant; import java.util.List; diff --git a/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItem.java b/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItem.java index ff498a80..d93c2eab 100644 --- a/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItem.java +++ b/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItem.java @@ -1,9 +1,10 @@ package until.the.eternity.auctionitem.domain.entity; import jakarta.persistence.*; +import lombok.*; + import java.time.Instant; import java.util.List; -import lombok.*; /** 실시간 경매장에서 판매 중인 아이템 정보. V15 마이그레이션에서 auction_item → auction_realtime_item으로 변경됨. */ @Entity diff --git a/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItemOption.java b/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItemOption.java index b0a651bf..28ba2905 100644 --- a/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItemOption.java +++ b/src/main/java/until/the/eternity/auctionitem/domain/entity/AuctionRealtimeItemOption.java @@ -1,12 +1,13 @@ package until.the.eternity.auctionitem.domain.entity; import jakarta.persistence.*; -import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.UUID; + /** 실시간 경매장 아이템(auction_realtime_item)에 연결된 아이템 옵션 정보. */ @Entity @Table(name = "auction_realtime_item_option") diff --git a/src/main/java/until/the/eternity/auctionitemoption/domain/entity/AuctionHistoryItemOption.java b/src/main/java/until/the/eternity/auctionitemoption/domain/entity/AuctionHistoryItemOption.java index dddac912..332605de 100644 --- a/src/main/java/until/the/eternity/auctionitemoption/domain/entity/AuctionHistoryItemOption.java +++ b/src/main/java/until/the/eternity/auctionitemoption/domain/entity/AuctionHistoryItemOption.java @@ -1,13 +1,14 @@ package until.the.eternity.auctionitemoption.domain.entity; import jakarta.persistence.*; -import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import until.the.eternity.auctionhistory.domain.entity.AuctionHistory; +import java.util.UUID; + /** * 경매장 거래 내역(auction_history)에 연결된 아이템 옵션 정보. V15 마이그레이션에서 auction_item_option → * auction_history_item_option으로 변경됨. diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java b/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java index 74296a41..865e2ab4 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/scheduler/AuctionRealtimeScheduler.java @@ -1,8 +1,5 @@ package until.the.eternity.auctionrealtime.application.scheduler; -import java.time.Instant; -import java.util.*; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -15,6 +12,10 @@ import until.the.eternity.auctionrealtime.domain.service.fetcher.AuctionRealtimeFetcherPort.FetchResult; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.*; +import java.util.stream.Collectors; + /** * 실시간 경매장 데이터 수집 스케줄러. * diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java b/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java index 07b1b2a5..9df0a986 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeService.java @@ -1,7 +1,5 @@ package until.the.eternity.auctionrealtime.application.service; -import java.time.Instant; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; @@ -20,6 +18,9 @@ import until.the.eternity.common.response.PageResponseDto; import until.the.eternity.config.CacheNames; +import java.time.Instant; +import java.util.List; + /** 실시간 경매장 데이터 Service. */ @Slf4j @Service diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcher.java b/src/main/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcher.java index b2da4f82..132e9d16 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcher.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcher.java @@ -1,7 +1,5 @@ package until.the.eternity.auctionrealtime.application.service.fetcher; -import java.util.ArrayList; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -11,6 +9,9 @@ import until.the.eternity.auctionrealtime.interfaces.external.dto.OpenApiAuctionRealtimeResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.ArrayList; +import java.util.List; + /** * 실시간 경매장 데이터 Fetcher 구현체. * diff --git a/src/main/java/until/the/eternity/auctionrealtime/application/service/persister/AuctionRealtimePersister.java b/src/main/java/until/the/eternity/auctionrealtime/application/service/persister/AuctionRealtimePersister.java index 10e0a9fc..81a73e29 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/application/service/persister/AuctionRealtimePersister.java +++ b/src/main/java/until/the/eternity/auctionrealtime/application/service/persister/AuctionRealtimePersister.java @@ -1,6 +1,5 @@ package until.the.eternity.auctionrealtime.application.service.persister; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -10,6 +9,8 @@ import until.the.eternity.auctionrealtime.interfaces.external.dto.OpenApiAuctionRealtimeResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.List; + /** 실시간 경매장 데이터 Persister 구현체. */ @Slf4j @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/AuctionRealtimeMapper.java b/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/AuctionRealtimeMapper.java index e373ae9c..f292d803 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/AuctionRealtimeMapper.java +++ b/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/AuctionRealtimeMapper.java @@ -1,6 +1,5 @@ package until.the.eternity.auctionrealtime.domain.mapper; -import java.util.List; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import until.the.eternity.auctionitem.domain.entity.AuctionRealtimeItem; @@ -8,6 +7,8 @@ import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.AuctionRealtimeDetailResponse; import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.RealtimeItemOptionResponse; +import java.util.List; + /** AuctionRealtimeItem Entity to DTO mapper class. */ @Mapper(componentModel = "spring") public interface AuctionRealtimeMapper { diff --git a/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/OpenApiAuctionRealtimeMapper.java b/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/OpenApiAuctionRealtimeMapper.java index 1409ba29..8f65de6b 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/OpenApiAuctionRealtimeMapper.java +++ b/src/main/java/until/the/eternity/auctionrealtime/domain/mapper/OpenApiAuctionRealtimeMapper.java @@ -1,13 +1,14 @@ package until.the.eternity.auctionrealtime.domain.mapper; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.List; import org.mapstruct.*; import until.the.eternity.auctionitem.domain.entity.AuctionRealtimeItem; import until.the.eternity.auctionrealtime.interfaces.external.dto.OpenApiAuctionRealtimeResponse; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.List; + /** OpenApiAuctionRealtimeResponse → AuctionRealtimeItem Entity 변환 Mapper. */ @Mapper(componentModel = "spring", uses = OpenApiRealtimeItemOptionMapper.class) public interface OpenApiAuctionRealtimeMapper { diff --git a/src/main/java/until/the/eternity/auctionrealtime/domain/repository/AuctionRealtimeItemRepositoryPort.java b/src/main/java/until/the/eternity/auctionrealtime/domain/repository/AuctionRealtimeItemRepositoryPort.java index 1ff1e35a..373499f7 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/domain/repository/AuctionRealtimeItemRepositoryPort.java +++ b/src/main/java/until/the/eternity/auctionrealtime/domain/repository/AuctionRealtimeItemRepositoryPort.java @@ -1,14 +1,15 @@ package until.the.eternity.auctionrealtime.domain.repository; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import until.the.eternity.auctionitem.domain.entity.AuctionRealtimeItem; import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + /** AuctionRealtimeItem Repository Port (Hexagonal Architecture). */ public interface AuctionRealtimeItemRepositoryPort { diff --git a/src/main/java/until/the/eternity/auctionrealtime/domain/service/fetcher/AuctionRealtimeFetcherPort.java b/src/main/java/until/the/eternity/auctionrealtime/domain/service/fetcher/AuctionRealtimeFetcherPort.java index 31220874..161e47ea 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/domain/service/fetcher/AuctionRealtimeFetcherPort.java +++ b/src/main/java/until/the/eternity/auctionrealtime/domain/service/fetcher/AuctionRealtimeFetcherPort.java @@ -1,9 +1,10 @@ package until.the.eternity.auctionrealtime.domain.service.fetcher; -import java.util.List; import until.the.eternity.auctionrealtime.interfaces.external.dto.OpenApiAuctionRealtimeResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.List; + /** 실시간 경매장 데이터 Fetcher Port. */ public interface AuctionRealtimeFetcherPort { diff --git a/src/main/java/until/the/eternity/auctionrealtime/domain/service/persister/AuctionRealtimePersisterPort.java b/src/main/java/until/the/eternity/auctionrealtime/domain/service/persister/AuctionRealtimePersisterPort.java index 41357a28..f5b6201e 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/domain/service/persister/AuctionRealtimePersisterPort.java +++ b/src/main/java/until/the/eternity/auctionrealtime/domain/service/persister/AuctionRealtimePersisterPort.java @@ -1,10 +1,11 @@ package until.the.eternity.auctionrealtime.domain.service.persister; -import java.util.List; import until.the.eternity.auctionitem.domain.entity.AuctionRealtimeItem; import until.the.eternity.auctionrealtime.interfaces.external.dto.OpenApiAuctionRealtimeResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.List; + /** 실시간 경매장 데이터 Persister Port. */ public interface AuctionRealtimePersisterPort { diff --git a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepository.java b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepository.java index 53cbdbf4..be29cbf2 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepository.java +++ b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepository.java @@ -1,12 +1,13 @@ package until.the.eternity.auctionrealtime.infrastructure.persistence; -import java.time.Instant; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import until.the.eternity.auctionitem.domain.entity.AuctionRealtimeItem; +import java.time.Instant; + /** AuctionRealtimeItem JPA Repository. */ public interface AuctionRealtimeItemRepository extends JpaRepository { diff --git a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepositoryPortImpl.java b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepositoryPortImpl.java index 6da0da26..b1b7c333 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeItemRepositoryPortImpl.java @@ -1,9 +1,6 @@ package until.the.eternity.auctionrealtime.infrastructure.persistence; import jakarta.persistence.EntityManager; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -14,6 +11,10 @@ import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + /** AuctionRealtimeItemRepositoryPort 구현체. */ @Slf4j @Repository diff --git a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java index 50e9d8fd..5b34c20a 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java +++ b/src/main/java/until/the/eternity/auctionrealtime/infrastructure/persistence/AuctionRealtimeQueryDslRepository.java @@ -8,11 +8,6 @@ import com.querydsl.core.types.dsl.NumberTemplate; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -29,6 +24,12 @@ import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.AuctionRealtimeSearchRequest; import until.the.eternity.auctionrealtime.interfaces.rest.dto.request.DateAuctionExpireRequest; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; + @Component @RequiredArgsConstructor class AuctionRealtimeQueryDslRepository { diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeListResponse.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeListResponse.java index 980fc9e3..114de80e 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeListResponse.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeListResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionrealtime.interfaces.external.dto; import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.List; /** Nexon Open API /auction/list 응답 리스트 DTO. */ diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeResponse.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeResponse.java index 28d59235..2b337bfe 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeResponse.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/external/dto/OpenApiAuctionRealtimeResponse.java @@ -2,9 +2,10 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; +import until.the.eternity.auctionitemoption.domain.dto.external.OpenApiAuctionItemOptionResponse; + import java.time.Instant; import java.util.List; -import until.the.eternity.auctionitemoption.domain.dto.external.OpenApiAuctionItemOptionResponse; /** Nexon Open API /auction/list 응답 DTO. 현재 경매장에서 판매 중인 아이템 정보. */ public record OpenApiAuctionRealtimeResponse( diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java index 52c78b90..e7ad9b2f 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/AuctionRealtimeSearchRequest.java @@ -1,12 +1,13 @@ package until.the.eternity.auctionrealtime.interfaces.rest.dto.request; import io.swagger.v3.oas.annotations.media.Schema; -import java.util.List; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.EnchantSearchRequest; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.ItemOptionSearchRequest; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.MetalwareSearchRequest; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.PriceSearchRequest; +import java.util.List; + /** 실시간 경매장 검색 조건 DTO */ @Schema(description = "실시간 경매장 검색 조건") public record AuctionRealtimeSearchRequest( diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/RealtimeSortField.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/RealtimeSortField.java index d59ce5dd..06e233cf 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/RealtimeSortField.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/request/RealtimeSortField.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.Arrays; /** 실시간 경매장 정렬 필드 */ diff --git a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/response/AuctionRealtimeDetailResponse.java b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/response/AuctionRealtimeDetailResponse.java index ba184764..a3d5a9e0 100644 --- a/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/response/AuctionRealtimeDetailResponse.java +++ b/src/main/java/until/the/eternity/auctionrealtime/interfaces/rest/dto/response/AuctionRealtimeDetailResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionrealtime.interfaces.rest.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; + import java.time.Instant; import java.util.List; diff --git a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java index 25e9f1be..05cb9986 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionService.java @@ -2,8 +2,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.List; -import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -15,6 +13,9 @@ import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.SearchOptionMetadataResponse; import until.the.eternity.config.CacheNames; +import java.util.List; +import java.util.Map; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/auctionsearchoption/domain/entity/AuctionSearchOptionMetadata.java b/src/main/java/until/the/eternity/auctionsearchoption/domain/entity/AuctionSearchOptionMetadata.java index 21a9e82b..5356db73 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/domain/entity/AuctionSearchOptionMetadata.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/domain/entity/AuctionSearchOptionMetadata.java @@ -1,13 +1,14 @@ package until.the.eternity.auctionsearchoption.domain.entity; import jakarta.persistence.*; -import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.type.SqlTypes; +import java.time.LocalDateTime; + @Entity @Table(name = "auction_search_option_metadata") @Getter diff --git a/src/main/java/until/the/eternity/auctionsearchoption/domain/repository/AuctionSearchOptionRepositoryPort.java b/src/main/java/until/the/eternity/auctionsearchoption/domain/repository/AuctionSearchOptionRepositoryPort.java index 971be29e..fe4e89b0 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/domain/repository/AuctionSearchOptionRepositoryPort.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/domain/repository/AuctionSearchOptionRepositoryPort.java @@ -1,8 +1,9 @@ package until.the.eternity.auctionsearchoption.domain.repository; -import java.util.List; import until.the.eternity.auctionsearchoption.domain.entity.AuctionSearchOptionMetadata; +import java.util.List; + public interface AuctionSearchOptionRepositoryPort { /** diff --git a/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionJpaRepository.java b/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionJpaRepository.java index e7074578..c18fd9e5 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionJpaRepository.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionJpaRepository.java @@ -1,10 +1,11 @@ package until.the.eternity.auctionsearchoption.infrastructure.persistence; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import until.the.eternity.auctionsearchoption.domain.entity.AuctionSearchOptionMetadata; +import java.util.List; + @Repository interface AuctionSearchOptionJpaRepository extends JpaRepository { diff --git a/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionRepositoryPortImpl.java b/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionRepositoryPortImpl.java index 850f43f4..2440e821 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/infrastructure/persistence/AuctionSearchOptionRepositoryPortImpl.java @@ -1,11 +1,12 @@ package until.the.eternity.auctionsearchoption.infrastructure.persistence; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import until.the.eternity.auctionsearchoption.domain.entity.AuctionSearchOptionMetadata; import until.the.eternity.auctionsearchoption.domain.repository.AuctionSearchOptionRepositoryPort; +import java.util.List; + @Component @RequiredArgsConstructor class AuctionSearchOptionRepositoryPortImpl implements AuctionSearchOptionRepositoryPort { diff --git a/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/AuctionSearchOptionController.java b/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/AuctionSearchOptionController.java index 8ad6484b..0231a36a 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/AuctionSearchOptionController.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/AuctionSearchOptionController.java @@ -2,7 +2,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -12,6 +11,8 @@ import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.SearchOptionMetadataResponse; import until.the.eternity.common.response.ApiResponse; +import java.util.List; + @Tag(name = "Auction Search Option", description = "경매 검색 옵션 API") @RestController @RequestMapping("/api/search-option") diff --git a/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/FieldMetadata.java b/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/FieldMetadata.java index 8b8b6ca1..43e5d916 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/FieldMetadata.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/FieldMetadata.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.List; @Schema(description = "검색 조건 필드 메타데이터") diff --git a/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/SearchOptionMetadataResponse.java b/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/SearchOptionMetadataResponse.java index 04581ef7..02c318fb 100644 --- a/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/SearchOptionMetadataResponse.java +++ b/src/main/java/until/the/eternity/auctionsearchoption/interfaces/rest/dto/response/SearchOptionMetadataResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.auctionsearchoption.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.Map; @Schema(description = "검색 옵션 메타데이터 응답") diff --git a/src/main/java/until/the/eternity/batchlog/application/service/BatchExecutionLogService.java b/src/main/java/until/the/eternity/batchlog/application/service/BatchExecutionLogService.java index 7f108b64..183e99f6 100644 --- a/src/main/java/until/the/eternity/batchlog/application/service/BatchExecutionLogService.java +++ b/src/main/java/until/the/eternity/batchlog/application/service/BatchExecutionLogService.java @@ -1,7 +1,5 @@ package until.the.eternity.batchlog.application.service; -import java.time.LocalDateTime; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -13,6 +11,9 @@ import until.the.eternity.batchlog.domain.enums.TriggerType; import until.the.eternity.batchlog.domain.repository.BatchExecutionLogRepositoryPort; +import java.time.LocalDateTime; +import java.util.List; + @Service @RequiredArgsConstructor public class BatchExecutionLogService { diff --git a/src/main/java/until/the/eternity/batchlog/domain/entity/BatchExecutionLog.java b/src/main/java/until/the/eternity/batchlog/domain/entity/BatchExecutionLog.java index 2eb8c424..ff42ddf2 100644 --- a/src/main/java/until/the/eternity/batchlog/domain/entity/BatchExecutionLog.java +++ b/src/main/java/until/the/eternity/batchlog/domain/entity/BatchExecutionLog.java @@ -1,13 +1,14 @@ package until.the.eternity.batchlog.domain.entity; import jakarta.persistence.*; -import java.time.LocalDateTime; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import until.the.eternity.batchlog.domain.enums.BatchType; import until.the.eternity.batchlog.domain.enums.TriggerType; +import java.time.LocalDateTime; + @Entity @Table(name = "batch_execution_log") @Getter diff --git a/src/main/java/until/the/eternity/batchlog/domain/repository/BatchExecutionLogRepositoryPort.java b/src/main/java/until/the/eternity/batchlog/domain/repository/BatchExecutionLogRepositoryPort.java index 694bbde8..c6777c89 100644 --- a/src/main/java/until/the/eternity/batchlog/domain/repository/BatchExecutionLogRepositoryPort.java +++ b/src/main/java/until/the/eternity/batchlog/domain/repository/BatchExecutionLogRepositoryPort.java @@ -1,11 +1,12 @@ package until.the.eternity.batchlog.domain.repository; -import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import until.the.eternity.batchlog.domain.entity.BatchExecutionLog; import until.the.eternity.batchlog.domain.enums.BatchType; +import java.util.List; + public interface BatchExecutionLogRepositoryPort { void save(BatchExecutionLog log); diff --git a/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogJpaRepository.java b/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogJpaRepository.java index 0def2940..9fa06d38 100644 --- a/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogJpaRepository.java +++ b/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogJpaRepository.java @@ -1,12 +1,13 @@ package until.the.eternity.batchlog.infrastructure.persistence; -import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import until.the.eternity.batchlog.domain.entity.BatchExecutionLog; import until.the.eternity.batchlog.domain.enums.BatchType; +import java.util.Optional; + public interface BatchExecutionLogJpaRepository extends JpaRepository { Page findByBatchTypeOrderByStartedAtDesc( diff --git a/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogRepositoryPortImpl.java b/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogRepositoryPortImpl.java index 7ece29b3..28bd82c4 100644 --- a/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/batchlog/infrastructure/persistence/BatchExecutionLogRepositoryPortImpl.java @@ -1,8 +1,5 @@ package until.the.eternity.batchlog.infrastructure.persistence; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -11,6 +8,10 @@ import until.the.eternity.batchlog.domain.enums.BatchType; import until.the.eternity.batchlog.domain.repository.BatchExecutionLogRepositoryPort; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + @Repository @RequiredArgsConstructor public class BatchExecutionLogRepositoryPortImpl implements BatchExecutionLogRepositoryPort { diff --git a/src/main/java/until/the/eternity/batchlog/interfaces/rest/controller/BatchExecutionLogController.java b/src/main/java/until/the/eternity/batchlog/interfaces/rest/controller/BatchExecutionLogController.java index 3e44b8e5..fda8059f 100644 --- a/src/main/java/until/the/eternity/batchlog/interfaces/rest/controller/BatchExecutionLogController.java +++ b/src/main/java/until/the/eternity/batchlog/interfaces/rest/controller/BatchExecutionLogController.java @@ -5,7 +5,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; @@ -20,6 +19,8 @@ import until.the.eternity.batchlog.interfaces.rest.dto.response.BatchExecutionLogResponse; import until.the.eternity.common.response.PageResponseDto; +import java.util.List; + @RestController @RequestMapping("/api/batch-logs") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/batchlog/interfaces/rest/dto/response/BatchExecutionLogResponse.java b/src/main/java/until/the/eternity/batchlog/interfaces/rest/dto/response/BatchExecutionLogResponse.java index edb134f8..8971fd41 100644 --- a/src/main/java/until/the/eternity/batchlog/interfaces/rest/dto/response/BatchExecutionLogResponse.java +++ b/src/main/java/until/the/eternity/batchlog/interfaces/rest/dto/response/BatchExecutionLogResponse.java @@ -1,11 +1,12 @@ package until.the.eternity.batchlog.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; -import java.time.LocalDateTime; import until.the.eternity.batchlog.domain.entity.BatchExecutionLog; import until.the.eternity.batchlog.domain.enums.BatchType; import until.the.eternity.batchlog.domain.enums.TriggerType; +import java.time.LocalDateTime; + @Schema(description = "배치 실행 로그 응답 DTO") public record BatchExecutionLogResponse( @Schema(description = "로그 ID") Long id, diff --git a/src/main/java/until/the/eternity/common/annotation/BatchLog.java b/src/main/java/until/the/eternity/common/annotation/BatchLog.java index 09776641..d33edfa3 100644 --- a/src/main/java/until/the/eternity/common/annotation/BatchLog.java +++ b/src/main/java/until/the/eternity/common/annotation/BatchLog.java @@ -1,8 +1,9 @@ package until.the.eternity.common.annotation; -import java.lang.annotation.*; import until.the.eternity.batchlog.domain.enums.BatchType; +import java.lang.annotation.*; + @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented diff --git a/src/main/java/until/the/eternity/common/annotation/MetalwareParameters.java b/src/main/java/until/the/eternity/common/annotation/MetalwareParameters.java index a6a9adcc..9efb1ea4 100644 --- a/src/main/java/until/the/eternity/common/annotation/MetalwareParameters.java +++ b/src/main/java/until/the/eternity/common/annotation/MetalwareParameters.java @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; + import java.lang.annotation.*; @Target(ElementType.METHOD) diff --git a/src/main/java/until/the/eternity/common/aspect/BatchExecutionLoggingAspect.java b/src/main/java/until/the/eternity/common/aspect/BatchExecutionLoggingAspect.java index 6644d3b3..51ed960e 100644 --- a/src/main/java/until/the/eternity/common/aspect/BatchExecutionLoggingAspect.java +++ b/src/main/java/until/the/eternity/common/aspect/BatchExecutionLoggingAspect.java @@ -1,6 +1,5 @@ package until.the.eternity.common.aspect; -import java.time.LocalDateTime; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; @@ -17,6 +16,8 @@ import until.the.eternity.common.annotation.BatchLog; import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSyncResponse; +import java.time.LocalDateTime; + @Slf4j @Aspect @Order(1) diff --git a/src/main/java/until/the/eternity/common/enums/ItemCategory.java b/src/main/java/until/the/eternity/common/enums/ItemCategory.java index 6b8ab078..ca9ee313 100644 --- a/src/main/java/until/the/eternity/common/enums/ItemCategory.java +++ b/src/main/java/until/the/eternity/common/enums/ItemCategory.java @@ -1,11 +1,12 @@ package until.the.eternity.common.enums; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + import java.util.Arrays; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; -import lombok.Getter; -import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/common/enums/SortDirection.java b/src/main/java/until/the/eternity/common/enums/SortDirection.java index 5e688da2..4a797556 100644 --- a/src/main/java/until/the/eternity/common/enums/SortDirection.java +++ b/src/main/java/until/the/eternity/common/enums/SortDirection.java @@ -3,9 +3,10 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; -import java.util.Arrays; import org.springframework.data.domain.Sort; +import java.util.Arrays; + /** 정렬 방향 (오름차순/내림차순) */ @Schema(description = "정렬 방향", enumAsRef = true) public enum SortDirection { diff --git a/src/main/java/until/the/eternity/common/enums/SortField.java b/src/main/java/until/the/eternity/common/enums/SortField.java index 704d79d5..3c26de2b 100644 --- a/src/main/java/until/the/eternity/common/enums/SortField.java +++ b/src/main/java/until/the/eternity/common/enums/SortField.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.Arrays; /** 정렬 필드 */ diff --git a/src/main/java/until/the/eternity/common/enums/UserRole.java b/src/main/java/until/the/eternity/common/enums/UserRole.java index 02d2ddd8..e6c61071 100644 --- a/src/main/java/until/the/eternity/common/enums/UserRole.java +++ b/src/main/java/until/the/eternity/common/enums/UserRole.java @@ -1,12 +1,13 @@ package until.the.eternity.common.enums; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + import java.util.Arrays; import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; -import lombok.Getter; -import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/common/exception/GlobalExceptionCode.java b/src/main/java/until/the/eternity/common/exception/GlobalExceptionCode.java index 21c217b0..1169e930 100644 --- a/src/main/java/until/the/eternity/common/exception/GlobalExceptionCode.java +++ b/src/main/java/until/the/eternity/common/exception/GlobalExceptionCode.java @@ -1,11 +1,11 @@ package until.the.eternity.common.exception; -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; - import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + @Getter @RequiredArgsConstructor public enum GlobalExceptionCode implements ExceptionCode { diff --git a/src/main/java/until/the/eternity/common/exception/GlobalExceptionHandler.java b/src/main/java/until/the/eternity/common/exception/GlobalExceptionHandler.java index 4cf5af10..bc069d00 100644 --- a/src/main/java/until/the/eternity/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/until/the/eternity/common/exception/GlobalExceptionHandler.java @@ -1,7 +1,5 @@ package until.the.eternity.common.exception; -import static until.the.eternity.common.exception.GlobalExceptionCode.SERVER_ERROR; - import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -9,6 +7,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import until.the.eternity.common.response.ApiResponse; +import static until.the.eternity.common.exception.GlobalExceptionCode.SERVER_ERROR; + @Slf4j @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { diff --git a/src/main/java/until/the/eternity/common/filter/GatewayAuthFilter.java b/src/main/java/until/the/eternity/common/filter/GatewayAuthFilter.java index 678f8ebc..703faeb7 100644 --- a/src/main/java/until/the/eternity/common/filter/GatewayAuthFilter.java +++ b/src/main/java/until/the/eternity/common/filter/GatewayAuthFilter.java @@ -4,9 +4,6 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,6 +17,10 @@ import until.the.eternity.common.enums.UserRole; import until.the.eternity.common.util.IpAddressUtil; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + /** * Gateway에서 전달한 인증 헤더(X-Auth-*)를 기반으로 Spring Security의 Authentication을 생성하는 필터 * diff --git a/src/main/java/until/the/eternity/common/response/ApiResponse.java b/src/main/java/until/the/eternity/common/response/ApiResponse.java index c7f83b13..c7b99b00 100644 --- a/src/main/java/until/the/eternity/common/response/ApiResponse.java +++ b/src/main/java/until/the/eternity/common/response/ApiResponse.java @@ -1,9 +1,10 @@ package until.the.eternity.common.response; -import java.time.Instant; import lombok.Builder; import lombok.Getter; +import java.time.Instant; + @Getter public class ApiResponse { diff --git a/src/main/java/until/the/eternity/common/response/PageResponseDto.java b/src/main/java/until/the/eternity/common/response/PageResponseDto.java index c142faac..0919ce20 100644 --- a/src/main/java/until/the/eternity/common/response/PageResponseDto.java +++ b/src/main/java/until/the/eternity/common/response/PageResponseDto.java @@ -1,6 +1,7 @@ package until.the.eternity.common.response; import io.swagger.v3.oas.annotations.media.Schema; + import java.util.List; @Schema(description = "페이지 응답 객체") diff --git a/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java b/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java index d1d72674..c309a241 100644 --- a/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java +++ b/src/main/java/until/the/eternity/common/util/CacheKeyBuilder.java @@ -1,6 +1,5 @@ package until.the.eternity.common.util; -import java.time.LocalDate; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest; @@ -9,6 +8,8 @@ import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest; import until.the.eternity.metalwareinfo.interfaces.rest.dto.request.MetalwareAttributeInfoSearchRequest; +import java.time.LocalDate; + public final class CacheKeyBuilder { private CacheKeyBuilder() {} diff --git a/src/main/java/until/the/eternity/common/util/SegongOptionParser.java b/src/main/java/until/the/eternity/common/util/SegongOptionParser.java index 3b362769..55fd9a26 100644 --- a/src/main/java/until/the/eternity/common/util/SegongOptionParser.java +++ b/src/main/java/until/the/eternity/common/util/SegongOptionParser.java @@ -1,8 +1,9 @@ package until.the.eternity.common.util; +import lombok.extern.slf4j.Slf4j; + import java.util.regex.Matcher; import java.util.regex.Pattern; -import lombok.extern.slf4j.Slf4j; /** * 세공 옵션의 option_value를 파싱하여 스킬명(option_value), 레벨(option_value2), 설명(option_desc)을 분리하는 유틸리티. diff --git a/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java b/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java index e22299ac..1fc82d99 100644 --- a/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java +++ b/src/main/java/until/the/eternity/config/CacheStartupWarmupRunner.java @@ -1,7 +1,5 @@ package until.the.eternity.config; -import java.time.LocalDate; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -27,18 +25,12 @@ import until.the.eternity.metalwareinfo.application.service.MetalwareInfoService; import until.the.eternity.metalwareinfo.interfaces.rest.dto.request.MetalwareAttributeInfoSearchRequest; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse; -import until.the.eternity.ranking.application.service.AllTimeRankingService; -import until.the.eternity.ranking.application.service.CategoryRankingService; -import until.the.eternity.ranking.application.service.PriceChangeRankingService; -import until.the.eternity.ranking.application.service.PriceRankingService; -import until.the.eternity.ranking.application.service.VolumeRankingService; +import until.the.eternity.ranking.application.service.*; import until.the.eternity.ranking.util.RankingConstants; -import until.the.eternity.statistics.application.service.ItemDailyStatisticsService; -import until.the.eternity.statistics.application.service.ItemWeeklyStatisticsService; -import until.the.eternity.statistics.application.service.SubcategoryDailyStatisticsService; -import until.the.eternity.statistics.application.service.SubcategoryWeeklyStatisticsService; -import until.the.eternity.statistics.application.service.TopCategoryDailyStatisticsService; -import until.the.eternity.statistics.application.service.TopCategoryWeeklyStatisticsService; +import until.the.eternity.statistics.application.service.*; + +import java.time.LocalDate; +import java.util.List; @Slf4j @Component diff --git a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java index ca5c391f..847ae193 100644 --- a/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java +++ b/src/main/java/until/the/eternity/config/RedisCacheErrorHandler.java @@ -1,10 +1,11 @@ package until.the.eternity.config; -import java.net.ConnectException; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.Cache; import org.springframework.cache.interceptor.CacheErrorHandler; +import java.net.ConnectException; + /** * Redis 장애 시 캐시 오류를 로깅만 하고 예외를 전파하지 않는 핸들러. * diff --git a/src/main/java/until/the/eternity/config/RedisConfig.java b/src/main/java/until/the/eternity/config/RedisConfig.java index 965b9506..abf5fad9 100644 --- a/src/main/java/until/the/eternity/config/RedisConfig.java +++ b/src/main/java/until/the/eternity/config/RedisConfig.java @@ -3,9 +3,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; import org.springframework.cache.annotation.CachingConfigurer; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheErrorHandler; @@ -18,6 +15,10 @@ import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + @Configuration @EnableCaching public class RedisConfig implements CachingConfigurer { diff --git a/src/main/java/until/the/eternity/config/openapi/OpenApiFilters.java b/src/main/java/until/the/eternity/config/openapi/OpenApiFilters.java index af0147a8..29ca38fe 100644 --- a/src/main/java/until/the/eternity/config/openapi/OpenApiFilters.java +++ b/src/main/java/until/the/eternity/config/openapi/OpenApiFilters.java @@ -1,12 +1,13 @@ package until.the.eternity.config.openapi; -import java.time.Duration; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import reactor.core.publisher.Mono; +import java.time.Duration; + @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/config/openapi/OpenApiRetryPolicy.java b/src/main/java/until/the/eternity/config/openapi/OpenApiRetryPolicy.java index 8c9d0cff..a419df7c 100644 --- a/src/main/java/until/the/eternity/config/openapi/OpenApiRetryPolicy.java +++ b/src/main/java/until/the/eternity/config/openapi/OpenApiRetryPolicy.java @@ -1,11 +1,12 @@ package until.the.eternity.config.openapi; -import java.time.Duration; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; +import java.time.Duration; + /** Nexon OPEN API 전용 재시도(Back-off) 정책. */ @Component public class OpenApiRetryPolicy { diff --git a/src/main/java/until/the/eternity/config/openapi/OpenApiWebClientProperties.java b/src/main/java/until/the/eternity/config/openapi/OpenApiWebClientProperties.java index 9d51746d..f8d79043 100644 --- a/src/main/java/until/the/eternity/config/openapi/OpenApiWebClientProperties.java +++ b/src/main/java/until/the/eternity/config/openapi/OpenApiWebClientProperties.java @@ -2,10 +2,11 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Positive; -import java.time.Duration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; +import java.time.Duration; + /** 외부 API용 WebClient 설정값 홀더 application.yml 사용) */ @Validated @ConfigurationProperties(prefix = "openapi.nexon") diff --git a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java index 5d672321..18a9b3af 100644 --- a/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java +++ b/src/main/java/until/the/eternity/enchantinfo/application/service/EnchantInfoService.java @@ -1,7 +1,5 @@ package until.the.eternity.enchantinfo.application.service; -import java.util.List; -import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -17,6 +15,9 @@ import until.the.eternity.enchantinfo.interfaces.rest.dto.response.EnchantInfoResponse; import until.the.eternity.enchantinfo.interfaces.rest.dto.response.EnchantInfoSyncResponse; +import java.util.List; +import java.util.Set; + @Service @Transactional(readOnly = true) @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/enchantinfo/domain/exception/EnchantInfoExceptionCode.java b/src/main/java/until/the/eternity/enchantinfo/domain/exception/EnchantInfoExceptionCode.java index ab88e521..6fc377b0 100644 --- a/src/main/java/until/the/eternity/enchantinfo/domain/exception/EnchantInfoExceptionCode.java +++ b/src/main/java/until/the/eternity/enchantinfo/domain/exception/EnchantInfoExceptionCode.java @@ -1,12 +1,12 @@ package until.the.eternity.enchantinfo.domain.exception; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import until.the.eternity.common.exception.ExceptionCode; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + @Getter @RequiredArgsConstructor public enum EnchantInfoExceptionCode implements ExceptionCode { diff --git a/src/main/java/until/the/eternity/enchantinfo/domain/repository/EnchantInfoRepositoryPort.java b/src/main/java/until/the/eternity/enchantinfo/domain/repository/EnchantInfoRepositoryPort.java index 753bf6ad..379972de 100644 --- a/src/main/java/until/the/eternity/enchantinfo/domain/repository/EnchantInfoRepositoryPort.java +++ b/src/main/java/until/the/eternity/enchantinfo/domain/repository/EnchantInfoRepositoryPort.java @@ -1,10 +1,11 @@ package until.the.eternity.enchantinfo.domain.repository; -import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import until.the.eternity.enchantinfo.infrastructure.persistence.EnchantInfoEntity; +import java.util.List; + public interface EnchantInfoRepositoryPort { Page findAll(Pageable pageable); diff --git a/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoEntity.java b/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoEntity.java index 60783446..370c3c3b 100644 --- a/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoEntity.java +++ b/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoEntity.java @@ -1,11 +1,6 @@ package until.the.eternity.enchantinfo.infrastructure.persistence; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoJpaRepository.java b/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoJpaRepository.java index 392c1fe7..b007aae5 100644 --- a/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoJpaRepository.java +++ b/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoJpaRepository.java @@ -1,10 +1,11 @@ package until.the.eternity.enchantinfo.infrastructure.persistence; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import java.util.List; + public interface EnchantInfoJpaRepository extends JpaRepository { @Query("SELECT e.fullname FROM EnchantInfoEntity e ORDER BY e.id ASC") diff --git a/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoRepositoryPortImpl.java b/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoRepositoryPortImpl.java index e0c27316..600bde4a 100644 --- a/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/enchantinfo/infrastructure/persistence/EnchantInfoRepositoryPortImpl.java @@ -1,12 +1,13 @@ package until.the.eternity.enchantinfo.infrastructure.persistence; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Repository; import until.the.eternity.enchantinfo.domain.repository.EnchantInfoRepositoryPort; +import java.util.List; + @Repository @RequiredArgsConstructor public class EnchantInfoRepositoryPortImpl implements EnchantInfoRepositoryPort { diff --git a/src/main/java/until/the/eternity/enchantinfo/interfaces/rest/controller/EnchantInfoController.java b/src/main/java/until/the/eternity/enchantinfo/interfaces/rest/controller/EnchantInfoController.java index 14222db8..6db5b49b 100644 --- a/src/main/java/until/the/eternity/enchantinfo/interfaces/rest/controller/EnchantInfoController.java +++ b/src/main/java/until/the/eternity/enchantinfo/interfaces/rest/controller/EnchantInfoController.java @@ -5,22 +5,18 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import until.the.eternity.enchantinfo.application.service.EnchantInfoService; import until.the.eternity.enchantinfo.interfaces.rest.dto.request.EnchantInfoPageRequestDto; import until.the.eternity.enchantinfo.interfaces.rest.dto.response.EnchantInfoResponse; import until.the.eternity.enchantinfo.interfaces.rest.dto.response.EnchantInfoSyncResponse; +import java.util.List; + @RestController @RequestMapping("/api/enchant-infos") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/hornBugle/application/runner/HornBugleIndexRunner.java b/src/main/java/until/the/eternity/hornBugle/application/runner/HornBugleIndexRunner.java index f4da3691..f96534ff 100644 --- a/src/main/java/until/the/eternity/hornBugle/application/runner/HornBugleIndexRunner.java +++ b/src/main/java/until/the/eternity/hornBugle/application/runner/HornBugleIndexRunner.java @@ -1,6 +1,5 @@ package until.the.eternity.hornBugle.application.runner; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; @@ -14,6 +13,8 @@ import until.the.eternity.hornBugle.domain.repository.HornBugleRepositoryPort; import until.the.eternity.hornBugle.infrastructure.elasticsearch.HornBugleIndexService; +import java.util.List; + /** * 서버 재기동 시 DB 데이터를 Elasticsearch에 일괄 색인하는 Runner. application.yml에서 * elasticsearch.index.enabled=true로 설정 시 활성화됩니다. diff --git a/src/main/java/until/the/eternity/hornBugle/application/scheduler/HornBugleScheduler.java b/src/main/java/until/the/eternity/hornBugle/application/scheduler/HornBugleScheduler.java index aaa6f55e..1fe31492 100644 --- a/src/main/java/until/the/eternity/hornBugle/application/scheduler/HornBugleScheduler.java +++ b/src/main/java/until/the/eternity/hornBugle/application/scheduler/HornBugleScheduler.java @@ -1,10 +1,5 @@ package until.the.eternity.hornBugle.application.scheduler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -20,6 +15,12 @@ import until.the.eternity.hornBugle.kafka.application.HornBugleKafkaProducerService; import until.the.eternity.hornBugle.kafka.dto.UserVerificationVerifyEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/hornBugle/application/service/HornBugleService.java b/src/main/java/until/the/eternity/hornBugle/application/service/HornBugleService.java index ed11102f..dc650089 100644 --- a/src/main/java/until/the/eternity/hornBugle/application/service/HornBugleService.java +++ b/src/main/java/until/the/eternity/hornBugle/application/service/HornBugleService.java @@ -1,8 +1,5 @@ package until.the.eternity.hornBugle.application.service; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; @@ -19,6 +16,10 @@ import until.the.eternity.hornBugle.interfaces.rest.dto.request.HornBuglePageRequestDto; import until.the.eternity.hornBugle.interfaces.rest.dto.response.HornBugleHistoryResponse; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + @Slf4j @Service public class HornBugleService { diff --git a/src/main/java/until/the/eternity/hornBugle/domain/entity/HornBugleWorldHistory.java b/src/main/java/until/the/eternity/hornBugle/domain/entity/HornBugleWorldHistory.java index 482c8572..05ca8dff 100644 --- a/src/main/java/until/the/eternity/hornBugle/domain/entity/HornBugleWorldHistory.java +++ b/src/main/java/until/the/eternity/hornBugle/domain/entity/HornBugleWorldHistory.java @@ -1,9 +1,10 @@ package until.the.eternity.hornBugle.domain.entity; import jakarta.persistence.*; -import java.time.Instant; import lombok.*; +import java.time.Instant; + @Entity @Table( name = "horn_bugle_world_history", diff --git a/src/main/java/until/the/eternity/hornBugle/domain/enums/HornBugleServer.java b/src/main/java/until/the/eternity/hornBugle/domain/enums/HornBugleServer.java index fe361d09..51bd034f 100644 --- a/src/main/java/until/the/eternity/hornBugle/domain/enums/HornBugleServer.java +++ b/src/main/java/until/the/eternity/hornBugle/domain/enums/HornBugleServer.java @@ -1,10 +1,11 @@ package until.the.eternity.hornBugle.domain.enums; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import lombok.Getter; -import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/hornBugle/domain/mapper/HornBugleMapper.java b/src/main/java/until/the/eternity/hornBugle/domain/mapper/HornBugleMapper.java index a24aee75..c2bb9e73 100644 --- a/src/main/java/until/the/eternity/hornBugle/domain/mapper/HornBugleMapper.java +++ b/src/main/java/until/the/eternity/hornBugle/domain/mapper/HornBugleMapper.java @@ -1,6 +1,5 @@ package until.the.eternity.hornBugle.domain.mapper; -import java.time.Instant; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import until.the.eternity.hornBugle.domain.entity.HornBugleWorldHistory; @@ -9,6 +8,8 @@ import until.the.eternity.hornBugle.interfaces.external.dto.OpenApiHornBugleHistoryResponse; import until.the.eternity.hornBugle.interfaces.rest.dto.response.HornBugleHistoryResponse; +import java.time.Instant; + @Mapper(componentModel = "spring") public interface HornBugleMapper { diff --git a/src/main/java/until/the/eternity/hornBugle/domain/repository/HornBugleRepositoryPort.java b/src/main/java/until/the/eternity/hornBugle/domain/repository/HornBugleRepositoryPort.java index 8e85b756..75dfd277 100644 --- a/src/main/java/until/the/eternity/hornBugle/domain/repository/HornBugleRepositoryPort.java +++ b/src/main/java/until/the/eternity/hornBugle/domain/repository/HornBugleRepositoryPort.java @@ -1,12 +1,13 @@ package until.the.eternity.hornBugle.domain.repository; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import until.the.eternity.hornBugle.domain.entity.HornBugleWorldHistory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + public interface HornBugleRepositoryPort { void saveAll(List entities); diff --git a/src/main/java/until/the/eternity/hornBugle/domain/service/HornBugleDuplicateChecker.java b/src/main/java/until/the/eternity/hornBugle/domain/service/HornBugleDuplicateChecker.java index 846ea39a..4d8be4d3 100644 --- a/src/main/java/until/the/eternity/hornBugle/domain/service/HornBugleDuplicateChecker.java +++ b/src/main/java/until/the/eternity/hornBugle/domain/service/HornBugleDuplicateChecker.java @@ -1,10 +1,5 @@ package until.the.eternity.hornBugle.domain.service; -import java.time.Instant; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -13,6 +8,12 @@ import until.the.eternity.hornBugle.domain.repository.HornBugleRepositoryPort; import until.the.eternity.hornBugle.interfaces.external.dto.OpenApiHornBugleHistoryResponse; +import java.time.Instant; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleDocument.java b/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleDocument.java index 7c0ceb37..98bb7864 100644 --- a/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleDocument.java +++ b/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleDocument.java @@ -1,6 +1,5 @@ package until.the.eternity.hornBugle.infrastructure.elasticsearch; -import java.time.Instant; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -12,6 +11,8 @@ import org.springframework.data.elasticsearch.annotations.Setting; import until.the.eternity.hornBugle.domain.entity.HornBugleWorldHistory; +import java.time.Instant; + @Document(indexName = "horn_bugle_world_history") @Setting(settingPath = "elasticsearch/horn-bugle-settings.json") @Getter diff --git a/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleIndexService.java b/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleIndexService.java index d439bfb8..52f59505 100644 --- a/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleIndexService.java +++ b/src/main/java/until/the/eternity/hornBugle/infrastructure/elasticsearch/HornBugleIndexService.java @@ -2,7 +2,6 @@ import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; import co.elastic.clients.elasticsearch._types.query_dsl.Query; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -18,6 +17,8 @@ import org.springframework.stereotype.Service; import until.the.eternity.hornBugle.domain.entity.HornBugleWorldHistory; +import java.util.List; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleJpaRepository.java b/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleJpaRepository.java index 2e6acde1..e68b01eb 100644 --- a/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleJpaRepository.java +++ b/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleJpaRepository.java @@ -1,8 +1,5 @@ package until.the.eternity.hornBugle.infrastructure.persistence; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -10,6 +7,10 @@ import org.springframework.stereotype.Repository; import until.the.eternity.hornBugle.domain.entity.HornBugleWorldHistory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + @Repository public interface HornBugleJpaRepository extends JpaRepository { diff --git a/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleRepositoryPortImpl.java b/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleRepositoryPortImpl.java index 52366b65..706bc05b 100644 --- a/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/hornBugle/infrastructure/persistence/HornBugleRepositoryPortImpl.java @@ -1,9 +1,6 @@ package until.the.eternity.hornBugle.infrastructure.persistence; import jakarta.persistence.EntityManager; -import java.time.Instant; -import java.util.List; -import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; @@ -13,6 +10,10 @@ import until.the.eternity.hornBugle.domain.entity.HornBugleWorldHistory; import until.the.eternity.hornBugle.domain.repository.HornBugleRepositoryPort; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + @Repository @RequiredArgsConstructor public class HornBugleRepositoryPortImpl implements HornBugleRepositoryPort { diff --git a/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryListResponse.java b/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryListResponse.java index 4090a2d4..adea275a 100644 --- a/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryListResponse.java +++ b/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryListResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.hornBugle.interfaces.external.dto; import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.List; public record OpenApiHornBugleHistoryListResponse( diff --git a/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryResponse.java b/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryResponse.java index 1a11eb0f..78f67772 100644 --- a/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryResponse.java +++ b/src/main/java/until/the/eternity/hornBugle/interfaces/external/dto/OpenApiHornBugleHistoryResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; + import java.time.Instant; public record OpenApiHornBugleHistoryResponse( diff --git a/src/main/java/until/the/eternity/hornBugle/interfaces/rest/dto/response/HornBugleHistoryResponse.java b/src/main/java/until/the/eternity/hornBugle/interfaces/rest/dto/response/HornBugleHistoryResponse.java index cd47b1c0..7660ff1a 100644 --- a/src/main/java/until/the/eternity/hornBugle/interfaces/rest/dto/response/HornBugleHistoryResponse.java +++ b/src/main/java/until/the/eternity/hornBugle/interfaces/rest/dto/response/HornBugleHistoryResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.time.Instant; @Schema(description = "뿔피리 히스토리 응답") diff --git a/src/main/java/until/the/eternity/hornBugle/kafka/application/HornBugleKafkaProducerService.java b/src/main/java/until/the/eternity/hornBugle/kafka/application/HornBugleKafkaProducerService.java index 6a5d854a..df662e9b 100644 --- a/src/main/java/until/the/eternity/hornBugle/kafka/application/HornBugleKafkaProducerService.java +++ b/src/main/java/until/the/eternity/hornBugle/kafka/application/HornBugleKafkaProducerService.java @@ -1,6 +1,5 @@ package until.the.eternity.hornBugle.kafka.application; -import java.util.concurrent.CompletableFuture; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.kafka.core.KafkaTemplate; @@ -9,6 +8,8 @@ import until.the.eternity.common.constant.KafkaTopicConstant; import until.the.eternity.hornBugle.kafka.dto.UserVerificationVerifyEvent; +import java.util.concurrent.CompletableFuture; + @Service @RequiredArgsConstructor public class HornBugleKafkaProducerService { diff --git a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java index 6275c02d..4527a44e 100644 --- a/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java +++ b/src/main/java/until/the/eternity/iteminfo/application/service/ItemInfoService.java @@ -1,9 +1,5 @@ package until.the.eternity.iteminfo.application.service; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; @@ -26,6 +22,11 @@ import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSummaryResponse; import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSyncResponse; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + @Slf4j @Service @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/iteminfo/domain/entity/ItemInfoId.java b/src/main/java/until/the/eternity/iteminfo/domain/entity/ItemInfoId.java index d53cd3b3..6293e4ee 100644 --- a/src/main/java/until/the/eternity/iteminfo/domain/entity/ItemInfoId.java +++ b/src/main/java/until/the/eternity/iteminfo/domain/entity/ItemInfoId.java @@ -2,9 +2,10 @@ import jakarta.persistence.Column; import jakarta.persistence.Embeddable; -import java.io.Serializable; import lombok.*; +import java.io.Serializable; + @Embeddable @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/until/the/eternity/iteminfo/domain/exception/ItemInfoExceptionCode.java b/src/main/java/until/the/eternity/iteminfo/domain/exception/ItemInfoExceptionCode.java index a7ffd4c2..f870031a 100644 --- a/src/main/java/until/the/eternity/iteminfo/domain/exception/ItemInfoExceptionCode.java +++ b/src/main/java/until/the/eternity/iteminfo/domain/exception/ItemInfoExceptionCode.java @@ -1,12 +1,12 @@ package until.the.eternity.iteminfo.domain.exception; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import until.the.eternity.common.exception.ExceptionCode; +import static org.springframework.http.HttpStatus.BAD_REQUEST; + @Getter @RequiredArgsConstructor public enum ItemInfoExceptionCode implements ExceptionCode { diff --git a/src/main/java/until/the/eternity/iteminfo/domain/repository/ItemInfoRepositoryPort.java b/src/main/java/until/the/eternity/iteminfo/domain/repository/ItemInfoRepositoryPort.java index b540fc66..c9f85ea3 100644 --- a/src/main/java/until/the/eternity/iteminfo/domain/repository/ItemInfoRepositoryPort.java +++ b/src/main/java/until/the/eternity/iteminfo/domain/repository/ItemInfoRepositoryPort.java @@ -1,12 +1,13 @@ package until.the.eternity.iteminfo.domain.repository; -import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import until.the.eternity.iteminfo.domain.entity.ItemInfo; import until.the.eternity.iteminfo.domain.entity.ItemInfoId; import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest; +import java.util.List; + public interface ItemInfoRepositoryPort { List findAll(); diff --git a/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoJpaRepository.java b/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoJpaRepository.java index 2be98732..c6838467 100644 --- a/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoJpaRepository.java +++ b/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoJpaRepository.java @@ -1,12 +1,13 @@ package until.the.eternity.iteminfo.infrastructure.persistence; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import until.the.eternity.iteminfo.domain.entity.ItemInfo; import until.the.eternity.iteminfo.domain.entity.ItemInfoId; +import java.util.List; + public interface ItemInfoJpaRepository extends JpaRepository, JpaSpecificationExecutor { diff --git a/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoQueryDslRepository.java b/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoQueryDslRepository.java index 266b2303..e13e45f9 100644 --- a/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoQueryDslRepository.java +++ b/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoQueryDslRepository.java @@ -3,7 +3,6 @@ import com.querydsl.core.BooleanBuilder; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -13,6 +12,8 @@ import until.the.eternity.iteminfo.domain.entity.QItemInfo; import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest; +import java.util.List; + @Repository @RequiredArgsConstructor public class ItemInfoQueryDslRepository { diff --git a/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoRepositoryPortImpl.java b/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoRepositoryPortImpl.java index 66481cac..497ad7d1 100644 --- a/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/iteminfo/infrastructure/persistence/ItemInfoRepositoryPortImpl.java @@ -1,6 +1,5 @@ package until.the.eternity.iteminfo.infrastructure.persistence; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -10,6 +9,8 @@ import until.the.eternity.iteminfo.domain.repository.ItemInfoRepositoryPort; import until.the.eternity.iteminfo.interfaces.rest.dto.request.ItemInfoSearchRequest; +import java.util.List; + @Repository @RequiredArgsConstructor public class ItemInfoRepositoryPortImpl implements ItemInfoRepositoryPort { diff --git a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/controller/ItemInfoController.java b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/controller/ItemInfoController.java index 33463e87..da5d2611 100644 --- a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/controller/ItemInfoController.java +++ b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/controller/ItemInfoController.java @@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; @@ -20,6 +19,8 @@ import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSummaryResponse; import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSyncResponse; +import java.util.List; + @RestController @RequestMapping("/api/item-infos") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemCategoryResponse.java b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemCategoryResponse.java index 065d209e..0b1e6817 100644 --- a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemCategoryResponse.java +++ b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemCategoryResponse.java @@ -1,12 +1,13 @@ package until.the.eternity.iteminfo.interfaces.rest.dto.response; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; import lombok.Builder; import lombok.Getter; import until.the.eternity.common.enums.ItemCategory; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + @Getter @Builder public class ItemCategoryResponse { diff --git a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoResponse.java b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoResponse.java index be9d890b..70897793 100644 --- a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoResponse.java +++ b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoResponse.java @@ -1,11 +1,12 @@ package until.the.eternity.iteminfo.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; -import java.util.List; -import java.util.stream.Collectors; import lombok.Builder; import until.the.eternity.iteminfo.domain.entity.ItemInfo; +import java.util.List; +import java.util.stream.Collectors; + @Builder @Schema(description = "아이템 정보 응답 DTO") public record ItemInfoResponse( diff --git a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSummaryResponse.java b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSummaryResponse.java index 98e5cfd5..4b9da91b 100644 --- a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSummaryResponse.java +++ b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSummaryResponse.java @@ -1,11 +1,12 @@ package until.the.eternity.iteminfo.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; -import java.util.List; -import java.util.stream.Collectors; import lombok.Builder; import until.the.eternity.iteminfo.domain.entity.ItemInfo; +import java.util.List; +import java.util.stream.Collectors; + @Builder @Schema(description = "아이템 정보 요약 응답 DTO") public record ItemInfoSummaryResponse( diff --git a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSyncResponse.java b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSyncResponse.java index e98fce37..02016f52 100644 --- a/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSyncResponse.java +++ b/src/main/java/until/the/eternity/iteminfo/interfaces/rest/dto/response/ItemInfoSyncResponse.java @@ -1,9 +1,10 @@ package until.the.eternity.iteminfo.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; -import java.util.List; import lombok.Builder; +import java.util.List; + @Builder @Schema(description = "아이템 정보 동기화 응답 DTO") public record ItemInfoSyncResponse( diff --git a/src/main/java/until/the/eternity/itemoptioninfo/application/service/ItemOptionInfoService.java b/src/main/java/until/the/eternity/itemoptioninfo/application/service/ItemOptionInfoService.java index e4f5da74..8595e38c 100644 --- a/src/main/java/until/the/eternity/itemoptioninfo/application/service/ItemOptionInfoService.java +++ b/src/main/java/until/the/eternity/itemoptioninfo/application/service/ItemOptionInfoService.java @@ -1,6 +1,5 @@ package until.the.eternity.itemoptioninfo.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,6 +7,8 @@ import until.the.eternity.itemoptioninfo.domain.entity.ItemOptionInfoId; import until.the.eternity.itemoptioninfo.domain.repository.ItemOptionInfoRepositoryPort; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/itemoptioninfo/domain/entity/ItemOptionInfoId.java b/src/main/java/until/the/eternity/itemoptioninfo/domain/entity/ItemOptionInfoId.java index 17634464..5bbcdaf9 100644 --- a/src/main/java/until/the/eternity/itemoptioninfo/domain/entity/ItemOptionInfoId.java +++ b/src/main/java/until/the/eternity/itemoptioninfo/domain/entity/ItemOptionInfoId.java @@ -2,12 +2,13 @@ import jakarta.persistence.Column; import jakarta.persistence.Embeddable; -import java.io.Serializable; -import java.util.Objects; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import java.io.Serializable; +import java.util.Objects; + @Embeddable @Getter @NoArgsConstructor diff --git a/src/main/java/until/the/eternity/itemoptioninfo/domain/repository/ItemOptionInfoRepositoryPort.java b/src/main/java/until/the/eternity/itemoptioninfo/domain/repository/ItemOptionInfoRepositoryPort.java index 904949d5..37076dd7 100644 --- a/src/main/java/until/the/eternity/itemoptioninfo/domain/repository/ItemOptionInfoRepositoryPort.java +++ b/src/main/java/until/the/eternity/itemoptioninfo/domain/repository/ItemOptionInfoRepositoryPort.java @@ -1,10 +1,11 @@ package until.the.eternity.itemoptioninfo.domain.repository; -import java.util.List; -import java.util.Optional; import until.the.eternity.itemoptioninfo.domain.entity.ItemOptionInfo; import until.the.eternity.itemoptioninfo.domain.entity.ItemOptionInfoId; +import java.util.List; +import java.util.Optional; + public interface ItemOptionInfoRepositoryPort { List findAll(); diff --git a/src/main/java/until/the/eternity/itemoptioninfo/infrastructure/persistence/ItemOptionInfoRepositoryPortImpl.java b/src/main/java/until/the/eternity/itemoptioninfo/infrastructure/persistence/ItemOptionInfoRepositoryPortImpl.java index f8f7f1cc..0d5c1247 100644 --- a/src/main/java/until/the/eternity/itemoptioninfo/infrastructure/persistence/ItemOptionInfoRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/itemoptioninfo/infrastructure/persistence/ItemOptionInfoRepositoryPortImpl.java @@ -1,13 +1,14 @@ package until.the.eternity.itemoptioninfo.infrastructure.persistence; -import java.util.List; -import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import until.the.eternity.itemoptioninfo.domain.entity.ItemOptionInfo; import until.the.eternity.itemoptioninfo.domain.entity.ItemOptionInfoId; import until.the.eternity.itemoptioninfo.domain.repository.ItemOptionInfoRepositoryPort; +import java.util.List; +import java.util.Optional; + @Repository @RequiredArgsConstructor public class ItemOptionInfoRepositoryPortImpl implements ItemOptionInfoRepositoryPort { diff --git a/src/main/java/until/the/eternity/itemoptioninfo/interfaces/rest/controller/ItemOptionInfoController.java b/src/main/java/until/the/eternity/itemoptioninfo/interfaces/rest/controller/ItemOptionInfoController.java index e36b5213..f5351cc9 100644 --- a/src/main/java/until/the/eternity/itemoptioninfo/interfaces/rest/controller/ItemOptionInfoController.java +++ b/src/main/java/until/the/eternity/itemoptioninfo/interfaces/rest/controller/ItemOptionInfoController.java @@ -4,8 +4,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -17,6 +15,9 @@ import until.the.eternity.itemoptioninfo.interfaces.rest.dto.request.ItemOptionInfoRequest; import until.the.eternity.itemoptioninfo.interfaces.rest.dto.response.ItemOptionInfoResponse; +import java.util.List; +import java.util.stream.Collectors; + @RestController @RequestMapping("/api/v1/item-option-infos") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java index 7c734b4d..d1e74172 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java +++ b/src/main/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoService.java @@ -1,6 +1,5 @@ package until.the.eternity.metalwareinfo.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -12,6 +11,8 @@ import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoSyncResponse; +import java.util.List; + @Service @Transactional(readOnly = true) @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoJpaRepository.java b/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoJpaRepository.java index b0610721..bcb58052 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoJpaRepository.java +++ b/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoJpaRepository.java @@ -1,10 +1,11 @@ package until.the.eternity.metalwareinfo.infrastructure.persistence; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import java.util.List; + public interface MetalwareInfoJpaRepository extends JpaRepository { @Query("SELECT m.metalware FROM MetalwareInfoEntity m") diff --git a/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoRepositoryPortImpl.java b/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoRepositoryPortImpl.java index 9355cf37..60ccfde6 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoRepositoryPortImpl.java +++ b/src/main/java/until/the/eternity/metalwareinfo/infrastructure/persistence/MetalwareInfoRepositoryPortImpl.java @@ -1,10 +1,11 @@ package until.the.eternity.metalwareinfo.infrastructure.persistence; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import until.the.eternity.metalwareinfo.domain.repository.MetalwareInfoRepositoryPort; +import java.util.List; + @Repository @RequiredArgsConstructor public class MetalwareInfoRepositoryPortImpl implements MetalwareInfoRepositoryPort { diff --git a/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/controller/MetalwareInfoController.java b/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/controller/MetalwareInfoController.java index 7047ad96..5917ed61 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/controller/MetalwareInfoController.java +++ b/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/controller/MetalwareInfoController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -15,6 +14,8 @@ import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoSyncResponse; +import java.util.List; + @RestController @RequestMapping("/api/metalware-infos") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/dto/response/MetalwareInfoResponse.java b/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/dto/response/MetalwareInfoResponse.java index a3122710..4e8d9d1e 100644 --- a/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/dto/response/MetalwareInfoResponse.java +++ b/src/main/java/until/the/eternity/metalwareinfo/interfaces/rest/dto/response/MetalwareInfoResponse.java @@ -1,9 +1,10 @@ package until.the.eternity.metalwareinfo.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; + import java.util.List; import java.util.stream.Collectors; -import lombok.Builder; @Builder @Schema(description = "세공 정보 응답 DTO") diff --git a/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java index e8703336..79b0f3ae 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/AllTimeRankingService.java @@ -1,6 +1,5 @@ package until.the.eternity.ranking.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -10,6 +9,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.AllTimeRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java index 1f4c2d80..c223d3eb 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/CategoryRankingService.java @@ -1,6 +1,5 @@ package until.the.eternity.ranking.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -11,6 +10,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java index a3ae944e..442a4858 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/PriceChangeRankingService.java @@ -1,6 +1,5 @@ package until.the.eternity.ranking.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -11,6 +10,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeChangeRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java index 3db9873a..b27ff48f 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/PriceRankingService.java @@ -1,6 +1,5 @@ package until.the.eternity.ranking.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -10,6 +9,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.PriceRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java b/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java index b778e573..7dbab3d4 100644 --- a/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java +++ b/src/main/java/until/the/eternity/ranking/application/service/VolumeRankingService.java @@ -1,6 +1,5 @@ package until.the.eternity.ranking.application.service; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -10,6 +9,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeRankingResponse; import until.the.eternity.ranking.repository.RankingRepository; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/src/main/java/until/the/eternity/ranking/domain/mapper/RankingMapper.java b/src/main/java/until/the/eternity/ranking/domain/mapper/RankingMapper.java index 973c42d8..008f1ea5 100644 --- a/src/main/java/until/the/eternity/ranking/domain/mapper/RankingMapper.java +++ b/src/main/java/until/the/eternity/ranking/domain/mapper/RankingMapper.java @@ -1,5 +1,8 @@ package until.the.eternity.ranking.domain.mapper; +import org.springframework.stereotype.Component; +import until.the.eternity.ranking.interfaces.rest.dto.response.*; + import java.math.BigDecimal; import java.sql.Date; import java.sql.Timestamp; @@ -7,8 +10,6 @@ import java.time.LocalDate; import java.util.List; import java.util.stream.IntStream; -import org.springframework.stereotype.Component; -import until.the.eternity.ranking.interfaces.rest.dto.response.*; @Component public class RankingMapper { diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/AllTimeRankingController.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/AllTimeRankingController.java index 606efa53..57110a5c 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/AllTimeRankingController.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/AllTimeRankingController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.ResponseEntity; @@ -16,6 +15,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.request.RankingSearchRequest; import until.the.eternity.ranking.interfaces.rest.dto.response.AllTimeRankingResponse; +import java.util.List; + @RestController @RequestMapping("/rankings/all-time") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/CategoryRankingController.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/CategoryRankingController.java index c02d8c13..335b73a8 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/CategoryRankingController.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/CategoryRankingController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.ResponseEntity; @@ -17,6 +16,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.PriceRankingResponse; import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeRankingResponse; +import java.util.List; + @RestController @RequestMapping("/rankings/category") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceChangeRankingController.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceChangeRankingController.java index 3140cac0..0cf931ca 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceChangeRankingController.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceChangeRankingController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.ResponseEntity; @@ -17,6 +16,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.response.PriceChangeRankingResponse; import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeChangeRankingResponse; +import java.util.List; + @RestController @RequestMapping("/rankings/price-change") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceRankingController.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceRankingController.java index d27291e2..33b539a1 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceRankingController.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/PriceRankingController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.ResponseEntity; @@ -16,6 +15,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.request.RankingSearchRequest; import until.the.eternity.ranking.interfaces.rest.dto.response.PriceRankingResponse; +import java.util.List; + @RestController @RequestMapping("/rankings/price") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/VolumeRankingController.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/VolumeRankingController.java index 68d84170..77e77c52 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/VolumeRankingController.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/controller/VolumeRankingController.java @@ -3,7 +3,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.ResponseEntity; @@ -16,6 +15,8 @@ import until.the.eternity.ranking.interfaces.rest.dto.request.RankingSearchRequest; import until.the.eternity.ranking.interfaces.rest.dto.response.VolumeRankingResponse; +import java.util.List; + @RestController @RequestMapping("/rankings/volume") @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/AllTimeRankingResponse.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/AllTimeRankingResponse.java index 9d0f2ef4..5da8ec98 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/AllTimeRankingResponse.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/AllTimeRankingResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.time.Instant; @Schema(description = "역대 기록 랭킹 응답") diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceChangeRankingResponse.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceChangeRankingResponse.java index 8ae2aea7..d1749dba 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceChangeRankingResponse.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceChangeRankingResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.ranking.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; @Schema(description = "가격 변동 랭킹 응답") diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceRankingResponse.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceRankingResponse.java index c4789746..adef1c49 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceRankingResponse.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/PriceRankingResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeChangeRankingResponse.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeChangeRankingResponse.java index bfde6388..181014a8 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeChangeRankingResponse.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeChangeRankingResponse.java @@ -1,6 +1,7 @@ package until.the.eternity.ranking.interfaces.rest.dto.response; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; @Schema(description = "거래량 변동 랭킹 응답") diff --git a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeRankingResponse.java b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeRankingResponse.java index 853e3550..df5087bc 100644 --- a/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeRankingResponse.java +++ b/src/main/java/until/the/eternity/ranking/interfaces/rest/dto/response/VolumeRankingResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; diff --git a/src/main/java/until/the/eternity/ranking/repository/RankingRepository.java b/src/main/java/until/the/eternity/ranking/repository/RankingRepository.java index 9c41273c..55a252b4 100644 --- a/src/main/java/until/the/eternity/ranking/repository/RankingRepository.java +++ b/src/main/java/until/the/eternity/ranking/repository/RankingRepository.java @@ -1,11 +1,12 @@ package until.the.eternity.ranking.repository; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import until.the.eternity.statistics.domain.entity.daily.ItemDailyStatistics; +import java.util.List; + public interface RankingRepository extends JpaRepository { // ===== 가격 랭킹 (Price Ranking) ===== diff --git a/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java index 641d9981..0a959bfa 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/ItemDailyStatisticsService.java @@ -1,8 +1,5 @@ package until.the.eternity.statistics.application.service; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -14,6 +11,10 @@ import until.the.eternity.statistics.interfaces.rest.dto.response.ItemDailyStatisticsResponse; import until.the.eternity.statistics.repository.daily.ItemDailyStatisticsRepository; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java index ee53d2a1..a2392f61 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/ItemWeeklyStatisticsService.java @@ -1,8 +1,5 @@ package until.the.eternity.statistics.application.service; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -14,6 +11,10 @@ import until.the.eternity.statistics.interfaces.rest.dto.response.ItemWeeklyStatisticsResponse; import until.the.eternity.statistics.repository.weekly.ItemWeeklyStatisticsRepository; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java index ea3c74ff..05e6dd6e 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryDailyStatisticsService.java @@ -1,8 +1,5 @@ package until.the.eternity.statistics.application.service; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -14,6 +11,10 @@ import until.the.eternity.statistics.interfaces.rest.dto.response.SubcategoryDailyStatisticsResponse; import until.the.eternity.statistics.repository.daily.SubcategoryDailyStatisticsRepository; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java index 7445ba04..a2180889 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/SubcategoryWeeklyStatisticsService.java @@ -1,8 +1,5 @@ package until.the.eternity.statistics.application.service; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -14,6 +11,10 @@ import until.the.eternity.statistics.interfaces.rest.dto.response.SubcategoryWeeklyStatisticsResponse; import until.the.eternity.statistics.repository.weekly.SubcategoryWeeklyStatisticsRepository; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java index a7ca0697..6bf7e92d 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryDailyStatisticsService.java @@ -1,8 +1,5 @@ package until.the.eternity.statistics.application.service; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -14,6 +11,10 @@ import until.the.eternity.statistics.interfaces.rest.dto.response.TopCategoryDailyStatisticsResponse; import until.the.eternity.statistics.repository.daily.TopCategoryDailyStatisticsRepository; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java index 7ecbe622..462c97d5 100644 --- a/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java +++ b/src/main/java/until/the/eternity/statistics/application/service/TopCategoryWeeklyStatisticsService.java @@ -1,8 +1,5 @@ package until.the.eternity.statistics.application.service; -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; @@ -14,6 +11,10 @@ import until.the.eternity.statistics.interfaces.rest.dto.response.TopCategoryWeeklyStatisticsResponse; import until.the.eternity.statistics.repository.weekly.TopCategoryWeeklyStatisticsRepository; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + @Slf4j @Service @RequiredArgsConstructor diff --git a/src/main/java/until/the/eternity/statistics/domain/entity/daily/ItemDailyStatistics.java b/src/main/java/until/the/eternity/statistics/domain/entity/daily/ItemDailyStatistics.java index 361df9c1..f6217f44 100644 --- a/src/main/java/until/the/eternity/statistics/domain/entity/daily/ItemDailyStatistics.java +++ b/src/main/java/until/the/eternity/statistics/domain/entity/daily/ItemDailyStatistics.java @@ -2,10 +2,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import lombok.*; @Entity @Table( diff --git a/src/main/java/until/the/eternity/statistics/domain/entity/daily/SubcategoryDailyStatistics.java b/src/main/java/until/the/eternity/statistics/domain/entity/daily/SubcategoryDailyStatistics.java index 66e5382d..887807d9 100644 --- a/src/main/java/until/the/eternity/statistics/domain/entity/daily/SubcategoryDailyStatistics.java +++ b/src/main/java/until/the/eternity/statistics/domain/entity/daily/SubcategoryDailyStatistics.java @@ -2,10 +2,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import lombok.*; @Entity @Table( diff --git a/src/main/java/until/the/eternity/statistics/domain/entity/daily/TopCategoryDailyStatistics.java b/src/main/java/until/the/eternity/statistics/domain/entity/daily/TopCategoryDailyStatistics.java index fb3ab7a8..bfcb536b 100644 --- a/src/main/java/until/the/eternity/statistics/domain/entity/daily/TopCategoryDailyStatistics.java +++ b/src/main/java/until/the/eternity/statistics/domain/entity/daily/TopCategoryDailyStatistics.java @@ -2,10 +2,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import lombok.*; @Entity @Table( diff --git a/src/main/java/until/the/eternity/statistics/domain/entity/weekly/ItemWeeklyStatistics.java b/src/main/java/until/the/eternity/statistics/domain/entity/weekly/ItemWeeklyStatistics.java index 6970f18e..44c20386 100644 --- a/src/main/java/until/the/eternity/statistics/domain/entity/weekly/ItemWeeklyStatistics.java +++ b/src/main/java/until/the/eternity/statistics/domain/entity/weekly/ItemWeeklyStatistics.java @@ -2,10 +2,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import lombok.*; @Entity @Table( diff --git a/src/main/java/until/the/eternity/statistics/domain/entity/weekly/SubcategoryWeeklyStatistics.java b/src/main/java/until/the/eternity/statistics/domain/entity/weekly/SubcategoryWeeklyStatistics.java index 5756b091..a05c528e 100644 --- a/src/main/java/until/the/eternity/statistics/domain/entity/weekly/SubcategoryWeeklyStatistics.java +++ b/src/main/java/until/the/eternity/statistics/domain/entity/weekly/SubcategoryWeeklyStatistics.java @@ -2,10 +2,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import lombok.*; @Entity @Table( diff --git a/src/main/java/until/the/eternity/statistics/domain/entity/weekly/TopCategoryWeeklyStatistics.java b/src/main/java/until/the/eternity/statistics/domain/entity/weekly/TopCategoryWeeklyStatistics.java index 9201faaf..22e4406d 100644 --- a/src/main/java/until/the/eternity/statistics/domain/entity/weekly/TopCategoryWeeklyStatistics.java +++ b/src/main/java/until/the/eternity/statistics/domain/entity/weekly/TopCategoryWeeklyStatistics.java @@ -2,10 +2,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; -import lombok.*; @Entity @Table( diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/DailyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/DailyStatisticsSearchRequest.java index 7908da49..59954a6b 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/DailyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/DailyStatisticsSearchRequest.java @@ -1,9 +1,10 @@ package until.the.eternity.statistics.interfaces.rest.dto.request; import io.swagger.v3.oas.annotations.media.Schema; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "일간 통계 검색 요청") public record DailyStatisticsSearchRequest( @Schema(description = "아이템 이름 (부분 일치)", example = "켈틱") String itemName, diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemDailyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemDailyStatisticsSearchRequest.java index f6f91521..46b2cf78 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemDailyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemDailyStatisticsSearchRequest.java @@ -2,9 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "아이템별 일간 통계 검색 요청") public record ItemDailyStatisticsSearchRequest( @NotBlank(message = "아이템 이름은 필수입니다") diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemWeeklyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemWeeklyStatisticsSearchRequest.java index 1360de10..d132153d 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemWeeklyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/ItemWeeklyStatisticsSearchRequest.java @@ -2,9 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "아이템별 주간 통계 검색 요청") public record ItemWeeklyStatisticsSearchRequest( @NotBlank(message = "아이템 이름은 필수입니다") diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryDailyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryDailyStatisticsSearchRequest.java index 47c2c966..4ff95e0d 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryDailyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryDailyStatisticsSearchRequest.java @@ -2,9 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "서브카테고리별 일간 통계 검색 요청") public record SubcategoryDailyStatisticsSearchRequest( @NotBlank(message = "탑 카테고리는 필수입니다") diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryWeeklyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryWeeklyStatisticsSearchRequest.java index 9d7bc716..e0247871 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryWeeklyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/SubcategoryWeeklyStatisticsSearchRequest.java @@ -2,9 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "서브카테고리별 주간 통계 검색 요청") public record SubcategoryWeeklyStatisticsSearchRequest( @NotBlank(message = "탑 카테고리는 필수입니다") diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryDailyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryDailyStatisticsSearchRequest.java index 4b8e25d7..382bfefb 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryDailyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryDailyStatisticsSearchRequest.java @@ -2,9 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "탑카테고리별 일간 통계 검색 요청") public record TopCategoryDailyStatisticsSearchRequest( @NotBlank(message = "탑 카테고리는 필수입니다") diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryWeeklyStatisticsSearchRequest.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryWeeklyStatisticsSearchRequest.java index ad1c6b41..2986275f 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryWeeklyStatisticsSearchRequest.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/request/TopCategoryWeeklyStatisticsSearchRequest.java @@ -2,9 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDate; + @Schema(description = "탑카테고리별 주간 통계 검색 요청") public record TopCategoryWeeklyStatisticsSearchRequest( @NotBlank(message = "탑 카테고리는 필수입니다") diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemDailyStatisticsResponse.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemDailyStatisticsResponse.java index a9611010..e2485f4d 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemDailyStatisticsResponse.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemDailyStatisticsResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemWeeklyStatisticsResponse.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemWeeklyStatisticsResponse.java index 05e86f70..7d499d85 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemWeeklyStatisticsResponse.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/ItemWeeklyStatisticsResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryDailyStatisticsResponse.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryDailyStatisticsResponse.java index e27f7f3a..b167b92c 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryDailyStatisticsResponse.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryDailyStatisticsResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryWeeklyStatisticsResponse.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryWeeklyStatisticsResponse.java index bb826866..5f67f69e 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryWeeklyStatisticsResponse.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/SubcategoryWeeklyStatisticsResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryDailyStatisticsResponse.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryDailyStatisticsResponse.java index fd49c2f2..df6c9f8e 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryDailyStatisticsResponse.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryDailyStatisticsResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryWeeklyStatisticsResponse.java b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryWeeklyStatisticsResponse.java index ad81f768..01782f02 100644 --- a/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryWeeklyStatisticsResponse.java +++ b/src/main/java/until/the/eternity/statistics/interfaces/rest/dto/response/TopCategoryWeeklyStatisticsResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; + import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/src/main/java/until/the/eternity/statistics/repository/daily/ItemDailyStatisticsRepository.java b/src/main/java/until/the/eternity/statistics/repository/daily/ItemDailyStatisticsRepository.java index 447c2425..253bcac2 100644 --- a/src/main/java/until/the/eternity/statistics/repository/daily/ItemDailyStatisticsRepository.java +++ b/src/main/java/until/the/eternity/statistics/repository/daily/ItemDailyStatisticsRepository.java @@ -1,7 +1,5 @@ package until.the.eternity.statistics.repository.daily; -import java.time.LocalDate; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -9,6 +7,9 @@ import org.springframework.transaction.annotation.Transactional; import until.the.eternity.statistics.domain.entity.daily.ItemDailyStatistics; +import java.time.LocalDate; +import java.util.List; + public interface ItemDailyStatisticsRepository extends JpaRepository { /** diff --git a/src/main/java/until/the/eternity/statistics/repository/daily/SubcategoryDailyStatisticsRepository.java b/src/main/java/until/the/eternity/statistics/repository/daily/SubcategoryDailyStatisticsRepository.java index 3bed0b1a..e8f72fc4 100644 --- a/src/main/java/until/the/eternity/statistics/repository/daily/SubcategoryDailyStatisticsRepository.java +++ b/src/main/java/until/the/eternity/statistics/repository/daily/SubcategoryDailyStatisticsRepository.java @@ -1,7 +1,5 @@ package until.the.eternity.statistics.repository.daily; -import java.time.LocalDate; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -9,6 +7,9 @@ import org.springframework.transaction.annotation.Transactional; import until.the.eternity.statistics.domain.entity.daily.SubcategoryDailyStatistics; +import java.time.LocalDate; +import java.util.List; + public interface SubcategoryDailyStatisticsRepository extends JpaRepository { diff --git a/src/main/java/until/the/eternity/statistics/repository/daily/TopCategoryDailyStatisticsRepository.java b/src/main/java/until/the/eternity/statistics/repository/daily/TopCategoryDailyStatisticsRepository.java index 31749482..0fff60a8 100644 --- a/src/main/java/until/the/eternity/statistics/repository/daily/TopCategoryDailyStatisticsRepository.java +++ b/src/main/java/until/the/eternity/statistics/repository/daily/TopCategoryDailyStatisticsRepository.java @@ -1,7 +1,5 @@ package until.the.eternity.statistics.repository.daily; -import java.time.LocalDate; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -9,6 +7,9 @@ import org.springframework.transaction.annotation.Transactional; import until.the.eternity.statistics.domain.entity.daily.TopCategoryDailyStatistics; +import java.time.LocalDate; +import java.util.List; + public interface TopCategoryDailyStatisticsRepository extends JpaRepository { diff --git a/src/main/java/until/the/eternity/statistics/repository/weekly/ItemWeeklyStatisticsRepository.java b/src/main/java/until/the/eternity/statistics/repository/weekly/ItemWeeklyStatisticsRepository.java index dc7a301a..24f37b00 100644 --- a/src/main/java/until/the/eternity/statistics/repository/weekly/ItemWeeklyStatisticsRepository.java +++ b/src/main/java/until/the/eternity/statistics/repository/weekly/ItemWeeklyStatisticsRepository.java @@ -1,6 +1,5 @@ package until.the.eternity.statistics.repository.weekly; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -8,6 +7,8 @@ import org.springframework.transaction.annotation.Transactional; import until.the.eternity.statistics.domain.entity.weekly.ItemWeeklyStatistics; +import java.util.List; + public interface ItemWeeklyStatisticsRepository extends JpaRepository { /** diff --git a/src/main/java/until/the/eternity/statistics/repository/weekly/SubcategoryWeeklyStatisticsRepository.java b/src/main/java/until/the/eternity/statistics/repository/weekly/SubcategoryWeeklyStatisticsRepository.java index fb0986af..ea3542c1 100644 --- a/src/main/java/until/the/eternity/statistics/repository/weekly/SubcategoryWeeklyStatisticsRepository.java +++ b/src/main/java/until/the/eternity/statistics/repository/weekly/SubcategoryWeeklyStatisticsRepository.java @@ -1,6 +1,5 @@ package until.the.eternity.statistics.repository.weekly; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -8,6 +7,8 @@ import org.springframework.transaction.annotation.Transactional; import until.the.eternity.statistics.domain.entity.weekly.SubcategoryWeeklyStatistics; +import java.util.List; + public interface SubcategoryWeeklyStatisticsRepository extends JpaRepository { diff --git a/src/main/java/until/the/eternity/statistics/repository/weekly/TopCategoryWeeklyStatisticsRepository.java b/src/main/java/until/the/eternity/statistics/repository/weekly/TopCategoryWeeklyStatisticsRepository.java index 45a1dad4..c2140d57 100644 --- a/src/main/java/until/the/eternity/statistics/repository/weekly/TopCategoryWeeklyStatisticsRepository.java +++ b/src/main/java/until/the/eternity/statistics/repository/weekly/TopCategoryWeeklyStatisticsRepository.java @@ -1,6 +1,5 @@ package until.the.eternity.statistics.repository.weekly; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -8,6 +7,8 @@ import org.springframework.transaction.annotation.Transactional; import until.the.eternity.statistics.domain.entity.weekly.TopCategoryWeeklyStatistics; +import java.util.List; + public interface TopCategoryWeeklyStatisticsRepository extends JpaRepository { diff --git a/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java b/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java index 3d60f033..5aecef17 100644 --- a/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java +++ b/src/test/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryServiceTest.java @@ -1,11 +1,5 @@ package until.the.eternity.auctionhistory.application.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -import java.util.List; -import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,6 +21,13 @@ import until.the.eternity.common.request.PageRequestDto; import until.the.eternity.common.response.PageResponseDto; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class AuctionHistoryServiceTest { diff --git a/src/test/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcherTest.java b/src/test/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcherTest.java index e6e76af4..d1187257 100644 --- a/src/test/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcherTest.java +++ b/src/test/java/until/the/eternity/auctionhistory/application/service/fetcher/AuctionHistoryFetcherTest.java @@ -1,13 +1,5 @@ package until.the.eternity.auctionhistory.application.service.fetcher; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -import java.time.Instant; -import java.util.List; -import java.util.OptionalInt; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -22,6 +14,15 @@ import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; +import java.util.OptionalInt; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class AuctionHistoryFetcherTest { diff --git a/src/test/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersisterTest.java b/src/test/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersisterTest.java index 0d9b8d2d..7764a911 100644 --- a/src/test/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersisterTest.java +++ b/src/test/java/until/the/eternity/auctionhistory/application/service/persister/AuctionHistoryPersisterTest.java @@ -1,11 +1,5 @@ package until.the.eternity.auctionhistory.application.service.persister; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -19,6 +13,13 @@ import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class AuctionHistoryPersisterTest { diff --git a/src/test/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateCheckerTest.java b/src/test/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateCheckerTest.java index e0018834..2591d675 100644 --- a/src/test/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateCheckerTest.java +++ b/src/test/java/until/the/eternity/auctionhistory/domain/service/AuctionHistoryDuplicateCheckerTest.java @@ -1,13 +1,5 @@ package until.the.eternity.auctionhistory.domain.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -import java.time.Instant; -import java.util.List; -import java.util.Optional; -import java.util.OptionalInt; -import java.util.Set; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -20,6 +12,15 @@ import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + @ExtendWith(MockitoExtension.class) class AuctionHistoryDuplicateCheckerTest { diff --git a/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java b/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java index 1ef2f79b..c7e0ede3 100644 --- a/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java +++ b/src/test/java/until/the/eternity/auctionrealtime/application/service/AuctionRealtimeServiceTest.java @@ -1,14 +1,5 @@ package until.the.eternity.auctionrealtime.application.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import java.util.List; -import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,6 +20,13 @@ import until.the.eternity.auctionrealtime.interfaces.rest.dto.response.RealtimeItemOptionResponse; import until.the.eternity.common.response.PageResponseDto; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class AuctionRealtimeServiceTest { diff --git a/src/test/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcherTest.java b/src/test/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcherTest.java index cb22f7b3..e59f27ad 100644 --- a/src/test/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcherTest.java +++ b/src/test/java/until/the/eternity/auctionrealtime/application/service/fetcher/AuctionRealtimeFetcherTest.java @@ -1,12 +1,5 @@ package until.the.eternity.auctionrealtime.application.service.fetcher; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -import java.time.Instant; -import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -21,6 +14,14 @@ import until.the.eternity.auctionrealtime.interfaces.external.dto.OpenApiAuctionRealtimeResponse; import until.the.eternity.common.enums.ItemCategory; +import java.time.Instant; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class AuctionRealtimeFetcherTest { diff --git a/src/test/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionServiceTest.java b/src/test/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionServiceTest.java index d92cf748..cbd42577 100644 --- a/src/test/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionServiceTest.java +++ b/src/test/java/until/the/eternity/auctionsearchoption/application/service/AuctionSearchOptionServiceTest.java @@ -1,11 +1,6 @@ package until.the.eternity.auctionsearchoption.application.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.List; -import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -17,6 +12,12 @@ import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.FieldMetadata; import until.the.eternity.auctionsearchoption.interfaces.rest.dto.response.SearchOptionMetadataResponse; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class AuctionSearchOptionServiceTest { diff --git a/src/test/java/until/the/eternity/common/util/SegongOptionParserTest.java b/src/test/java/until/the/eternity/common/util/SegongOptionParserTest.java index be0a18f5..8f0e956d 100644 --- a/src/test/java/until/the/eternity/common/util/SegongOptionParserTest.java +++ b/src/test/java/until/the/eternity/common/util/SegongOptionParserTest.java @@ -1,13 +1,13 @@ package until.the.eternity.common.util; -import static org.assertj.core.api.Assertions.assertThat; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import static org.assertj.core.api.Assertions.assertThat; + class SegongOptionParserTest { private static final String SEGONG = "세공 옵션"; diff --git a/src/test/java/until/the/eternity/iteminfo/application/service/ItemInfoServiceTest.java b/src/test/java/until/the/eternity/iteminfo/application/service/ItemInfoServiceTest.java index bd64c643..0c472953 100644 --- a/src/test/java/until/the/eternity/iteminfo/application/service/ItemInfoServiceTest.java +++ b/src/test/java/until/the/eternity/iteminfo/application/service/ItemInfoServiceTest.java @@ -1,10 +1,5 @@ package until.the.eternity.iteminfo.application.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -22,6 +17,12 @@ import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSummaryResponse; import until.the.eternity.iteminfo.interfaces.rest.dto.response.ItemInfoSyncResponse; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class ItemInfoServiceTest { diff --git a/src/test/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoServiceTest.java b/src/test/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoServiceTest.java index 4bd777ea..b357e1cf 100644 --- a/src/test/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoServiceTest.java +++ b/src/test/java/until/the/eternity/metalwareinfo/application/service/MetalwareInfoServiceTest.java @@ -1,9 +1,5 @@ package until.the.eternity.metalwareinfo.application.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,6 +10,11 @@ import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse; import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoSyncResponse; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class MetalwareInfoServiceTest { From 4544feb9d01046af5659252d50f001712abd3ae8 Mon Sep 17 00:00:00 2001 From: Lee Sanghyun <59863112+dev-ant@users.noreply.github.com> Date: Thu, 5 Mar 2026 12:52:43 +0900 Subject: [PATCH 16/16] =?UTF-8?q?fix:=20AuctionHistoryCacheWarmupService?= =?UTF-8?q?=20Javadoc=EC=97=90=20Git=20merge=20conflict=20marker=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../application/service/AuctionHistoryCacheWarmupService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java index f2e1ab8f..59dd02d6 100644 --- a/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java +++ b/src/main/java/until/the/eternity/auctionhistory/application/service/AuctionHistoryCacheWarmupService.java @@ -34,8 +34,7 @@ public class AuctionHistoryCacheWarmupService { private final CacheManager cacheManager; /** - * <<<<<<< HEAD 캐시 무효화 후 기본 30가지 조합을 선제적으로 워밍한다. ======= 캐시 무효화 후 기본 12가지 조합(page 1~2 × size 20 - * × sortField 3종 × direction 2종)을 선제적으로 워밍한다. >>>>>>> 40261cb1cdfa017f341bfbde515c64716860b68f + * 캐시 무효화 후 기본 12가지 조합(page 1~2 × size 20 × sortField 3종 × direction 2종)을 선제적으로 워밍한다. * *

빈 검색 조건(필터 없음) 기준으로 워밍하므로, 단순 목록 조회 요청에 즉시 캐시 히트가 발생한다. */