diff --git a/server/build.gradle b/server/build.gradle index b556195..5c69f23 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -78,11 +78,16 @@ dependencies { //local용 db runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + //cache + implementation 'org.springframework.boot:spring-boot-starter-cache' + //redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' - implementation 'org.springframework.boot:spring-boot-starter-cache' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3' + //caffeine + implementation 'com.github.ben-manes.caffeine:caffeine' + //smtp 메일 전송 implementation 'org.springframework.boot:spring-boot-starter-mail' diff --git a/server/src/main/java/com/greenroom/server/api/config/RedisConfig.java b/server/src/main/java/com/greenroom/server/api/config/RedisConfig.java deleted file mode 100644 index 98dfa27..0000000 --- a/server/src/main/java/com/greenroom/server/api/config/RedisConfig.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.greenroom.server.api.config; - -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; -import com.greenroom.server.api.domain.greenroom.entity.Item; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -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.connection.RedisStandaloneConfiguration; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.serializer.*; -import java.time.Duration; -import java.util.List; - -@EnableCaching -@Configuration -public class RedisConfig { - - @Value("${spring.cache.redis.host}") - private String host; - - @Value("${spring.cache.redis.port}") - private String port; - - @Bean - public LettuceConnectionFactory redisConnectionFactory() { - return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, Integer.parseInt(port))); - } - - @Primary - @Bean(value = "basicCacheManager") - public RedisCacheManager cacheManager(RedisConnectionFactory cf) { - - RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() - .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // 키는 String - .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer(Object.class))) - .entryTtl(Duration.ofMinutes(30)); // 캐시 TTL 30분 설정 - - return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(cf) - .cacheDefaults(redisCacheConfiguration) - .build(); - } - - @Bean(value = "itemCacheManager") - public RedisCacheManager itemCacheManager(RedisConnectionFactory cf) { - - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.activateDefaultTyping( - LaissezFaireSubTypeValidator.instance, - ObjectMapper.DefaultTyping.NON_FINAL, - JsonTypeInfo.As.PROPERTY - ); - - // List 타입 생성 - JavaType javaType = objectMapper.getTypeFactory() - .constructCollectionType(List.class, Item.class); - - // Serializer 생성자에 JavaType 사용 - Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer<>(javaType); - - RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() - .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) - .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer)) - .entryTtl(Duration.ofHours(12)); // 캐시 TTL 12시간 설정 - - return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(cf) - .cacheDefaults(redisCacheConfiguration) - .build(); - } - -} \ No newline at end of file diff --git a/server/src/main/java/com/greenroom/server/api/domain/board/entity/Suggestion.java b/server/src/main/java/com/greenroom/server/api/domain/board/entity/Suggestion.java deleted file mode 100644 index 8edd0e5..0000000 --- a/server/src/main/java/com/greenroom/server/api/domain/board/entity/Suggestion.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.greenroom.server.api.domain.board.entity; - -import com.greenroom.server.api.domain.common.entity.BaseTime; -import com.greenroom.server.api.domain.greenroom.entity.Plant; -import com.greenroom.server.api.domain.user.entity.User; -import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Table(name = "suggestion") -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Suggestion extends BaseTime { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long suggestionId; - - private Boolean isRegistered; - - private String content; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - public Suggestion(String content, User user, Plant plant) { - this.isRegistered = Boolean.FALSE; - this.content = content; - this.user = user; - } -} diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryListResponseDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryListResponseDto.java index 5df083a..ca19294 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryListResponseDto.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryListResponseDto.java @@ -2,7 +2,7 @@ import com.greenroom.server.api.domain.greenroom.entity.Diary; -import com.greenroom.server.api.global.config.PropertiesHolder; +import com.greenroom.server.api.global.properties.PropertiesHolder; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryResponseDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryResponseDto.java index eb66f28..2959691 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryResponseDto.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/DiaryResponseDto.java @@ -1,10 +1,9 @@ package com.greenroom.server.api.domain.greenroom.dto.out; import com.greenroom.server.api.domain.greenroom.entity.Diary; -import com.greenroom.server.api.global.config.PropertiesHolder; +import com.greenroom.server.api.global.properties.PropertiesHolder; import lombok.Data; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java index 0db2aed..3ca80e2 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomCalendarResponseDto.java @@ -1,7 +1,7 @@ package com.greenroom.server.api.domain.greenroom.dto.out; import com.greenroom.server.api.domain.greenroom.entity.*; -import com.greenroom.server.api.global.config.PropertiesHolder; +import com.greenroom.server.api.global.properties.PropertiesHolder; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomDetailResponseDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomDetailResponseDto.java index 93615c3..05cd2df 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomDetailResponseDto.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomDetailResponseDto.java @@ -2,7 +2,7 @@ import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; import com.greenroom.server.api.domain.greenroom.entity.Todo; -import com.greenroom.server.api.global.config.PropertiesHolder; +import com.greenroom.server.api.global.properties.PropertiesHolder; import java.time.LocalDate; import java.util.List; diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomInfoResponseDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomInfoResponseDto.java index fc185d4..66a1630 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomInfoResponseDto.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/GreenroomInfoResponseDto.java @@ -2,12 +2,8 @@ import com.greenroom.server.api.domain.greenroom.entity.Activity; import com.greenroom.server.api.domain.greenroom.entity.GreenRoom; -import com.greenroom.server.api.domain.greenroom.entity.Item; -import com.greenroom.server.api.global.config.PropertiesHolder; -import lombok.AllArgsConstructor; -import lombok.Data; +import com.greenroom.server.api.global.properties.PropertiesHolder; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import java.util.List; import java.util.Map; diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/PlantInfoDto.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/PlantInfoDto.java index 56cffb5..7bbc97c 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/PlantInfoDto.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/dto/out/PlantInfoDto.java @@ -1,8 +1,7 @@ package com.greenroom.server.api.domain.greenroom.dto.out; import com.greenroom.server.api.domain.greenroom.entity.Plant; -import com.greenroom.server.api.global.config.PropertiesHolder; -import org.springframework.beans.factory.annotation.Value; +import com.greenroom.server.api.global.properties.PropertiesHolder; public record PlantInfoDto (Long plantId, String name, String scientificName, String description, String imageUrl){ diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/ItemCachedService.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/ItemCachedService.java index 8710697..6609a78 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/ItemCachedService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/ItemCachedService.java @@ -20,7 +20,7 @@ public class ItemCachedService { //repository private final ItemRepository itemRepository; - @Cacheable(cacheNames = {"items"},key = "#category+'_'+#subCategory",cacheManager = "itemCacheManager") + @Cacheable(cacheNames = {"items"},key = "#category+'_'+#subCategory") public List getItems(Integer category, Integer subCategory){ return(itemRepository.findAll() .stream() diff --git a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/PlantService.java b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/PlantService.java index 6fc0d99..604c44c 100644 --- a/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/PlantService.java +++ b/server/src/main/java/com/greenroom/server/api/domain/greenroom/service/PlantService.java @@ -103,7 +103,7 @@ public List getPlantListWithKeyword(String keyWord, Integer si throw new CustomException(ResponseCodeEnum.FAIL_TO_SEARCH_WITH_ELASTICSEARCH,e.getMessage()); } } - @Cacheable(cacheNames = {"plants"},key = "#size",cacheManager = "basicCacheManager") + @Cacheable(cacheNames = {"plants"},key = "#size") public List getPopularPlantList(Integer size){ return plantRepository.findAll() diff --git a/server/src/main/java/com/greenroom/server/api/config/AwsS3Config.java b/server/src/main/java/com/greenroom/server/api/global/config/AwsS3Config.java similarity index 95% rename from server/src/main/java/com/greenroom/server/api/config/AwsS3Config.java rename to server/src/main/java/com/greenroom/server/api/global/config/AwsS3Config.java index e4fc62d..21215fe 100644 --- a/server/src/main/java/com/greenroom/server/api/config/AwsS3Config.java +++ b/server/src/main/java/com/greenroom/server/api/global/config/AwsS3Config.java @@ -1,4 +1,4 @@ -package com.greenroom.server.api.config; +package com.greenroom.server.api.global.config; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; diff --git a/server/src/main/java/com/greenroom/server/api/global/config/CaffeineCacheConfig.java b/server/src/main/java/com/greenroom/server/api/global/config/CaffeineCacheConfig.java new file mode 100644 index 0000000..ec0338c --- /dev/null +++ b/server/src/main/java/com/greenroom/server/api/global/config/CaffeineCacheConfig.java @@ -0,0 +1,32 @@ +package com.greenroom.server.api.global.config; + + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.greenroom.server.api.global.enums.CacheType; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Configuration +@EnableCaching +public class CaffeineCacheConfig { + @Bean + public CacheManager cacheManager() { + SimpleCacheManager cacheManager = new SimpleCacheManager(); + List caches = Arrays.stream(CacheType.values()) + .map(cache -> new CaffeineCache(cache.getCacheName(), Caffeine.newBuilder().recordStats() + .expireAfterWrite(cache.getExpiredAfterWrite(), TimeUnit.SECONDS) + .maximumSize(cache.getMaximumSize()) + .build())) + .toList(); + cacheManager.setCaches(caches); + return cacheManager; + } +} diff --git a/server/src/main/java/com/greenroom/server/api/config/ElasticsearchConfig.java b/server/src/main/java/com/greenroom/server/api/global/config/ElasticsearchConfig.java similarity index 100% rename from server/src/main/java/com/greenroom/server/api/config/ElasticsearchConfig.java rename to server/src/main/java/com/greenroom/server/api/global/config/ElasticsearchConfig.java diff --git a/server/src/main/java/com/greenroom/server/api/config/JasyptConfig.java b/server/src/main/java/com/greenroom/server/api/global/config/JasyptConfig.java similarity index 96% rename from server/src/main/java/com/greenroom/server/api/config/JasyptConfig.java rename to server/src/main/java/com/greenroom/server/api/global/config/JasyptConfig.java index 59dd69f..31e73e8 100644 --- a/server/src/main/java/com/greenroom/server/api/config/JasyptConfig.java +++ b/server/src/main/java/com/greenroom/server/api/global/config/JasyptConfig.java @@ -1,4 +1,4 @@ -package com.greenroom.server.api.config; +package com.greenroom.server.api.global.config; import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; import lombok.extern.slf4j.Slf4j; diff --git a/server/src/main/java/com/greenroom/server/api/global/config/RedisConfig.java b/server/src/main/java/com/greenroom/server/api/global/config/RedisConfig.java new file mode 100644 index 0000000..d7e4139 --- /dev/null +++ b/server/src/main/java/com/greenroom/server/api/global/config/RedisConfig.java @@ -0,0 +1,78 @@ +//package com.greenroom.server.api.config; +// +//import com.fasterxml.jackson.annotation.JsonTypeInfo; +//import com.fasterxml.jackson.databind.JavaType; +//import com.fasterxml.jackson.databind.ObjectMapper; +//import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +//import com.greenroom.server.api.domain.greenroom.entity.Item; +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.cache.annotation.EnableCaching; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.context.annotation.Primary; +//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.connection.RedisStandaloneConfiguration; +//import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +//import org.springframework.data.redis.serializer.*; +//import java.time.Duration; +//import java.util.List; +// +//@EnableCaching +//@Configuration +//public class RedisConfig { +// +// @Value("${spring.cache.redis.host}") +// private String host; +// +// @Value("${spring.cache.redis.port}") +// private String port; +// +// @Bean +// public LettuceConnectionFactory redisConnectionFactory() { +// return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, Integer.parseInt(port))); +// } +// +// @Primary +// @Bean(value = "basicCacheManager") +// public RedisCacheManager cacheManager(RedisConnectionFactory cf) { +// +// RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() +// .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // 키는 String +// .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer(Object.class))) +// .entryTtl(Duration.ofMinutes(30)); // 캐시 TTL 30분 설정 +// +// return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(cf) +// .cacheDefaults(redisCacheConfiguration) +// .build(); +// } +// +// @Bean(value = "itemCacheManager") +// public RedisCacheManager itemCacheManager(RedisConnectionFactory cf) { +// +// ObjectMapper objectMapper = new ObjectMapper(); +// objectMapper.activateDefaultTyping( +// LaissezFaireSubTypeValidator.instance, +// ObjectMapper.DefaultTyping.NON_FINAL, +// JsonTypeInfo.As.PROPERTY +// ); +// +// // List 타입 생성 +// JavaType javaType = objectMapper.getTypeFactory() +// .constructCollectionType(List.class, Item.class); +// +// // Serializer 생성자에 JavaType 사용 +// Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer<>(javaType); +// +// RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() +// .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) +// .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer)) +// .entryTtl(Duration.ofHours(12)); // 캐시 TTL 12시간 설정 +// +// return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(cf) +// .cacheDefaults(redisCacheConfiguration) +// .build(); +// } +// +//} \ No newline at end of file diff --git a/server/src/main/java/com/greenroom/server/api/config/SMTPConfig.java b/server/src/main/java/com/greenroom/server/api/global/config/SMTPConfig.java similarity index 96% rename from server/src/main/java/com/greenroom/server/api/config/SMTPConfig.java rename to server/src/main/java/com/greenroom/server/api/global/config/SMTPConfig.java index d036762..68fee27 100644 --- a/server/src/main/java/com/greenroom/server/api/config/SMTPConfig.java +++ b/server/src/main/java/com/greenroom/server/api/global/config/SMTPConfig.java @@ -1,4 +1,4 @@ -package com.greenroom.server.api.config; +package com.greenroom.server.api.global.config; import org.springframework.boot.autoconfigure.mail.MailProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/server/src/main/java/com/greenroom/server/api/global/enums/CacheType.java b/server/src/main/java/com/greenroom/server/api/global/enums/CacheType.java new file mode 100644 index 0000000..45b3ff5 --- /dev/null +++ b/server/src/main/java/com/greenroom/server/api/global/enums/CacheType.java @@ -0,0 +1,19 @@ +package com.greenroom.server.api.global.enums; + +import lombok.Getter; + +@Getter +public enum CacheType { + ITEM("items",12*60*60,50), + PLANT("plants",60*60,10); + + private final String cacheName; + private final Integer expiredAfterWrite; // seconds + private final Integer maximumSize; + + CacheType(String cacheName, Integer expiredAfterWrite, Integer maximumSize){ + this.cacheName = cacheName; + this.expiredAfterWrite = expiredAfterWrite; + this.maximumSize = maximumSize; + } +} diff --git a/server/src/main/java/com/greenroom/server/api/global/config/PropertiesHolder.java b/server/src/main/java/com/greenroom/server/api/global/properties/PropertiesHolder.java similarity index 88% rename from server/src/main/java/com/greenroom/server/api/global/config/PropertiesHolder.java rename to server/src/main/java/com/greenroom/server/api/global/properties/PropertiesHolder.java index 21bb060..6deff12 100644 --- a/server/src/main/java/com/greenroom/server/api/global/config/PropertiesHolder.java +++ b/server/src/main/java/com/greenroom/server/api/global/properties/PropertiesHolder.java @@ -1,4 +1,4 @@ -package com.greenroom.server.api.global.config; +package com.greenroom.server.api.global.properties; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value;