diff --git a/build.gradle b/build.gradle index 1d3e9ce0..2b409379 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,9 @@ dependencies { // actuator implementation 'org.springframework.boot:spring-boot-starter-actuator' + // Redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + // SpringDoc OpenAPI (Swagger) implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0' diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java index 016545fb..c053ffb0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java @@ -17,6 +17,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class TestDto { + private Long id; private Geometry polygon; private Double centroidX; @@ -29,6 +30,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class CountDto { + private String classCd; // 영문코드 private String className; // 한글명 private Long count; // 건수 @@ -40,6 +42,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class CogUrlReq { + private Integer beforeYear; private Integer afterYear; private String mapSheetNum; @@ -51,6 +54,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class CogUrlDto { + private String beforeCogUrl; private String afterCogUrl; private Geometry bbox; @@ -62,6 +66,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class AnalYearList { + private Long analUid; private String analTitle; private Integer beforeYear; @@ -75,6 +80,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class MapSheetList { + private String mapSheetNum; private String mapSheetName; private String alias; @@ -86,6 +92,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class PolygonFeatureList { + private String type; private List features; // Point 값 } @@ -96,6 +103,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class PointFeatureList { + private String type; private List features; // Point 값 } @@ -106,6 +114,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class PolygonFeature { + private String type; private JsonNode geometry; // after 분류 private PolygonProperties properties; // @@ -117,6 +126,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class PolygonQueryData { + private String type; private String geometry; // geoJson String private Long geoUid; @@ -135,6 +145,7 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class PointFeature { + private String type; private Geometry geometry; // point private PointProperties properties; // Point 정보 @@ -146,14 +157,18 @@ public class ChangeDetectionDto { @NoArgsConstructor @AllArgsConstructor public static class PointProperties { + private Long geoUid; private String classCd; // after 분류 } @Schema(name = "PolygonProperties", description = "폴리곤 정보") @Getter + @Setter + @NoArgsConstructor @AllArgsConstructor public static class PolygonProperties { + private Long geoUid; private Double area; // 면적 private Integer beforeYear; // 기준년도 diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java index f9e3334a..f037f038 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java @@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.changedetection.dto.ChangeDetectionDto; import com.kamco.cd.kamcoback.postgres.core.ChangeDetectionCoreService; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service @@ -34,11 +35,14 @@ public class ChangeDetectionService { return changeDetectionCoreService.getChangeDetectionYearList(); } + @Cacheable(value = "changeDetectionPolygon", key = "#analUid + '_' + #mapSheetNum") public ChangeDetectionDto.PolygonFeatureList getChangeDetectionPolygonList( Long analUid, String mapSheetNum) { + return changeDetectionCoreService.getChangeDetectionPolygonList(analUid, mapSheetNum); } + // Geometry 객체 순환 참조 문제로 캐싱 불가 public ChangeDetectionDto.PointFeatureList getChangeDetectionPointList( Long analUid, String mapSheetNum) { return changeDetectionCoreService.getChangeDetectionPointList(analUid, mapSheetNum); diff --git a/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java new file mode 100644 index 00000000..f1dde5be --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/config/RedisConfig.java @@ -0,0 +1,73 @@ +package com.kamco.cd.kamcoback.config; + +import java.time.Duration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.CacheManager; +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.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +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 { + + @Value("${spring.data.redis.host}") + private String host; + + @Value("${spring.data.redis.port}") + private int port; + + @Value("${spring.data.redis.password}") + private String password; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(); + redisConfig.setHostName(host); + redisConfig.setPort(port); + redisConfig.setPassword(password); + return new LettuceConnectionFactory(redisConfig); + } + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + // Key는 String으로 직렬화 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + // Value는 JSON으로 직렬화 + template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + + template.afterPropertiesSet(); + return template; + } + + // 기본 레디스 캐시 세팅 + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + RedisCacheConfiguration config = + RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofHours(1)) // 기본 TTL 1시간 + .serializeKeysWith( + RedisSerializationContext.SerializationPair.fromSerializer( + new StringRedisSerializer())) + .serializeValuesWith( + RedisSerializationContext.SerializationPair.fromSerializer( + new GenericJackson2JsonRedisSerializer())); + + return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build(); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 25711c02..7e6d6dec 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -25,10 +25,12 @@ spring: idle-timeout: 300000 # 5분 유휴 타임아웃 max-lifetime: 1800000 # 30분 최대 수명 leak-detection-threshold: 60000 # 연결 누수 감지 - + transaction: default-timeout: 300 # 5분 트랜잭션 타임아웃 - - - + data: + redis: + host: 192.168.2.109 + port: 6379 + password: kamco diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 4ae1abee..07d1eaea 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -22,3 +22,9 @@ spring: minimum-idle: 1 maximum-pool-size: 5 + data: + redis: + host: 192.168.2.109 + port: 6379 + password: kamco + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 84e951a0..f8cb1814 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,6 +20,12 @@ spring: idle-timeout: 300000 max-lifetime: 1800000 leak-detection-threshold: 60000 + + data: + redis: + host: localhost + port: 6379 + password: jpa: hibernate: ddl-auto: update # 테이블이 없으면 생성, 있으면 업데이트