diff --git a/Dockerfile b/Dockerfile
index 80fb859..0906462 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -27,13 +27,16 @@ ENV TZ=Asia/Seoul \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseStringDeduplication \
-XX:+HeapDumpOnOutOfMemoryError \
--XX:HeapDumpPath=/tmp \
+-XX:HeapDumpPath=/heapdumps \
+-XX:+ExitOnOutOfMemoryError \
-XX:+DisableExplicitGC \
-javaagent:/opt/opentelemetry-javaagent.jar"
# 타임존 설정
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
+RUN mkdir -p /heapdumps && chown -R 1000:1000 /heapdumps
+
# OTEL 에이전트 복사
COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar
RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar
diff --git a/Jenkinsfile b/Jenkinsfile
index e513db6..f8b193e 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -162,6 +162,10 @@ spec:
done
fi
+ if [ "${TARGET_ENV}" = "dev" ]; then
+ kubectl -n ${APP_NS} patch deploy ${DEPLOY} --type=strategic -p '{"spec":{"template":{"spec":{"containers":[{"name":"'${DEPLOY}'","env":[{"name":"SPRING_PROFILES_ACTIVE","value":"redis-session"}],"volumeMounts":[{"name":"heapdumps","mountPath":"/heapdumps"}]}],"volumes":[{"name":"heapdumps","nfs":{"server":"192.168.0.120","path":"/volume2/NFS/helpdesk-dev/heapdumps"}}]}}}}'
+ fi
+
kubectl -n ${APP_NS} set image deploy/${DEPLOY} ${DEPLOY}=${REG}/${IMAGE}:${IMAGE_TAG}
if [ "${IS_SESSION_JOB}" = "true" ]; then
diff --git a/src/main/java/egovframework/main/web/OptionalSpringSessionFilter.java b/src/main/java/egovframework/main/web/OptionalSpringSessionFilter.java
new file mode 100644
index 0000000..6f3a5fd
--- /dev/null
+++ b/src/main/java/egovframework/main/web/OptionalSpringSessionFilter.java
@@ -0,0 +1,89 @@
+package egovframework.main.web;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+public class OptionalSpringSessionFilter implements Filter {
+
+ private static final String PROPERTIES_PATH = "egovframework/egovProps/globals.properties";
+ private static final String ENABLED_KEY = "Session.Redis.Enabled";
+ private static final String TARGET_BEAN_NAME = "springSessionRepositoryFilter";
+
+ private ServletContext servletContext;
+ private boolean enabled;
+ private volatile Filter delegate;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.servletContext = filterConfig.getServletContext();
+ this.enabled = Boolean.parseBoolean(loadProperty(ENABLED_KEY, "false"));
+ if (this.enabled) {
+ this.servletContext.log("Spring Session Redis filter is enabled.");
+ } else {
+ this.servletContext.log("Spring Session Redis filter is disabled.");
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ if (!this.enabled) {
+ chain.doFilter(request, response);
+ return;
+ }
+ getDelegate().doFilter(request, response, chain);
+ }
+
+ @Override
+ public void destroy() {
+ this.delegate = null;
+ }
+
+ private Filter getDelegate() throws ServletException {
+ Filter current = this.delegate;
+ if (current != null) {
+ return current;
+ }
+ synchronized (this) {
+ current = this.delegate;
+ if (current == null) {
+ WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(this.servletContext);
+ current = context.getBean(TARGET_BEAN_NAME, Filter.class);
+ this.delegate = current;
+ }
+ return current;
+ }
+ }
+
+ private String loadProperty(String key, String defaultValue) {
+ InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(PROPERTIES_PATH);
+ if (input == null) {
+ return defaultValue;
+ }
+ try {
+ Properties properties = new Properties();
+ properties.load(input);
+ return properties.getProperty(key, defaultValue).trim();
+ } catch (IOException e) {
+ this.servletContext.log("Failed to load " + PROPERTIES_PATH + ". Using default for " + key + ".", e);
+ return defaultValue;
+ } finally {
+ try {
+ input.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+}
diff --git a/src/main/resources/egovframework/egovProps/globals-dev.properties b/src/main/resources/egovframework/egovProps/globals-dev.properties
index 6a58aeb..b0c9f4f 100644
--- a/src/main/resources/egovframework/egovProps/globals-dev.properties
+++ b/src/main/resources/egovframework/egovProps/globals-dev.properties
@@ -154,6 +154,7 @@ ldap.username =uid=admin,ou=system
ldap.password =secret
# Spring Session Redis
+Session.Redis.Enabled=true
Session.Redis.Host=sayit-helpdesk-session-redis
Session.Redis.Port=6379
Session.Redis.Database=0
diff --git a/src/main/resources/egovframework/egovProps/globals-prod.properties b/src/main/resources/egovframework/egovProps/globals-prod.properties
index ca2cec8..430bdf1 100644
--- a/src/main/resources/egovframework/egovProps/globals-prod.properties
+++ b/src/main/resources/egovframework/egovProps/globals-prod.properties
@@ -152,6 +152,7 @@ ldap.username =uid=admin,ou=system
ldap.password =secret
# Spring Session Redis
+Session.Redis.Enabled=true
Session.Redis.Host=sayit-helpdesk-session-redis
Session.Redis.Port=6379
Session.Redis.Database=0
diff --git a/src/main/resources/egovframework/egovProps/globals-stage.properties b/src/main/resources/egovframework/egovProps/globals-stage.properties
index e605343..293d946 100644
--- a/src/main/resources/egovframework/egovProps/globals-stage.properties
+++ b/src/main/resources/egovframework/egovProps/globals-stage.properties
@@ -147,6 +147,7 @@ ldap.username =uid=admin,ou=system
ldap.password =secret
# Spring Session Redis
+Session.Redis.Enabled=true
Session.Redis.Host=sayit-helpdesk-session-redis
Session.Redis.Port=6379
Session.Redis.Database=0
diff --git a/src/main/resources/egovframework/egovProps/globals.properties b/src/main/resources/egovframework/egovProps/globals.properties
index 4f61ab4..08d1a3e 100644
--- a/src/main/resources/egovframework/egovProps/globals.properties
+++ b/src/main/resources/egovframework/egovProps/globals.properties
@@ -152,3 +152,6 @@ ldap.url =ldap://localhost:10389
ldap.rootDn =c=kr
ldap.username =uid=admin,ou=system
ldap.password =secret
+
+# Spring Session Redis
+Session.Redis.Enabled=false
diff --git a/src/main/resources/egovframework/spring/com/context-session.xml b/src/main/resources/egovframework/spring/com/context-session.xml
index bb11ebc..2d03ee8 100644
--- a/src/main/resources/egovframework/spring/com/context-session.xml
+++ b/src/main/resources/egovframework/spring/com/context-session.xml
@@ -8,6 +8,7 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
+
+
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index cb95042..c9442a4 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -3,7 +3,7 @@
Default
springSessionRepositoryFilter
- org.springframework.web.filter.DelegatingFilterProxy
+ egovframework.main.web.OptionalSpringSessionFilter
springSessionRepositoryFilter