-
Notifications
You must be signed in to change notification settings - Fork 1
캐싱 적용 및 중복 로직 제거 #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
캐싱 적용 및 중복 로직 제거 #35
Conversation
dependency submission code removed
merging main retry
WalkthroughThis change set refactors and enhances the caching strategy across several service classes in the application. It updates the TTLs for multiple Redis caches, introduces new cache entries, and enables or modifies Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant DietControllerV2
participant CacheServiceV2
participant Redis
participant Database
Client->>DietControllerV2: handleRequest(params)
DietControllerV2->>CacheServiceV2: getDietList(params, cafeteriaId)
CacheServiceV2->>Redis: GET dietList cache by key
alt Cache hit
Redis-->>CacheServiceV2: Return cached diet list
CacheServiceV2-->>DietControllerV2: Return diet list
else Cache miss
CacheServiceV2->>Database: Query diet list
Database-->>CacheServiceV2: Return diet list
CacheServiceV2->>Redis: SET diet list with TTL (until next midnight)
CacheServiceV2-->>DietControllerV2: Return diet list
end
DietControllerV2-->>Client: Return response
Possibly related PRs
Poem
Tip ⚡💬 Agentic Chat (Pro Plan, General Availability)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (6)
src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java (1)
18-18: Leverage or remove the injectedlog
You’ve added@Slf4jto enable logging, but there are currently nologstatements in this class. Consider adding log entries (e.g., entering/exiting methods, key parameter values, or error conditions) to improve traceability, or remove the annotation if logging isn’t needed here.src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java (1)
16-16: Enable SLF4J logging
Annotating the class with@Slf4jis appropriate. To fully leverage this change, consider insertinglog.debug()orlog.info()statements in key methods (e.g., upon entry torequestHandler, cache misses/hits, error branches) for better observability.src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java (1)
15-15: Enable structured logging with@Slf4j.
The@Slf4jannotation correctly injects aloginstance for this service. Consider adding meaningful log statements (e.g., cache‐hit vs. cache‐miss events, entry/exit of critical methods) to leverage this enhancement and improve observability.src/main/java/com/example/Jinus/config/RedisCacheManager.java (1)
49-50: Fix duplicate comment numberingThere are two sections labeled as "3." - one for campusName and another for cafeteriaId. Please correct the numbering in the comments.
- // 3. 식당 id 캐시 (불변 데이터, 30일 유지) + // 4. 식당 id 캐시 (불변 데이터, 30일 유지) - // 4. 캠퍼스 id 캐시 (불변 데이터, 30일 유지) + // 5. 캠퍼스 id 캐시 (불변 데이터, 30일 유지) - // 5. 식당 url 캐시 (불변 데이터, 30일 유지) + // 6. 식당 url 캐시 (불변 데이터, 30일 유지)Also applies to: 57-58
src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java (2)
31-33: Add explicit type safety to the Redis read to preventClassCastException
(List<DietDto>) redisTemplate.opsForValue().get(key)relies on unchecked casting.
Configure the template with aJackson2JsonRedisSerializer<List<DietDto>>(or your preferred serializer) and parameterise it:private final RedisTemplate<String, List<DietDto>> redisTemplate; ... List<DietDto> cached = redisTemplate.opsForValue().get(key);This eliminates raw‑type warnings and guards against accidental type mismatches if another component writes to the same key.
21-22:@Slf4jadded but never usedSince logging was introduced, consider logging cache hits/misses inside
getDietListandgetCafeteriaListto aid future debugging and performance analysis.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/main/java/com/example/Jinus/config/RedisCacheManager.java(2 hunks)src/main/java/com/example/Jinus/config/RestTemplateConfig.java(0 hunks)src/main/java/com/example/Jinus/controller/v2/DietControllerV2.java(0 hunks)src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java(1 hunks)src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java(1 hunks)src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java(2 hunks)src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java(2 hunks)src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java(2 hunks)src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java(1 hunks)src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java(2 hunks)
💤 Files with no reviewable changes (2)
- src/main/java/com/example/Jinus/config/RestTemplateConfig.java
- src/main/java/com/example/Jinus/controller/v2/DietControllerV2.java
🔇 Additional comments (16)
src/main/java/com/example/Jinus/service/v2/cafeteria/DietParameterServiceV2.java (1)
8-8: Lombok SLF4J import added correctly
The import forlombok.extern.slf4j.Slf4jis in place. Ensure that Lombok annotation processing is enabled in your build (e.g.,maven-compiler-pluginor IDE configuration) so thelogfield is generated without issues.src/main/java/com/example/Jinus/service/v2/cafeteria/DietServiceV2.java (1)
7-7: Approved: Import for logging support
The addition oflombok.extern.slf4j.Slf4jis correct and prepares the class for structured logging.src/main/java/com/example/Jinus/service/v2/userInfo/UserServiceV2.java (1)
5-5: Approve addition of SLF4J import.
Importinglombok.extern.slf4j.Slf4jis necessary to activate the@Slf4jannotation and aligns with other service classes.src/main/java/com/example/Jinus/config/RedisCacheManager.java (4)
24-30: Good update to cafeteria list cache TTLExtending the TTL to 30 days for immutable cafeteria list data is appropriate and helps reduce unnecessary database queries.
41-48: Consistent caching strategy for immutable dataGood approach applying 30-day TTL consistently across all immutable data caches (campusName, cafeteriaId, campusId).
Also applies to: 49-63
65-71: Good addition of cafeteriaUrl cacheAdding the cafeteriaUrl cache with a 30-day TTL for immutable data is consistent with the overall caching strategy.
34-39:Details
✅ Verification successful
Confirm if dietList cache removal is intentional
The dietList cache configuration is now commented out. This suggests that the caching strategy for diet data has changed, likely to a manual implementation using RedisTemplate with dynamic TTL as mentioned in the summary.
Please verify that the corresponding diet data caching is now being handled manually elsewhere in the code (likely in CacheServiceV2 with RedisTemplate).
🏁 Script executed:
#!/bin/bash # Check for RedisTemplate usage in CacheServiceV2 rg -A 10 "RedisTemplate|getDietList" src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.javaLength of output: 1063
dietList cache is now managed manually in CacheServiceV2
The commented‑out
dietListentry inRedisCacheManageris intentional. Caching is now handled in CacheServiceV2’s getDietList method using RedisTemplate with a dynamic TTL:• File: src/main/java/com/example/Jinus/service/v2/cafeteria/CacheServiceV2.java
– Method:getDietList(HandleRequestDto, int)
– UsesredisConfig.redisTemplate().opsForValue().get(key)and.set(key, result, Duration.ofSeconds(ttlSeconds))wherettlSecondsis calculated until next midnight.src/main/java/com/example/Jinus/service/v2/cafeteria/CafeteriaQueryServiceV2.java (3)
5-11: Good addition of logging supportAdding the @slf4j annotation enables proper logging capabilities in this service class.
15-22: Good implementation of caching for cafeteriaId lookupsThe @Cacheable annotation is properly configured with:
- Appropriate cache name
- Well-formatted composite key using both parameters
- Condition to prevent caching of "not found" results (-1)
- Explicit cache manager reference
This will effectively reduce database queries for these lookups.
24-30: Good implementation of caching for cafeteria image URLsAdding caching for the getImgUrl method is beneficial as image URLs are unlikely to change frequently. The cache configuration is properly set up with the appropriate cache name, key, and cache manager.
src/main/java/com/example/Jinus/service/v2/cafeteria/CampusServiceV2.java (3)
6-14: Good addition of logging and cache importsAdding the @slf4j annotation and importing the necessary caching annotations is appropriate for the changes in this class.
18-25: Good implementation of caching for campus name lookupsThe @Cacheable annotation on getUserCampusName is properly configured with:
- Appropriate cache name
- Simple key using the campusId parameter
- Explicit cache manager reference
This will effectively reduce database queries for campus name lookups.
32-39: Good implementation of caching for campus ID lookupsThe @Cacheable annotation on getCampusId is properly configured with:
- Appropriate cache name
- Simple key using the campusName parameter
- Explicit cache manager reference
This will effectively reduce database queries for campus ID lookups.
src/main/java/com/example/Jinus/service/v2/cafeteria/DietQueryServiceV2.java (3)
7-19: Good addition of logging supportAdding the @slf4j annotation enables proper logging capabilities in this service class.
26-36: Excellent optimization to eliminate redundant data fetchingThe refactored code now retrieves the diet list only once from cacheServiceV2 and checks if it's empty, rather than querying twice (once to check existence, once to retrieve data). This is a significant improvement that reduces duplicate queries.
40-51: Good refactoring of getDiets methodChanging the getDiets method to accept a pre-fetched list of DietDto objects instead of fetching them internally eliminates redundant data retrieval and makes the method more reusable. This change works well with the optimized getDietResponse method.
| List<DietDto> cached = (List<DietDto>) redisConfig.redisTemplate().opsForValue().get(key); | ||
| if (cached != null) return cached; | ||
|
|
||
| List<DietDto> result = dietRepositoryV2.findDietList(parameters.getDietDate(), parameters.getPeriod(), cafeteriaId); | ||
|
|
||
| if (result != null && !result.isEmpty()) { | ||
| long ttlSeconds = calculateTtlUntilNextMidnight(parameters.getDietDate()); | ||
| redisConfig.redisTemplate().opsForValue().set(key, result, Duration.ofSeconds(ttlSeconds)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skip the SET operation when TTL ≤ 0 to avoid creating instantly‑expired keys
If calculateTtlUntilNextMidnight returns 0, the current code still executes
redisTemplate.opsForValue().set(key, result, Duration.ofSeconds(0));With Redis this translates to a SETEX key 0, which immediately expires the key and produces unnecessary network traffic.
Guard the call with a positive‑TTL check instead:
long ttlSeconds = calculateTtlUntilNextMidnight(parameters.getDietDate());
-if (ttlSeconds > 0) {
- redisTemplate.opsForValue().set(key, result, Duration.ofSeconds(ttlSeconds));
-}
+if (ttlSeconds > 0) {
+ redisTemplate.opsForValue().set(key, result, Duration.ofSeconds(ttlSeconds));
+} else {
+ log.debug("Diet cache not written because TTL is non‑positive for key={}", key);
+}| private final RedisConfig redisConfig; | ||
|
|
||
| // @Cacheable( | ||
| // value = "dietList", | ||
| // key = "#parameters?.dietDate?.toString() + '::' + #parameters?.period + '::' + #cafeteriaId", | ||
| // unless = "#result == null || #result.isEmpty()", | ||
| // cacheManager = "contentCacheManager" | ||
| // ) | ||
| // 식단 데이터 가져오기 | ||
| public List<DietDto> getDietList(HandleRequestDto parameters, int cafeteriaId) { | ||
| // 오늘, 내일 문자열로 날짜 설정하기 | ||
| Date dietDate = parameters.getDietDate(); | ||
| // 식단 데이터 반환 | ||
| return dietRepositoryV2.findDietList(dietDate, parameters.getPeriod(), cafeteriaId); | ||
| String key = parameters.getDietDate() + "::" + parameters.getPeriod() + "::" + cafeteriaId; | ||
|
|
||
| List<DietDto> cached = (List<DietDto>) redisConfig.redisTemplate().opsForValue().get(key); | ||
| if (cached != null) return cached; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Prefer constructor‑injected RedisTemplate over calling the RedisConfig factory on every invocation
redisConfig.redisTemplate() is executed on every call to getDietList.
Even though the factory method is likely annotated with @Bean, Spring still has to look the bean up each time, and the indirection hides the real dependency of this service (the template, not the config).
Injecting the template directly makes dependencies explicit, avoids the per‑call lookup, and removes the need to expose the redisTemplate() factory method altogether.
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.core.RedisTemplate;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
...
- private final RedisConfig redisConfig;
+ private final RedisTemplate<String, Object> redisTemplate;Update the two call‑sites (get / set) to use redisTemplate instead of redisConfig.redisTemplate().
This keeps the service focused and eases unit testing (you can now pass a mocked template).
Committable suggestion skipped: line range outside the PR's diff.
Suspect IssuesThis pull request was deployed and Sentry observed the following issues:
Did you find this useful? React with a 👍 or 👎 |
[식단 조회 캐싱 적용]
쿼리문 중복 요청 원인 찾아 제거함
Summary by CodeRabbit