diff --git a/pom.xml b/pom.xml
index 81eaed6e..b1b4fef9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -134,6 +134,11 @@
jjwt-jackson
0.11.5
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
diff --git a/src/main/java/com/t3t/frontserver/FrontServerApplication.java b/src/main/java/com/t3t/frontserver/FrontServerApplication.java
index c5c725c5..41eaa7b8 100644
--- a/src/main/java/com/t3t/frontserver/FrontServerApplication.java
+++ b/src/main/java/com/t3t/frontserver/FrontServerApplication.java
@@ -3,7 +3,9 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.cache.annotation.EnableCaching;
+@EnableCaching
@ConfigurationPropertiesScan
@SpringBootApplication
public class FrontServerApplication {
diff --git a/src/main/java/com/t3t/frontserver/book/controller/BookCategoryController.java b/src/main/java/com/t3t/frontserver/book/controller/BookCategoryController.java
index 2583bc0d..9b9da814 100644
--- a/src/main/java/com/t3t/frontserver/book/controller/BookCategoryController.java
+++ b/src/main/java/com/t3t/frontserver/book/controller/BookCategoryController.java
@@ -5,6 +5,7 @@
import com.t3t.frontserver.book.model.response.BookDetailResponse;
import com.t3t.frontserver.category.client.CategoryApiClient;
import com.t3t.frontserver.category.response.CategoryTreeResponse;
+import com.t3t.frontserver.category.service.CategoryService;
import com.t3t.frontserver.model.response.BaseResponse;
import com.t3t.frontserver.model.response.PageResponse;
import lombok.RequiredArgsConstructor;
@@ -23,13 +24,13 @@
@Controller
public class BookCategoryController {
private final BookCategoryApiClient bookCategoryApiClient;
- private final CategoryApiClient categoryAdaptor;
+ private final CategoryService categoryService;
@GetMapping("/category/{categoryId}/books")
public String getBooksByCategoryId(Model model, @PathVariable Integer categoryId,
@RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo) {
- List categoryList = getDataFromCategoryAdaptor(1, 2);
+ List categoryList = categoryService.getCategoryTreeByDepth(1, 2);
PageResponse bookList = getDataFromBookCategoryAdaptor(categoryId, pageNo);
if (bookList != null) {
@@ -49,11 +50,6 @@ public String getBooksByCategoryId(Model model, @PathVariable Integer categoryId
return "main/page/search";
}
- private List getDataFromCategoryAdaptor(Integer startDepth, Integer maxDepth ) {
- ResponseEntity>> categoriesResponse = categoryAdaptor.getCategoryTreeByDepth(startDepth, maxDepth);
- return handleResponse(categoriesResponse);
- }
-
private PageResponse getDataFromBookCategoryAdaptor(Integer categoryId, int pageNo) {
ResponseEntity>> booksResponse = bookCategoryApiClient.getBooksByCategoryId(categoryId, pageNo);
return handleResponse(booksResponse);
diff --git a/src/main/java/com/t3t/frontserver/book/controller/BookController.java b/src/main/java/com/t3t/frontserver/book/controller/BookController.java
index 39a02dd7..a2994ec8 100644
--- a/src/main/java/com/t3t/frontserver/book/controller/BookController.java
+++ b/src/main/java/com/t3t/frontserver/book/controller/BookController.java
@@ -4,6 +4,7 @@
import com.t3t.frontserver.book.model.response.BookDetailResponse;
import com.t3t.frontserver.category.client.CategoryApiClient;
import com.t3t.frontserver.category.response.CategoryTreeResponse;
+import com.t3t.frontserver.category.service.CategoryService;
import com.t3t.frontserver.index.OrderFormRequest;
import com.t3t.frontserver.model.response.BaseResponse;
import com.t3t.frontserver.model.response.PageResponse;
@@ -24,15 +25,15 @@
@Controller
@RequiredArgsConstructor
public class BookController {
- private final CategoryApiClient categoryAdaptor;
private final BookApiClient bookApiClient;
private final ReviewApiClient reviewApiClient;
+ private final CategoryService categoryService;
@GetMapping("books/{bookId}")
public String getBook(Model model, @PathVariable Long bookId,
@RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo) {
- List categoryList = getDataFromCategoryAdaptor(1, 2);
+ List categoryList = categoryService.getCategoryTreeByDepth(1, 2);
BookDetailResponse bookDetailList = getDataFromBookAdaptor(bookId);
PageResponse reviewList = getDataFromReviewAdaptor(bookId, pageNo);
@@ -58,11 +59,6 @@ public String getBook(Model model, @PathVariable Long bookId,
return "main/page/detail";
}
- private List getDataFromCategoryAdaptor(Integer startDepth, Integer maxDepth ) {
- ResponseEntity>> categoriesResponse = categoryAdaptor.getCategoryTreeByDepth(startDepth, maxDepth);
- return handleResponse(categoriesResponse);
- }
-
private BookDetailResponse getDataFromBookAdaptor(Long bookId) {
ResponseEntity> bookDetailResponse = bookApiClient.getBook(bookId);
return handleResponse(bookDetailResponse);
diff --git a/src/main/java/com/t3t/frontserver/category/response/CategoryTreeResponse.java b/src/main/java/com/t3t/frontserver/category/response/CategoryTreeResponse.java
index 645b169e..098b4508 100644
--- a/src/main/java/com/t3t/frontserver/category/response/CategoryTreeResponse.java
+++ b/src/main/java/com/t3t/frontserver/category/response/CategoryTreeResponse.java
@@ -1,7 +1,6 @@
package com.t3t.frontserver.category.response;
-import lombok.Builder;
-import lombok.Data;
+import lombok.*;
import java.util.List;
@@ -12,6 +11,8 @@
*/
@Data
@Builder
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class CategoryTreeResponse {
private Integer categoryId;
diff --git a/src/main/java/com/t3t/frontserver/category/service/CategoryService.java b/src/main/java/com/t3t/frontserver/category/service/CategoryService.java
index f39e1c26..84512161 100644
--- a/src/main/java/com/t3t/frontserver/category/service/CategoryService.java
+++ b/src/main/java/com/t3t/frontserver/category/service/CategoryService.java
@@ -3,15 +3,26 @@
import com.t3t.frontserver.category.adaptor.CategoryAdaptor;
import com.t3t.frontserver.category.response.CategoryTreeResponse;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
-@Service
+@CacheConfig(cacheNames = "categories")
@RequiredArgsConstructor
+@Service
public class CategoryService {
private final CategoryAdaptor categoryAdaptor;
+ /**
+ * 카테고리 트리를 조회한다.
+ * 요청하는 startDepth 와 maxDepth 에 대해서 캐싱이 적용되어 조회된다.
+ *
+ * @author woody33545(구건모)
+ */
+ @Cacheable(key = "'startDepth:' + #startDepth + 'maxDepth:' + #maxDepth", unless = "#result == null")
public List getCategoryTreeByDepth(Integer startDepth, Integer maxDepth) {
return categoryAdaptor.getCategoryTreeByDepth(startDepth, maxDepth);
}
diff --git a/src/main/java/com/t3t/frontserver/config/CacheConfig.java b/src/main/java/com/t3t/frontserver/config/CacheConfig.java
new file mode 100644
index 00000000..187ad694
--- /dev/null
+++ b/src/main/java/com/t3t/frontserver/config/CacheConfig.java
@@ -0,0 +1,37 @@
+package com.t3t.frontserver.config;
+
+import org.springframework.cache.CacheManager;
+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;
+
+import java.time.Duration;
+
+@Configuration
+public class CacheConfig {
+
+ /**
+ * Cache Manager 빈 등록
+ * Global Cache 로 Redis 를 사용하므로 RedisCacheManager 로 설정한다.
+ * @author woody35545(구건모)
+ */
+ @Bean
+ public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
+ RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
+ .defaultCacheConfig()
+ .disableCachingNullValues()
+ .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
+ .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
+ .entryTtl(Duration.ofMinutes(60L));
+
+ return RedisCacheManager.RedisCacheManagerBuilder
+ .fromConnectionFactory(redisConnectionFactory)
+ .cacheDefaults(redisCacheConfiguration)
+ .build();
+ }
+}
diff --git a/src/main/java/com/t3t/frontserver/main/controller/MainController.java b/src/main/java/com/t3t/frontserver/main/controller/MainController.java
index 5422a24a..de68d4e5 100644
--- a/src/main/java/com/t3t/frontserver/main/controller/MainController.java
+++ b/src/main/java/com/t3t/frontserver/main/controller/MainController.java
@@ -2,6 +2,7 @@
import com.t3t.frontserver.category.client.CategoryApiClient;
import com.t3t.frontserver.category.response.CategoryTreeResponse;
+import com.t3t.frontserver.category.service.CategoryService;
import com.t3t.frontserver.main.response.BookInfoBrief;
import com.t3t.frontserver.model.response.BaseResponse;
import com.t3t.frontserver.recommendation.client.RecommendationApiClient;
@@ -21,7 +22,7 @@
@RequiredArgsConstructor
public class MainController {
private final RecommendationApiClient recommendationAdaptor;
- private final CategoryApiClient categoryAdaptor;
+ private final CategoryService categoryService;
@GetMapping("/")
public String homeView(Model model) {
@@ -32,7 +33,7 @@ public String homeView(Model model) {
LocalDate currentDate = LocalDate.now();
//String formattedDate = currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String formattedDate = "2024-04-06"; // 테스트를 위해 값을 고정, 실제 배포시에는 삭제 예정
- List categoryList = getDataFromCategoryAdaptor(1, 2);
+ List categoryList = categoryService.getCategoryTreeByDepth(1, 2);
List recentlyPublishedBookList = getDataFromRecommendationAdaptor(() -> recommendationAdaptor.getRecentlyPublishedBooks(formattedDate, defaultMaxCount));
List mostLikeBookList = getDataFromRecommendationAdaptor(() -> recommendationAdaptor.getBooksByMostLikedAndHighAverageScore(defaultMaxCount));
List bestSellerBookList = getDataFromRecommendationAdaptor(() -> recommendationAdaptor.getBestSellerBooks(defaultMaxCount));
@@ -46,11 +47,6 @@ public String homeView(Model model) {
return "main/page/home";
}
- private List getDataFromCategoryAdaptor(Integer startDepth, Integer maxDepth ) {
- ResponseEntity>> categoriesResponse = categoryAdaptor.getCategoryTreeByDepth(startDepth, maxDepth);
- return handleResponse(categoriesResponse);
- }
-
private List getDataFromRecommendationAdaptor(Supplier>>> requestSupplier) {
ResponseEntity>> responseEntity = requestSupplier.get();
return handleResponse(responseEntity);