diff --git a/batch-quartz/pom.xml b/batch-quartz/pom.xml
index 8354471..6750a24 100644
--- a/batch-quartz/pom.xml
+++ b/batch-quartz/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.3.2
+ 2.7.18
com.spring
@@ -27,7 +27,7 @@
- 17
+ 11
diff --git a/batch-quartz/src/main/java/com/spring/common/util/ApplicationUtil.java b/batch-quartz/src/main/java/com/spring/common/util/ApplicationUtil.java
deleted file mode 100644
index 59f0292..0000000
--- a/batch-quartz/src/main/java/com/spring/common/util/ApplicationUtil.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.spring.common.util;
-
-import org.springframework.web.context.ContextLoader;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ApplicationUtil {
-
- public static ServletRequestAttributes getServletRequestAttributes(){
- return (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
- }
- //Request 객체 얻기
- public static HttpServletRequest getRequest(){
- return getServletRequestAttributes().getRequest();
- }
-
- //Set Request Attribute
- public static void setRequestAttributes(String key, Object obj){
- getServletRequestAttributes().setAttribute(key, obj, RequestAttributes.SCOPE_REQUEST);
- }
- //Get Request Attribute
- public static Object getRequestAttributes(String key){
- return getServletRequestAttributes().getAttribute(key, RequestAttributes.SCOPE_REQUEST);
- }
-
- //Session 객체 얻기
- public static HttpSession getSession(){
- return getRequest().getSession();
- }
-
- //Set Session Attributes
- public static void setSessionAttributes(String key, Object obj){
- getServletRequestAttributes().setAttribute(key, obj, RequestAttributes.SCOPE_SESSION);
- }
-
- //Get Session Attributes
- public static Object getSessionAttributes(String key){
- return getServletRequestAttributes().getAttribute(key, RequestAttributes.SCOPE_SESSION);
- }
-
- //HttpServletResponse 객체 얻기
- public static HttpServletResponse getResponse(){
- return getServletRequestAttributes().getResponse();
- }
-
- //beanName을 통해서 Bean을 얻을 수 있다.
- public static Object getBean(String beanName){
- var context = ContextLoader.getCurrentWebApplicationContext();
- if (context == null) {
- throw new IllegalStateException("WebApplicationContext를 찾을 수 없습니다.");
- }
- return context.getBean(beanName);
- }
-
-}
diff --git a/batch-quartz/src/main/java/com/spring/common/util/ContextUtils.java b/batch-quartz/src/main/java/com/spring/common/util/ContextUtils.java
new file mode 100644
index 0000000..4d772a5
--- /dev/null
+++ b/batch-quartz/src/main/java/com/spring/common/util/ContextUtils.java
@@ -0,0 +1,69 @@
+package com.spring.common.util;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+
+/**
+ * Spring ApplicationContext에 접근하기 위한 유틸리티 클래스입니다.
+ *
+ * 이 클래스는 ApplicationContextAware를 구현하여 ApplicationContext를 저장하고,
+ * 애플리케이션 전역에서 Spring 빈에 접근할 수 있는 정적 메소드를 제공합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
+@Component
+public class ContextUtils implements ApplicationContextAware {
+
+ private static final AtomicReference applicationContext = new AtomicReference<>();
+
+ /**
+ * Spring에 의해 호출되어 ApplicationContext를 설정합니다.
+ *
+ * @param context 설정할 ApplicationContext
+ * @throws BeansException 빈 예외 발생 시
+ */
+ @Override
+ public void setApplicationContext(@NonNull ApplicationContext context) throws BeansException {
+ applicationContext.set(context);
+ }
+
+ /**
+ * 지정된 이름과 타입의 빈을 반환합니다.
+ *
+ * @param 반환될 빈의 타입
+ * @param beanName 찾을 빈의 이름
+ * @param clazz 반환될 빈의 클래스
+ * @return 지정된 이름과 타입의 빈
+ * @throws IllegalStateException ApplicationContext가 설정되지 않은 경우
+ */
+ public static T getBean(String beanName, Class clazz) {
+ ApplicationContext context = applicationContext.get();
+ if (context == null) {
+ throw new IllegalStateException("ApplicationContext가 설정되지 않았습니다.");
+ }
+ return context.getBean(beanName, clazz);
+ }
+
+ /**
+ * 지정된 타입의 빈을 반환합니다.
+ *
+ * @param 반환될 빈의 타입
+ * @param clazz 반환될 빈의 클래스
+ * @return 지정된 타입의 빈
+ * @throws IllegalStateException ApplicationContext가 설정되지 않은 경우
+ */
+ public static T getBean(Class clazz) {
+ ApplicationContext context = applicationContext.get();
+ if (context == null) {
+ throw new IllegalStateException("ApplicationContext가 설정되지 않았습니다.");
+ }
+ return context.getBean(clazz);
+ }
+
+}
diff --git a/batch-quartz/src/main/java/com/spring/common/util/ServletUtils.java b/batch-quartz/src/main/java/com/spring/common/util/ServletUtils.java
new file mode 100644
index 0000000..dc6fb54
--- /dev/null
+++ b/batch-quartz/src/main/java/com/spring/common/util/ServletUtils.java
@@ -0,0 +1,117 @@
+package com.spring.common.util;
+
+import java.util.Optional;
+import java.util.function.Function;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * 서블릿 관련 유틸리티 클래스입니다.
+ *
+ * 현재 요청의 HttpServletRequest, HttpServletResponse, HttpSession 등에 접근하는 메서드를 제공합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ServletUtils {
+
+ /**
+ * 현재 요청의 ServletRequestAttributes를 Optional로 반환합니다.
+ *
+ * @return ServletRequestAttributes를 포함한 Optional 객체
+ */
+ private static Optional getAttributes() {
+ return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
+ .filter(ServletRequestAttributes.class::isInstance)
+ .map(ServletRequestAttributes.class::cast);
+ }
+
+ /**
+ * ServletRequestAttributes에서 특정 속성을 추출합니다.
+ *
+ * @param getter ServletRequestAttributes에서 원하는 속성을 추출하는 함수
+ * @param 반환될 속성의 타입
+ * @return 추출된 속성 또는 null
+ */
+ private static T getAttribute(Function getter) {
+ return getAttributes().map(getter).orElse(null);
+ }
+
+ /**
+ * 현재 요청의 HttpServletRequest를 반환합니다.
+ *
+ * @return 현재 HttpServletRequest 또는 null
+ */
+ public static HttpServletRequest getRequest() {
+ return getAttribute(ServletRequestAttributes::getRequest);
+ }
+
+ /**
+ * 현재 요청의 속성을 설정합니다.
+ *
+ * @param key 속성의 키
+ * @param obj 설정할 속성 값
+ */
+ public static void setRequestAttribute(String key, Object obj) {
+ getAttributes().ifPresent(attr -> attr.setAttribute(key, obj, RequestAttributes.SCOPE_REQUEST));
+ }
+
+ /**
+ * 현재 요청의 속성을 반환합니다.
+ *
+ * @param key 속성의 키
+ * @return 요청 속성 값 또는 null
+ */
+ public static Object getRequestAttribute(String key) {
+ return getAttribute(attr -> attr.getAttribute(key, RequestAttributes.SCOPE_REQUEST));
+ }
+
+ /**
+ * 현재 요청의 HttpSession을 반환합니다.
+ *
+ * @return 현재 HttpSession 또는 null
+ */
+ public static HttpSession getSession() {
+ return Optional.ofNullable(getRequest()).map(HttpServletRequest::getSession).orElse(null);
+ }
+
+ /**
+ * 현재 세션의 속성을 설정합니다.
+ *
+ * @param key 속성의 키
+ * @param obj 설정할 속성 값
+ */
+ public static void setSessionAttribute(String key, Object obj) {
+ getAttributes().ifPresent(attr -> attr.setAttribute(key, obj, RequestAttributes.SCOPE_SESSION));
+ }
+
+ /**
+ * 현재 세션의 속성을 반환합니다.
+ *
+ * @param key 속성의 키
+ * @return 세션 속성 값 또는 null
+ */
+ public static Object getSessionAttribute(String key) {
+ return getAttribute(attr -> attr.getAttribute(key, RequestAttributes.SCOPE_SESSION));
+ }
+
+ /**
+ * 현재 요청의 HttpServletResponse를 반환합니다.
+ *
+ * @return 현재 HttpServletResponse 또는 null
+ */
+ public static HttpServletResponse getResponse() {
+ return getAttribute(ServletRequestAttributes::getResponse);
+ }
+
+}
diff --git a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecution.java b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecution.java
index fc77bdd..22a94ad 100644
--- a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecution.java
+++ b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecution.java
@@ -2,15 +2,14 @@ package com.spring.domain.batch.entity;
import java.sql.Timestamp;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.ForeignKey;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
import lombok.Getter;
// @Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionContext.java b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionContext.java
index 794fe9c..439921e 100644
--- a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionContext.java
+++ b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionContext.java
@@ -1,12 +1,11 @@
package com.spring.domain.batch.entity;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.ForeignKey;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+
import lombok.Getter;
// @Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionParams.java b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionParams.java
index f60f775..4ecbf58 100644
--- a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionParams.java
+++ b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobExecutionParams.java
@@ -2,14 +2,13 @@ package com.spring.domain.batch.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.ForeignKey;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -37,7 +36,7 @@ public class BatchJobExecutionParams {
@Embeddable
@Getter
@EqualsAndHashCode
- public class BatchJobExecutionParamsId implements Serializable {
+ public static class BatchJobExecutionParamsId implements Serializable {
@Column(name = "JOB_EXECUTION_ID")
private Long jobExecutionId;
diff --git a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobInstance.java b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobInstance.java
index 135ba06..471b77d 100644
--- a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobInstance.java
+++ b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchJobInstance.java
@@ -1,12 +1,10 @@
package com.spring.domain.batch.entity;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
import lombok.Getter;
// @Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecution.java b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecution.java
index d700071..9ebe1c6 100644
--- a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecution.java
+++ b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecution.java
@@ -2,15 +2,14 @@ package com.spring.domain.batch.entity;
import java.sql.Timestamp;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.ForeignKey;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
import lombok.Getter;
// @Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecutionContext.java b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecutionContext.java
index fdf959e..31bbf02 100644
--- a/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecutionContext.java
+++ b/batch-quartz/src/main/java/com/spring/domain/batch/entity/BatchStepExecutionContext.java
@@ -1,12 +1,11 @@
package com.spring.domain.batch.entity;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.ForeignKey;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+
import lombok.Getter;
// @Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/email/batch/EmailSendBatch.java b/batch-quartz/src/main/java/com/spring/domain/email/batch/EmailSendBatch.java
index 8b85e15..98175ab 100644
--- a/batch-quartz/src/main/java/com/spring/domain/email/batch/EmailSendBatch.java
+++ b/batch-quartz/src/main/java/com/spring/domain/email/batch/EmailSendBatch.java
@@ -3,45 +3,40 @@ package com.spring.domain.email.batch;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
-import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.transaction.PlatformTransactionManager;
import com.spring.infra.quartz.QuartzJob;
-import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
-@RequiredArgsConstructor
public class EmailSendBatch {
- private final JobRepository jobRepository;
- private final PlatformTransactionManager transactionManager;
-
- @QuartzJob(name = "emailSendJob", cronExpression = "*/3 * * * * ?")
+ @QuartzJob(group = "EMAIL", name = "emailSendJob", cronExpression = "*/3 * * * * ?")
+ // @JobScope
@Bean(name = "emailSendJob")
Job emailSendJob(Step emailSendStep) {
log.info(">>> emailSendJob");
- return new JobBuilder("emailSendJob", jobRepository)
+ return new JobBuilder("emailSendJob")
.start(emailSendStep)
.build();
}
+ // @StepScope
@Bean("emailSendStep")
Step emailSendStep(Tasklet emailSendTasklet) {
log.info(">>> emailSendStep");
- return new StepBuilder("emailSendStep", jobRepository)
- .tasklet(emailSendTasklet, transactionManager).build();
+ return new StepBuilder("emailSendStep")
+ .tasklet(emailSendTasklet).build();
}
@Bean
- Tasklet emailSendTasklet(){
+ Tasklet emailSendTasklet() {
return ((contribution, chunkContext) -> {
log.info(">>>>> emailSendTasklet");
return RepeatStatus.FINISHED;
diff --git a/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailqueMst.java b/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailqueMst.java
index d313b4a..323a61c 100644
--- a/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailqueMst.java
+++ b/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailqueMst.java
@@ -3,15 +3,16 @@ package com.spring.domain.email.entity;
import java.io.Serializable;
import java.time.LocalDate;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.IdClass;
-import jakarta.persistence.Lob;
-import jakarta.persistence.SequenceGenerator;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Lob;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailrstLog.java b/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailrstLog.java
index 832f3c7..99348a3 100644
--- a/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailrstLog.java
+++ b/batch-quartz/src/main/java/com/spring/domain/email/entity/ComMailrstLog.java
@@ -3,11 +3,12 @@ package com.spring.domain.email.entity;
import java.io.Serializable;
import java.time.LocalDate;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/post/entity/Post.java b/batch-quartz/src/main/java/com/spring/domain/post/entity/Post.java
index cd85a56..f930ccb 100644
--- a/batch-quartz/src/main/java/com/spring/domain/post/entity/Post.java
+++ b/batch-quartz/src/main/java/com/spring/domain/post/entity/Post.java
@@ -1,14 +1,15 @@
package com.spring.domain.post.entity;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
import com.spring.infra.db.SecondaryDataSourceConfig;
import com.spring.infra.db.orm.jpa.annotation.DatabaseSelector;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
import lombok.Getter;
@DatabaseSelector(SecondaryDataSourceConfig.DATABASE)
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzBlobTriggers.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzBlobTriggers.java
index a00c2fc..32fba82 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzBlobTriggers.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzBlobTriggers.java
@@ -2,13 +2,12 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCalendars.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCalendars.java
index db6af16..8ce4cbb 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCalendars.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCalendars.java
@@ -2,11 +2,10 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCronTriggers.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCronTriggers.java
index 4fdc724..ae2ae10 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCronTriggers.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzCronTriggers.java
@@ -2,15 +2,14 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.ForeignKey;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzFiredTriggers.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzFiredTriggers.java
index 957d761..abfdedb 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzFiredTriggers.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzFiredTriggers.java
@@ -2,11 +2,10 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzJobDetails.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzJobDetails.java
index b59ba79..aa8ab67 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzJobDetails.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzJobDetails.java
@@ -2,11 +2,10 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzLocks.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzLocks.java
index 3ae8de4..5994a61 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzLocks.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzLocks.java
@@ -2,11 +2,10 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzPausedTriggerGrps.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzPausedTriggerGrps.java
index 6a4e7df..a420928 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzPausedTriggerGrps.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzPausedTriggerGrps.java
@@ -2,11 +2,10 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSchedulerState.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSchedulerState.java
index 8d8392e..5288eae 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSchedulerState.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSchedulerState.java
@@ -2,11 +2,10 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpleTriggers.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpleTriggers.java
index f259417..1732114 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpleTriggers.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpleTriggers.java
@@ -2,15 +2,14 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.ForeignKey;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpropTriggers.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpropTriggers.java
index c112e58..720a8ca 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpropTriggers.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzSimpropTriggers.java
@@ -3,15 +3,14 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
import java.math.BigDecimal;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.ForeignKey;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzTriggers.java b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzTriggers.java
index 2f9bfb3..cb308ea 100644
--- a/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzTriggers.java
+++ b/batch-quartz/src/main/java/com/spring/domain/quartz/entity/QrtzTriggers.java
@@ -2,15 +2,14 @@ package com.spring.domain.quartz.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.ForeignKey;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinColumns;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.ForeignKey;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java b/batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java
index 395def2..5bafd12 100644
--- a/batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java
+++ b/batch-quartz/src/main/java/com/spring/domain/user/api/AuthController.java
@@ -1,5 +1,7 @@
package com.spring.domain.user.api;
+import javax.servlet.http.HttpServletResponse;
+
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
@@ -11,7 +13,6 @@ import com.spring.domain.user.dto.SignInRequest;
import com.spring.domain.user.service.AuthService;
import com.spring.infra.security.jwt.JwtTokenService;
-import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
@RestController
diff --git a/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUser.java b/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUser.java
index 3f1470a..d172c86 100644
--- a/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUser.java
+++ b/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUser.java
@@ -2,15 +2,16 @@ package com.spring.domain.user.entity;
import java.util.Set;
-import jakarta.persistence.CascadeType;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.OneToMany;
-import jakarta.persistence.Table;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
import lombok.Getter;
@Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRole.java b/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRole.java
index c14f251..977e3c5 100644
--- a/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRole.java
+++ b/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRole.java
@@ -2,15 +2,16 @@ package com.spring.domain.user.entity;
import java.util.Set;
-import jakarta.persistence.CascadeType;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.OneToMany;
-import jakarta.persistence.Table;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
import lombok.Getter;
@Entity
diff --git a/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRoleMap.java b/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRoleMap.java
index f445e15..104a97b 100644
--- a/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRoleMap.java
+++ b/batch-quartz/src/main/java/com/spring/domain/user/entity/AppUserRoleMap.java
@@ -2,14 +2,15 @@ package com.spring.domain.user.entity;
import java.io.Serializable;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import jakarta.persistence.EmbeddedId;
-import jakarta.persistence.Entity;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.MapsId;
-import jakarta.persistence.Table;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapsId;
+import javax.persistence.Table;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
diff --git a/batch-quartz/src/main/java/com/spring/infra/batch/BatchConfig.java b/batch-quartz/src/main/java/com/spring/infra/batch/BatchConfig.java
new file mode 100644
index 0000000..9ee0e0b
--- /dev/null
+++ b/batch-quartz/src/main/java/com/spring/infra/batch/BatchConfig.java
@@ -0,0 +1,6 @@
+package com.spring.infra.batch;
+
+public class BatchConfig {
+
+
+}
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/PrimaryDataSourceConfig.java b/batch-quartz/src/main/java/com/spring/infra/db/PrimaryDataSourceConfig.java
index 8b95889..d44e479 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/PrimaryDataSourceConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/PrimaryDataSourceConfig.java
@@ -11,6 +11,18 @@ import org.springframework.context.annotation.Primary;
import com.zaxxer.hikari.HikariDataSource;
+/**
+ * 주 데이터 소스 설정을 위한 구성 클래스입니다.
+ *
+ * 이 클래스는 애플리케이션의 주 데이터 소스를 설정하며, 다음과 같은 기능을 제공합니다:
+ *
+ * - 주 데이터 소스 속성 설정
+ * - HikariCP를 사용한 주 데이터 소스 생성
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
public class PrimaryDataSourceConfig {
@@ -19,6 +31,14 @@ public class PrimaryDataSourceConfig {
private static final String DATASOURCE_PROPERTIES = "primaryDataSourceProperties";
private static final String DATASOURCE_PROPERTIES_PREFIX = "spring.datasource.primary";
+ /**
+ * 주 데이터 소스의 속성을 설정합니다.
+ *
+ * 이 메소드는 'spring.datasource.primary' 접두사로 시작하는 설정을 읽어
+ * DataSourceProperties 객체를 생성합니다.
+ *
+ * @return 설정된 DataSourceProperties 객체
+ */
@Primary
@Bean(name = DATASOURCE_PROPERTIES)
@ConfigurationProperties(prefix = DATASOURCE_PROPERTIES_PREFIX)
@@ -26,6 +46,14 @@ public class PrimaryDataSourceConfig {
return new DataSourceProperties();
}
+ /**
+ * 주 데이터 소스를 생성합니다.
+ *
+ * 이 메소드는 설정된 DataSourceProperties를 사용하여 HikariCP 데이터 소스를 생성합니다.
+ *
+ * @param properties 데이터 소스 속성
+ * @return 생성된 DataSource 객체
+ */
@Primary
@Bean(name = DATASOURCE)
DataSource dataSource(@Qualifier(DATASOURCE_PROPERTIES) DataSourceProperties properties) {
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/SecondaryDataSourceConfig.java b/batch-quartz/src/main/java/com/spring/infra/db/SecondaryDataSourceConfig.java
index 8da340c..808948f 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/SecondaryDataSourceConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/SecondaryDataSourceConfig.java
@@ -10,6 +10,18 @@ import org.springframework.context.annotation.Configuration;
import com.zaxxer.hikari.HikariDataSource;
+/**
+ * 보조 데이터 소스 설정을 위한 구성 클래스입니다.
+ *
+ * 이 클래스는 애플리케이션의 보조 데이터 소스를 설정하며, 다음과 같은 기능을 제공합니다:
+ *
+ * - 보조 데이터 소스 속성 설정
+ * - HikariCP를 사용한 보조 데이터 소스 생성
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
public class SecondaryDataSourceConfig {
@@ -18,12 +30,28 @@ public class SecondaryDataSourceConfig {
private static final String DATASOURCE_PROPERTIES = "secondaryDataSourceProperties";
private static final String DATASOURCE_PROPERTIES_PREFIX = "spring.datasource.secondary";
+ /**
+ * 보조 데이터 소스의 속성을 설정합니다.
+ *
+ * 이 메소드는 'spring.datasource.secondary' 접두사로 시작하는 설정을 읽어
+ * DataSourceProperties 객체를 생성합니다.
+ *
+ * @return 설정된 DataSourceProperties 객체
+ */
@Bean(name = DATASOURCE_PROPERTIES)
@ConfigurationProperties(prefix = DATASOURCE_PROPERTIES_PREFIX)
DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
+ /**
+ * 보조 데이터 소스를 생성합니다.
+ *
+ * 이 메소드는 설정된 DataSourceProperties를 사용하여 HikariCP 데이터 소스를 생성합니다.
+ *
+ * @param properties 데이터 소스 속성
+ * @return 생성된 DataSource 객체
+ */
@Bean(name = DATASOURCE)
DataSource dataSource(@Qualifier(DATASOURCE_PROPERTIES) DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/PrimaryJpaConfig.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/PrimaryJpaConfig.java
index 5c39df8..7ee587b 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/PrimaryJpaConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/PrimaryJpaConfig.java
@@ -1,5 +1,6 @@
package com.spring.infra.db.orm.jpa;
+import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -25,9 +26,21 @@ import com.spring.infra.db.PrimaryDataSourceConfig;
import com.spring.infra.db.orm.jpa.annotation.DatabaseSelector;
import com.spring.infra.db.orm.jpa.util.EntityScanner;
-import jakarta.persistence.EntityManagerFactory;
import lombok.RequiredArgsConstructor;
+/**
+ * 주 데이터베이스에 대한 JPA 설정을 담당하는 구성 클래스입니다.
+ *
+ * 이 클래스는 다음과 같은 주요 기능을 제공합니다:
+ *
+ * - 주 데이터베이스용 EntityManagerFactory 설정
+ * - 주 데이터베이스용 TransactionManager 설정
+ * - JPA 리포지토리 활성화 및 필터링
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
@EnableJpaRepositories(
basePackages = PrimaryJpaConfig.BASE_PACKAGE,
@@ -46,6 +59,13 @@ public class PrimaryJpaConfig {
private final JpaProperties jpaProperties;
private final HibernateProperties hibernateProperties;
+ /**
+ * 주 데이터베이스용 EntityManagerFactory를 생성합니다.
+ *
+ * @param builder EntityManagerFactory 빌더
+ * @param dataSource 주 데이터 소스
+ * @return 구성된 LocalContainerEntityManagerFactoryBean
+ */
@Primary
@Bean(name = ENTITY_MANAGER_FACTORY)
LocalContainerEntityManagerFactoryBean entityManagerFactory(
@@ -62,12 +82,23 @@ public class PrimaryJpaConfig {
.build();
}
+ /**
+ * 주 데이터베이스용 TransactionManager를 생성합니다.
+ *
+ * @param factory 주 EntityManagerFactory
+ * @return 구성된 PlatformTransactionManager
+ */
@Primary
@Bean(TRANSACTION_MANAGER)
PlatformTransactionManager transactionManager(@Qualifier(ENTITY_MANAGER_FACTORY) EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}
+ /**
+ * 데이터베이스 선택을 위한 커스텀 필터 클래스입니다.
+ *
+ * 이 필터는 DatabaseSelector 어노테이션이 없는 엔티티만 선택합니다.
+ */
public static class DatabaseFilter implements TypeFilter {
@Override
public boolean match(@NonNull MetadataReader reader, @NonNull MetadataReaderFactory factory) {
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/SecondaryJpaConfig.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/SecondaryJpaConfig.java
index a60c022..9e211d6 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/SecondaryJpaConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/SecondaryJpaConfig.java
@@ -2,6 +2,7 @@ package com.spring.infra.db.orm.jpa;
import java.util.Optional;
+import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -26,9 +27,21 @@ import com.spring.infra.db.SecondaryDataSourceConfig;
import com.spring.infra.db.orm.jpa.annotation.DatabaseSelector;
import com.spring.infra.db.orm.jpa.util.EntityScanner;
-import jakarta.persistence.EntityManagerFactory;
import lombok.RequiredArgsConstructor;
+/**
+ * 보조 데이터베이스에 대한 JPA 설정을 담당하는 구성 클래스입니다.
+ *
+ * 이 클래스는 다음과 같은 주요 기능을 제공합니다:
+ *
+ * - 보조 데이터베이스용 EntityManagerFactory 설정
+ * - 보조 데이터베이스용 TransactionManager 설정
+ * - JPA 리포지토리 활성화 및 필터링
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
@EnableJpaRepositories(
basePackages = SecondaryJpaConfig.BASE_PACKAGE,
@@ -47,6 +60,13 @@ public class SecondaryJpaConfig {
private final JpaProperties jpaProperties;
private final HibernateProperties hibernateProperties;
+ /**
+ * 보조 데이터베이스용 EntityManagerFactory를 생성합니다.
+ *
+ * @param builder EntityManagerFactory 빌더
+ * @param dataSource 보조 데이터 소스
+ * @return 구성된 LocalContainerEntityManagerFactoryBean
+ */
@Bean(name = ENTITY_MANAGER_FACTORY)
LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder,
@@ -62,11 +82,22 @@ public class SecondaryJpaConfig {
.build();
}
+ /**
+ * 보조 데이터베이스용 TransactionManager를 생성합니다.
+ *
+ * @param factory 보조 EntityManagerFactory
+ * @return 구성된 PlatformTransactionManager
+ */
@Bean(TRANSACTION_MANAGER)
PlatformTransactionManager transactionManager(@Qualifier(ENTITY_MANAGER_FACTORY) EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}
+ /**
+ * 데이터베이스 선택을 위한 커스텀 필터 클래스입니다.
+ *
+ * 이 필터는 DatabaseSelector 어노테이션이 있고, 그 값이 보조 데이터베이스와 일치하는 엔티티만 선택합니다.
+ */
public static class DatabaseFilter implements TypeFilter {
@Override
public boolean match(@NonNull MetadataReader reader, @NonNull MetadataReaderFactory factory) {
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/annotation/DatabaseSelector.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/annotation/DatabaseSelector.java
index fb0ca72..79b801c 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/annotation/DatabaseSelector.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/annotation/DatabaseSelector.java
@@ -5,8 +5,34 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * 엔티티 클래스가 사용할 데이터베이스를 지정하는 어노테이션입니다.
+ *
+ * 이 어노테이션은 JPA 엔티티 클래스에 적용되며, 해당 엔티티가 어떤 데이터베이스에서
+ * 사용될지를 지정합니다. 주로 다중 데이터베이스 환경에서 엔티티를 특정 데이터베이스에
+ * 매핑하는 데 사용됩니다.
+ *
+ * 사용 예:
+ *
+ * {@code
+ * @Entity
+ * @DatabaseSelector("secondary")
+ * public class MyEntity {
+ * // 엔티티 필드 및 메소드
+ * }
+ * }
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DatabaseSelector {
+ /**
+ * 엔티티가 사용할 데이터베이스의 이름을 지정합니다.
+ *
+ * @return 데이터베이스 이름
+ */
String value();
}
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/util/EntityScanner.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/util/EntityScanner.java
index 1d39e4c..ca04a13 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/util/EntityScanner.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/jpa/util/EntityScanner.java
@@ -1,5 +1,7 @@
package com.spring.infra.db.orm.jpa.util;
+import javax.persistence.Entity;
+
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.classreading.MetadataReader;
@@ -8,17 +10,38 @@ import org.springframework.util.StringUtils;
import com.spring.infra.db.orm.jpa.annotation.DatabaseSelector;
-import jakarta.persistence.Entity;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+/**
+ * JPA 엔티티 클래스를 스캔하는 유틸리티 클래스입니다.
+ *
+ * 이 클래스는 지정된 패키지 내의 엔티티 클래스를 스캔하고,
+ * 선택적으로 특정 데이터베이스에 해당하는 엔티티만 필터링할 수 있습니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class EntityScanner {
+ /**
+ * 지정된 기본 패키지 내의 모든 엔티티를 스캔합니다.
+ *
+ * @param basePackage 스캔할 기본 패키지
+ * @return 스캔된 엔티티 클래스의 패키지 이름 배열
+ */
public static String[] scanEntities(String basePackage) {
return scanEntities(basePackage, null);
}
+ /**
+ * 지정된 기본 패키지 내의 엔티티를 스캔하고, 선택적으로 특정 데이터베이스에 해당하는 엔티티만 필터링합니다.
+ *
+ * @param basePackage 스캔할 기본 패키지
+ * @param dbName 필터링할 데이터베이스 이름 (null이면 모든 엔티티 반환)
+ * @return 스캔된 엔티티 클래스의 패키지 이름 배열
+ */
public static String[] scanEntities(String basePackage, String dbName) {
var scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter((MetadataReader reader, MetadataReaderFactory factory) -> {
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/PrimaryMybatisConfig.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/PrimaryMybatisConfig.java
index 979e922..a8e5262 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/PrimaryMybatisConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/PrimaryMybatisConfig.java
@@ -16,6 +16,19 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.spring.infra.db.PrimaryDataSourceConfig;
import com.spring.infra.db.orm.mybatis.annotation.PrimaryMapper;
+/**
+ * 주 데이터베이스에 대한 MyBatis 설정을 담당하는 구성 클래스입니다.
+ *
+ * 이 클래스는 다음과 같은 주요 기능을 제공합니다:
+ *
+ * - 주 데이터베이스용 SqlSessionFactory 설정
+ * - MyBatis 매퍼 스캔 설정
+ * - MyBatis 관련 설정 (카멜 케이스 변환, null 처리 등)
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
@MapperScan(
basePackages = {PrimaryMybatisConfig.BASE_PACKAGE},
@@ -29,6 +42,13 @@ public class PrimaryMybatisConfig {
private static final String MAPPER_RESOURCES = "classpath:mapper/**/*.xml";
private static final String SESSION_FACTORY = "primarySqlSessionFactory";
+ /**
+ * 주 데이터베이스용 SqlSessionFactory를 생성합니다.
+ *
+ * @param dataSource 주 데이터 소스
+ * @return 구성된 SqlSessionFactory 객체
+ * @throws Exception SqlSessionFactory 생성 중 발생할 수 있는 예외
+ */
@Primary
@Bean(name = SESSION_FACTORY)
SqlSessionFactory sqlSessionFactory(@Qualifier(PrimaryDataSourceConfig.DATASOURCE) DataSource dataSource) throws Exception {
@@ -41,6 +61,11 @@ public class PrimaryMybatisConfig {
return sessionFactory.getObject();
}
+ /**
+ * MyBatis 설정을 구성합니다.
+ *
+ * @return 구성된 MyBatis Configuration 객체
+ */
private org.apache.ibatis.session.Configuration mybatisConfiguration() {
var configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/SecondaryMybatisConfig.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/SecondaryMybatisConfig.java
index 6138f9c..d064fdd 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/SecondaryMybatisConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/SecondaryMybatisConfig.java
@@ -15,6 +15,19 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.spring.infra.db.SecondaryDataSourceConfig;
import com.spring.infra.db.orm.mybatis.annotation.SecondaryMapper;
+/**
+ * 보조 데이터베이스에 대한 MyBatis 설정을 담당하는 구성 클래스입니다.
+ *
+ * 이 클래스는 다음과 같은 주요 기능을 제공합니다:
+ *
+ * - 보조 데이터베이스용 SqlSessionFactory 설정
+ * - MyBatis 매퍼 스캔 설정
+ * - MyBatis 관련 설정 (카멜 케이스 변환, null 처리 등)
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
@MapperScan(
basePackages = {SecondaryMybatisConfig.BASE_PACKAGE},
@@ -28,6 +41,13 @@ public class SecondaryMybatisConfig {
private static final String MAPPER_RESOURCES = "classpath:mapper/**/*.xml";
private static final String SESSION_FACTORY = "secondarySqlSessionFactory";
+ /**
+ * 보조 데이터베이스용 SqlSessionFactory를 생성합니다.
+ *
+ * @param dataSource 보조 데이터 소스
+ * @return 구성된 SqlSessionFactory 객체
+ * @throws Exception SqlSessionFactory 생성 중 발생할 수 있는 예외
+ */
@Bean(name = SESSION_FACTORY)
SqlSessionFactory sqlSessionFactory(@Qualifier(SecondaryDataSourceConfig.DATASOURCE) DataSource dataSource) throws Exception {
var sessionFactory = new SqlSessionFactoryBean();
@@ -39,6 +59,11 @@ public class SecondaryMybatisConfig {
return sessionFactory.getObject();
}
+ /**
+ * MyBatis 설정을 구성합니다.
+ *
+ * @return 구성된 MyBatis Configuration 객체
+ */
private org.apache.ibatis.session.Configuration mybatisConfiguration() {
var configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/PrimaryMapper.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/PrimaryMapper.java
index 3173d33..4a85aaf 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/PrimaryMapper.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/PrimaryMapper.java
@@ -5,6 +5,26 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * 주 데이터베이스용 MyBatis 매퍼를 지정하는 어노테이션입니다.
+ *
+ * 이 어노테이션은 인터페이스 레벨에서 사용되며, 해당 인터페이스가 주 데이터베이스와
+ * 연결된 MyBatis 매퍼임을 나타냅니다. 주로 다중 데이터베이스 환경에서 매퍼 인터페이스를
+ * 특정 데이터베이스에 연결하는 데 사용됩니다.
+ *
+ * 사용 예:
+ *
+ * {@code
+ * @PrimaryMapper
+ * public interface UserMapper {
+ * // 매퍼 메소드 정의
+ * }
+ * }
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PrimaryMapper {
diff --git a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/SecondaryMapper.java b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/SecondaryMapper.java
index 66dc5c0..d689746 100644
--- a/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/SecondaryMapper.java
+++ b/batch-quartz/src/main/java/com/spring/infra/db/orm/mybatis/annotation/SecondaryMapper.java
@@ -5,6 +5,26 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * 보조 데이터베이스용 MyBatis 매퍼를 지정하는 어노테이션입니다.
+ *
+ * 이 어노테이션은 인터페이스 레벨에서 사용되며, 해당 인터페이스가 보조 데이터베이스와
+ * 연결된 MyBatis 매퍼임을 나타냅니다. 주로 다중 데이터베이스 환경에서 매퍼 인터페이스를
+ * 특정 데이터베이스에 연결하는 데 사용됩니다.
+ *
+ * 사용 예:
+ *
+ * {@code
+ * @SecondaryMapper
+ * public interface UserMapper {
+ * // 매퍼 메소드 정의
+ * }
+ * }
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SecondaryMapper {
diff --git a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java
index 2dd76c3..74a7fef 100644
--- a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzConfig.java
@@ -14,6 +14,19 @@ import org.springframework.transaction.PlatformTransactionManager;
import lombok.RequiredArgsConstructor;
+/**
+ * Quartz 스케줄러 설정을 위한 구성 클래스입니다.
+ *
+ * 이 클래스는 Quartz 스케줄러의 기본 설정을 제공하며, 다음과 같은 기능을 수행합니다:
+ *
+ * - JobFactory 빈 생성 및 설정
+ * - SchedulerFactoryBean 생성 및 설정
+ * - Quartz 작업에 대한 의존성 주입 지원
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
@RequiredArgsConstructor
public class QuartzConfig {
@@ -23,10 +36,13 @@ public class QuartzConfig {
private final PlatformTransactionManager transactionManager;
/**
- * Quartz Schedule Job 에 의존성 주입
+ * Quartz Schedule Job에 의존성을 주입하기 위한 JobFactory를 생성합니다.
*
- * @param beanFactory application context beanFactory
- * @return the job factory
+ * 이 메소드는 Spring의 AutowireCapableBeanFactory를 사용하여
+ * Quartz Job 인스턴스에 자동으로 의존성을 주입합니다.
+ *
+ * @param beanFactory Spring의 AutowireCapableBeanFactory
+ * @return 생성된 JobFactory 인스턴스
*/
@Bean
JobFactory jobFactory(AutowireCapableBeanFactory beanFactory) {
@@ -38,10 +54,19 @@ public class QuartzConfig {
}
/**
- * Scheduler 전체를 관리하는 Manager.
+ * Quartz Scheduler를 생성하고 설정하는 SchedulerFactoryBean을 구성합니다.
+ *
+ * 이 메소드는 다음과 같은 설정을 수행합니다:
+ *
+ * - 스케줄러 이름 설정
+ * - Quartz 속성 설정
+ * - 데이터 소스 및 트랜잭션 매니저 설정
+ * - JobFactory 설정
+ * - 자동 시작 및 종료 시 작업 완료 대기 설정
+ *
*
- * @param jobFactory job factory
- * @return the scheduler factory bean
+ * @param jobFactory 사용할 JobFactory 인스턴스
+ * @return 구성된 SchedulerFactoryBean 인스턴스
*/
@Bean
SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
diff --git a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJob.java b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJob.java
index eb7cb31..2ba225e 100644
--- a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJob.java
+++ b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJob.java
@@ -5,9 +5,50 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * Quartz 스케줄러를 통해 실행될 작업을 정의하는 어노테이션입니다.
+ *
+ * 이 어노테이션은 메소드 레벨에서 사용되며, 해당 메소드를 Quartz 작업으로 등록합니다.
+ *
+ * 주요 기능:
+ *
+ * - 작업의 이름 지정
+ * - 작업의 실행 주기를 Cron 표현식으로 정의
+ *
+ *
+ * 사용 예:
+ *
+ * {@code
+ * @QuartzJob(name = "myJob", cronExpression = "0 0 12 * * ?")
+ * public void myScheduledJob() {
+ * // 작업 내용
+ * }
+ * }
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface QuartzJob {
+ /**
+ * Quartz 작업의 그룹을 지정합니다.
+ *
+ * @return 그룹의 이름
+ */
+ String group() default "DEFAULT";
+ /**
+ * Quartz 작업의 이름을 지정합니다.
+ *
+ * @return 작업의 이름
+ */
String name();
+
+ /**
+ * 작업의 실행 주기를 Cron 표현식으로 지정합니다.
+ *
+ * @return Cron 표현식
+ */
String cronExpression();
}
diff --git a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobLauncher.java b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobLauncher.java
index 57e866a..6eb6f2e 100644
--- a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobLauncher.java
+++ b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobLauncher.java
@@ -13,19 +13,49 @@ import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
+/**
+ * Quartz 작업을 실행하는 Spring Batch Job 실행기 클래스입니다.
+ *
+ * 이 클래스는 Quartz 스케줄러에 의해 호출되며, 지정된 Spring Batch Job을 실행합니다.
+ *
+ * 주요 기능:
+ *
+ * - JobRegistry에서 지정된 이름의 Job을 조회
+ * - Job 실행을 위한 JobParameters 생성
+ * - JobLauncher를 통한 Job 실행
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ * @see QuartzJobBean
+ * @see JobLauncher
+ * @see JobRegistry
+ */
@Component
@RequiredArgsConstructor
public class QuartzJobLauncher extends QuartzJobBean {
private final JobLauncher jobLauncher;
private final JobRegistry jobRegistry;
-
+
private String jobName;
public void setJobName(String jobName) {
this.jobName = jobName;
}
+ /**
+ * Quartz 스케줄러에 의해 호출되는 메소드로, 실제 Job을 실행합니다.
+ *
+ * 이 메소드는 다음과 같은 작업을 수행합니다:
+ *
+ * - JobRegistry에서 지정된 이름의 Job을 조회
+ * - 현재 시간을 기반으로 한 고유한 JobParameters 생성
+ * - JobLauncher를 사용하여 Job 실행
+ *
+ *
+ * @param context Quartz JobExecutionContext 객체
+ */
@Override
protected void executeInternal(@NonNull JobExecutionContext context) throws JobExecutionException {
try {
diff --git a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobRegistrar.java b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobRegistrar.java
index a56abf3..c351a9c 100644
--- a/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobRegistrar.java
+++ b/batch-quartz/src/main/java/com/spring/infra/quartz/QuartzJobRegistrar.java
@@ -19,6 +19,29 @@ import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
+/**
+ * Quartz 작업 등록기 클래스입니다.
+ *
+ * 이 클래스는 애플리케이션 컨텍스트가 리프레시될 때 실행되며,
+ * {@link QuartzJob} 어노테이션이 붙은 모든 메소드를 찾아 Quartz 스케줄러에 등록합니다.
+ *
+ * 주요 기능:
+ *
+ * - 애플리케이션 컨텍스트 내의 모든 빈을 검사
+ * - QuartzJob 어노테이션이 붙은 메소드 식별
+ * - 식별된 메소드를 Quartz 작업으로 등록
+ * - 각 작업에 대한 JobDetail 및 Trigger 생성
+ *
+ *
+ * 이 클래스는 {@link ApplicationListener}를 구현하여
+ * {@link ContextRefreshedEvent}가 발생할 때 자동으로 실행됩니다.
+ *
+ * @author mindol
+ * @version 1.0
+ * @see QuartzJob
+ * @see ApplicationListener
+ * @see ContextRefreshedEvent
+ */
@Component
@RequiredArgsConstructor
public class QuartzJobRegistrar implements ApplicationListener {
@@ -26,6 +49,12 @@ public class QuartzJobRegistrar implements ApplicationListener이 클래스는 application.properties 또는 application.yml 파일에서
+ * "spring.quartz.properties.org.quartz" 접두사로 시작하는 설정을 읽어옵니다.
+ *
+ * 주요 기능:
+ *
+ * - JobStore, Scheduler, ThreadPool 관련 설정 관리
+ * - 설정값을 Properties 객체로 변환
+ *
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Slf4j
@Getter
@RequiredArgsConstructor
@@ -45,18 +60,38 @@ public class QuartzProperties {
private final int threadPriority;
}
+ /**
+ * 현재 객체의 모든 속성을 Properties 객체로 변환합니다.
+ *
+ * @return 변환된 Properties 객체
+ */
public Properties toProperties() {
Properties properties = new Properties();
addProperties(PREFIX, this, properties);
return properties;
}
+ /**
+ * 주어진 객체의 모든 필드를 재귀적으로 순회하며 Properties 객체에 추가합니다.
+ *
+ * @param prefix 속성 키의 접두사
+ * @param object 속성을 추출할 객체
+ * @param properties 속성을 저장할 Properties 객체
+ */
private void addProperties(String prefix, Object object, Properties properties) {
Arrays.stream(object.getClass().getDeclaredFields())
.filter(field -> !Modifier.isStatic(field.getModifiers()))
.forEach(field -> setProperties(prefix, object, properties, field));
}
+ /**
+ * 주어진 필드의 값을 Properties 객체에 추가합니다.
+ *
+ * @param prefix 속성 키의 접두사
+ * @param object 속성을 추출할 객체
+ * @param properties 속성을 저장할 Properties 객체
+ * @param field 처리할 필드
+ */
private void setProperties(String prefix, Object object, Properties properties, Field field) {
try {
Object value = field.get(object);
@@ -74,6 +109,12 @@ public class QuartzProperties {
}
}
+ /**
+ * 주어진 타입이 단순 타입(primitive, String, Number, Boolean, Character)인지 확인합니다.
+ *
+ * @param type 확인할 클래스 타입
+ * @return 단순 타입이면 true, 그렇지 않으면 false
+ */
private boolean isSimpleType(Class> type) {
return type.isPrimitive()
|| String.class == type
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java b/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java
index 4c3e4d5..48867b2 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/config/SecurityConfig.java
@@ -23,16 +23,30 @@ import com.spring.infra.security.handler.JwtAccessDeniedHandler;
import com.spring.infra.security.handler.JwtAuthenticationEntryPoint;
import com.spring.infra.security.jwt.JwtTokenService;
-import lombok.RequiredArgsConstructor;
-
+/**
+ * 애플리케이션의 보안 설정을 담당하는 구성 클래스입니다.
+ *
+ * 이 클래스는 Spring Security를 구성하고 JWT 기반의 인증을 설정합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
-@RequiredArgsConstructor
public class SecurityConfig {
private static final String[] PERMITTED_URI = {"/favicon.ico", "/api/auth/**", "/signIn", "/h2-console/**"};
+ /**
+ * Spring Security의 필터 체인을 구성합니다.
+ *
+ * @param http HttpSecurity 객체
+ * @param tokenService JWT 토큰 서비스
+ * @param authenticationEntryPoint JWT 인증 진입점
+ * @param accessDeniedHandler JWT 접근 거부 핸들러
+ * @return 구성된 SecurityFilterChain
+ */
@Bean
SecurityFilterChain securityFilterChain(
HttpSecurity http,
@@ -46,7 +60,7 @@ public class SecurityConfig {
.httpBasic(HttpBasicConfigurer::disable)
.formLogin(FormLoginConfigurer::disable)
.authorizeHttpRequests(auth -> auth
- .requestMatchers(PERMITTED_URI).permitAll()
+ .antMatchers(PERMITTED_URI).permitAll()
.anyRequest().authenticated()
)
.logout(logout -> logout
@@ -63,11 +77,21 @@ public class SecurityConfig {
return http.build();
}
+ /**
+ * 특정 요청에 대해 보안 검사를 무시하도록 설정합니다.
+ *
+ * @return WebSecurityCustomizer 객체
+ */
@Bean
WebSecurityCustomizer ignoringCustomizer() {
- return web -> web.ignoring().requestMatchers("/h2-console/**");
+ return web -> web.ignoring().antMatchers("/h2-console/**");
}
+ /**
+ * 비밀번호 인코더를 구성합니다.
+ *
+ * @return PasswordEncoder 객체
+ */
@Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/domain/UserPrincipal.java b/batch-quartz/src/main/java/com/spring/infra/security/domain/UserPrincipal.java
index feab821..3c04ff2 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/domain/UserPrincipal.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/domain/UserPrincipal.java
@@ -12,16 +12,34 @@ import com.spring.domain.user.entity.AppUser;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
+/**
+ * Spring Security의 UserDetails 인터페이스를 구현한 사용자 주체(Principal) 클래스입니다.
+ * 애플리케이션의 사용자 정보를 Spring Security에서 사용할 수 있는 형태로 변환합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Getter
@RequiredArgsConstructor
public final class UserPrincipal implements UserDetails {
- private final AppUser appUser;
+ private final transient AppUser appUser;
+ /**
+ * AppUser 객체로부터 UserPrincipal 객체를 생성합니다.
+ *
+ * @param appUser 변환할 AppUser 객체
+ * @return 생성된 UserPrincipal 객체
+ */
public static UserPrincipal valueOf(AppUser appUser) {
return new UserPrincipal(appUser);
}
+ /**
+ * 사용자의 권한 목록을 반환합니다.
+ *
+ * @return 사용자의 GrantedAuthority 컬렉션
+ */
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return appUser.getAppUserRoleMap().stream()
@@ -30,31 +48,62 @@ public final class UserPrincipal implements UserDetails {
.collect(Collectors.toList());
}
+ /**
+ * 계정이 만료되지 않았는지 확인합니다.
+ *
+ * @return 계정 만료 여부 (true: 만료되지 않음)
+ */
@Override
public boolean isAccountNonExpired() {
return true;
}
+ /**
+ * 계정이 잠기지 않았는지 확인합니다.
+ *
+ * @return 계정 잠금 여부 (true: 잠기지 않음)
+ */
@Override
public boolean isAccountNonLocked() {
return true;
}
+ /**
+ * 자격 증명(비밀번호)이 만료되지 않았는지 확인합니다.
+ *
+ * @return 자격 증명 만료 여부 (true: 만료되지 않음)
+ */
@Override
public boolean isCredentialsNonExpired() {
return true;
}
+ /**
+ * 계정이 활성화되어 있는지 확인합니다.
+ *
+ * @return 계정 활성화 여부 (true: 활성화됨)
+ */
@Override
public boolean isEnabled() {
return true;
}
+ /**
+ * 사용자의 비밀번호를 반환합니다.
+ * 이 구현에서는 null을 반환합니다.
+ *
+ * @return 사용자 비밀번호 (null)
+ */
@Override
public String getPassword() {
return null;
}
+ /**
+ * 사용자의 로그인 ID를 반환합니다.
+ *
+ * @return 사용자 로그인 ID
+ */
@Override
public String getUsername() {
return appUser.getLoginId();
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/filter/JwtAuthenticationFilter.java b/batch-quartz/src/main/java/com/spring/infra/security/filter/JwtAuthenticationFilter.java
index 19deef0..205c603 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/filter/JwtAuthenticationFilter.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/filter/JwtAuthenticationFilter.java
@@ -3,6 +3,11 @@ package com.spring.infra.security.filter;
import java.io.IOException;
import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.springframework.lang.NonNull;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -11,21 +16,39 @@ import org.springframework.web.filter.OncePerRequestFilter;
import com.spring.infra.security.jwt.JwtTokenRule;
import com.spring.infra.security.jwt.JwtTokenService;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
+/**
+ * JWT 인증을 처리하는 필터 클래스입니다.
+ *
+ * 이 필터는 요청마다 JWT 토큰을 검증하고, 필요한 경우 토큰을 갱신합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@RequiredArgsConstructor
public final class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenService jwtTokenService;
private final List permitAllUrls;
+ /**
+ * 요청마다 실행되는 필터 메소드입니다.
+ *
+ * JWT 토큰을 검증하고, 필요한 경우 토큰을 갱신합니다.
+ *
+ * @param request HTTP 요청 객체
+ * @param response HTTP 응답 객체
+ * @param filterChain 필터 체인
+ * @throws ServletException 서블릿 예외
+ * @throws IOException 입출력 예외
+ */
@Override
- protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain)
- throws ServletException, IOException {
+ protected void doFilterInternal(
+ @NonNull HttpServletRequest request,
+ @NonNull HttpServletResponse response,
+ @NonNull FilterChain filterChain
+ ) throws ServletException, IOException {
String requestURI = request.getRequestURI();
if (permitAllUrls.stream().anyMatch(requestURI::startsWith)) {
@@ -51,11 +74,15 @@ public final class JwtAuthenticationFilter extends OncePerRequestFilter {
}
jwtTokenService.deleteCookie(response);
-
}
- private void setAuthenticationToContext(String accessToken) {
- Authentication authentication = jwtTokenService.getAuthentication(accessToken);
+ /**
+ * 인증 정보를 SecurityContext에 설정합니다.
+ *
+ * @param token 토큰
+ */
+ private void setAuthenticationToContext(String token) {
+ Authentication authentication = jwtTokenService.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java b/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java
index 06a04a6..199e21b 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAccessDeniedHandler.java
@@ -2,20 +2,38 @@ package com.spring.infra.security.handler;
import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-
/**
- * 유저 정보는 있으나 자원에 접근할 수 있는 권한이 없는 경우 : SC_FORBIDDEN (403) 응답
+ * JWT 인증에서 접근 거부 상황을 처리하는 핸들러 클래스입니다.
+ *
+ * 이 클래스는 사용자가 인증은 되었지만 특정 리소스에 대한 접근 권한이 없는 경우를 처리합니다.
+ * 이런 경우 SC_FORBIDDEN (403) 응답을 반환합니다.
+ *
+ * @author mindol
+ * @version 1.0
*/
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
+ /**
+ * 접근 거부 상황을 처리합니다.
+ *
+ * 사용자가 접근 권한이 없는 리소스에 접근을 시도할 때 호출됩니다.
+ * 이 메소드는 SC_FORBIDDEN (403) 상태 코드를 응답으로 전송합니다.
+ *
+ * @param request 현재 HTTP 요청
+ * @param response 현재 HTTP 응답
+ * @param accessDeniedException 발생한 접근 거부 예외
+ * @throws IOException 입출력 예외 발생 시
+ * @throws ServletException 서블릿 예외 발생 시
+ */
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java b/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java
index f687b75..aaa70d0 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/handler/JwtAuthenticationEntryPoint.java
@@ -2,20 +2,38 @@ package com.spring.infra.security.handler;
import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-
/**
- * 유저 정보 없이 접근한 경우 : SC_UNAUTHORIZED (401) 응답
+ * JWT 인증에서 인증되지 않은 접근을 처리하는 진입점 클래스입니다.
+ *
+ * 이 클래스는 사용자가 인증되지 않은 상태에서 보호된 리소스에 접근을 시도할 때 호출됩니다.
+ * 이런 경우 SC_UNAUTHORIZED (401) 응답을 반환합니다.
+ *
+ * @author mindol
+ * @version 1.0
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
+ /**
+ * 인증되지 않은 접근을 처리합니다.
+ *
+ * 인증되지 않은 사용자가 보호된 리소스에 접근을 시도할 때 호출됩니다.
+ * 이 메소드는 SC_UNAUTHORIZED (401) 상태 코드를 응답으로 전송합니다.
+ *
+ * @param request 현재 HTTP 요청
+ * @param response 현재 HTTP 응답
+ * @param authException 발생한 인증 예외
+ * @throws IOException 입출력 예외 발생 시
+ * @throws ServletException 서블릿 예외 발생 시
+ */
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtProperties.java b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtProperties.java
index 93adcc1..b1f66b5 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtProperties.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtProperties.java
@@ -5,6 +5,12 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
+/**
+ * JWT(JSON Web Token) 관련 설정 속성을 관리하는 클래스입니다.
+ * 'jwt' 접두사로 시작하는 설정 속성을 바인딩합니다.
+ * @author mindol
+ * @version 1.0
+ */
@Getter
@ConfigurationProperties(prefix = "jwt")
@RequiredArgsConstructor
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenGenerator.java b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenGenerator.java
index 07b2fd6..0cb4ae4 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenGenerator.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenGenerator.java
@@ -17,12 +17,26 @@ import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
+/**
+ * JWT 토큰을 생성하는 클래스입니다.
+ *
+ * 이 클래스는 액세스 토큰과 리프레시 토큰을 생성하는 기능을 제공합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Component
@RequiredArgsConstructor
public class JwtTokenGenerator {
private final JwtProperties jwtProperties;
+ /**
+ * 액세스 토큰을 생성합니다.
+ *
+ * @param authentication 인증 정보
+ * @return 생성된 액세스 토큰
+ */
public String generateAccessToken(Authentication authentication) {
return Jwts.builder()
.setHeader(createHeader())
@@ -33,6 +47,12 @@ public class JwtTokenGenerator {
.compact();
}
+ /**
+ * 리프레시 토큰을 생성합니다.
+ *
+ * @param authentication 인증 정보
+ * @return 생성된 리프레시 토큰
+ */
public String generateRefreshToken(Authentication authentication) {
return Jwts.builder()
.setHeader(createHeader())
@@ -42,6 +62,11 @@ public class JwtTokenGenerator {
.compact();
}
+ /**
+ * JWT 헤더를 생성합니다.
+ *
+ * @return JWT 헤더 맵
+ */
private Map createHeader() {
Map header = new HashMap<>();
header.put("typ", "JWT");
@@ -49,6 +74,12 @@ public class JwtTokenGenerator {
return header;
}
+ /**
+ * JWT 클레임을 생성합니다.
+ *
+ * @param authentication 인증 정보
+ * @return JWT 클레임 맵
+ */
private Map createClaims(Authentication authentication) {
Map claims = new HashMap<>();
claims.put(JwtTokenRule.AUTHORITIES_KEY.getValue(), authentication.getAuthorities().stream()
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenRule.java b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenRule.java
index a5e1ef7..33c382a 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenRule.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenRule.java
@@ -3,15 +3,46 @@ package com.spring.infra.security.jwt;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
+/**
+ * JWT 토큰 관련 규칙을 정의하는 열거형입니다.
+ *
+ * 이 열거형은 JWT 토큰 처리에 필요한 다양한 상수 값들을 정의합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@RequiredArgsConstructor
@Getter
public enum JwtTokenRule {
+ /**
+ * JWT 토큰 발급 시 사용되는 HTTP 헤더 이름입니다.
+ */
JWT_ISSUE_HEADER("Set-Cookie"),
+
+ /**
+ * JWT 토큰 해석 시 사용되는 HTTP 헤더 이름입니다.
+ */
JWT_RESOLVE_HEADER("Cookie"),
+
+ /**
+ * 액세스 토큰의 접두사입니다.
+ */
ACCESS_PREFIX("access"),
+
+ /**
+ * 리프레시 토큰의 접두사입니다.
+ */
REFRESH_PREFIX("refresh"),
+
+ /**
+ * Bearer 인증 스키마의 접두사입니다.
+ */
BEARER_PREFIX("Bearer "),
+
+ /**
+ * JWT 클레임에서 권한 정보를 나타내는 키입니다.
+ */
AUTHORITIES_KEY("auth");
private final String value;
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenService.java b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenService.java
index 8d4ca25..ae43a43 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenService.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenService.java
@@ -2,6 +2,10 @@ package com.spring.infra.security.jwt;
import java.security.Key;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.springframework.http.ResponseCookie;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -11,10 +15,15 @@ import org.springframework.stereotype.Service;
import com.spring.infra.security.service.UserPrincipalService;
import io.jsonwebtoken.Jwts;
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
+/**
+ * JWT 토큰 관련 서비스를 제공하는 클래스입니다.
+ *
+ * 이 클래스는 JWT 토큰의 생성, 검증, 해석 등 다양한 토큰 관련 기능을 제공합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Service
public class JwtTokenService {
@@ -41,6 +50,13 @@ public class JwtTokenService {
this.refreshExpiration = jwtProperties.getRefreshToken().getExpiration();
}
+ /**
+ * 액세스 토큰을 생성하고 응답 헤더에 설정합니다.
+ *
+ * @param response HTTP 응답 객체
+ * @param authentication 인증 정보
+ * @return 생성된 액세스 토큰
+ */
public String generateAccessToken(HttpServletResponse response, Authentication authentication) {
String accessToken = jwtTokenGenerator.generateAccessToken(authentication);
ResponseCookie cookie = setTokenToCookie(JwtTokenRule.ACCESS_PREFIX.getValue(), accessToken, accessExpiration / 1000);
@@ -48,6 +64,13 @@ public class JwtTokenService {
return accessToken;
}
+ /**
+ * 리프레시 토큰을 생성하고 응답 헤더에 설정합니다.
+ *
+ * @param response HTTP 응답 객체
+ * @param authentication 인증 정보
+ * @return 생성된 리프레시 토큰
+ */
public String generateRefreshToken(HttpServletResponse response, Authentication authentication) {
String refreshToken = jwtTokenGenerator.generateRefreshToken(authentication);
ResponseCookie cookie = setTokenToCookie(JwtTokenRule.REFRESH_PREFIX.getValue(), refreshToken, refreshExpiration / 1000);
@@ -55,6 +78,14 @@ public class JwtTokenService {
return refreshToken;
}
+ /**
+ * 토큰을 쿠키로 설정합니다.
+ *
+ * @param tokenPrefix 토큰 접두사
+ * @param token 토큰 값
+ * @param maxAgeSeconds 쿠키 유효 시간(초)
+ * @return 생성된 ResponseCookie 객체
+ */
private ResponseCookie setTokenToCookie(String tokenPrefix, String token, long maxAgeSeconds) {
return ResponseCookie.from(tokenPrefix, token)
.path("/")
@@ -65,14 +96,34 @@ public class JwtTokenService {
.build();
}
+ /**
+ * 액세스 토큰의 유효성을 검증합니다.
+ *
+ * @param token 검증할 토큰
+ * @return 토큰의 유효성 여부
+ */
public boolean validateAccessToken(String token) {
return jwtTokenUtil.getTokenStatus(token, accessSecretKey) == JwtTokenStatus.AUTHENTICATED;
}
+ /**
+ * 리프레시 토큰의 유효성을 검증합니다.
+ *
+ * @param token 검증할 토큰
+ * @return 토큰의 유효성 여부
+ */
public boolean validateRefreshToken(String token) {
return jwtTokenUtil.getTokenStatus(token, refreshSecretKey) == JwtTokenStatus.AUTHENTICATED;
}
+ /**
+ * 쿠키에서 토큰을 추출합니다.
+ *
+ * @param request HTTP 요청 객체
+ * @param tokenPrefix 토큰 접두사
+ * @return 추출된 토큰
+ * @throws IllegalStateException 토큰이 없을 경우 발생
+ */
public String resolveTokenFromCookie(HttpServletRequest request, JwtTokenRule tokenPrefix) {
Cookie[] cookies = request.getCookies();
if (cookies == null) {
@@ -81,11 +132,24 @@ public class JwtTokenService {
return jwtTokenUtil.resolveTokenFromCookie(cookies, tokenPrefix);
}
+ /**
+ * 토큰으로부터 인증 정보를 생성합니다.
+ *
+ * @param token JWT 토큰
+ * @return 생성된 Authentication 객체
+ */
public Authentication getAuthentication(String token) {
UserDetails principal = userPrincipalService.loadUserByUsername(getUserPk(token, accessSecretKey));
return new UsernamePasswordAuthenticationToken(principal, "", principal.getAuthorities());
}
+ /**
+ * 토큰에서 사용자 식별자를 추출합니다.
+ *
+ * @param token JWT 토큰
+ * @param secretKey 비밀 키
+ * @return 추출된 사용자 식별자
+ */
private String getUserPk(String token, Key secretKey) {
return Jwts.parserBuilder()
.setSigningKey(secretKey)
@@ -95,6 +159,11 @@ public class JwtTokenService {
.getSubject();
}
+ /**
+ * 액세스 토큰과 리프레시 토큰 쿠키를 삭제합니다.
+ *
+ * @param response HTTP 응답 객체
+ */
public void deleteCookie(HttpServletResponse response) {
Cookie accessCookie = jwtTokenUtil.resetToken(JwtTokenRule.ACCESS_PREFIX);
Cookie refreshCookie = jwtTokenUtil.resetToken(JwtTokenRule.REFRESH_PREFIX);
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenStatus.java b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenStatus.java
index cd4cb81..646b67b 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenStatus.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenStatus.java
@@ -3,10 +3,29 @@ package com.spring.infra.security.jwt;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
+/**
+ * JWT 토큰의 상태를 나타내는 열거형입니다.
+ *
+ * 이 열거형은 JWT 토큰의 유효성 검증 결과를 표현하는 데 사용됩니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@RequiredArgsConstructor
@Getter
public enum JwtTokenStatus {
+ /**
+ * 토큰이 유효하고 인증된 상태를 나타냅니다.
+ */
AUTHENTICATED,
+
+ /**
+ * 토큰이 만료된 상태를 나타냅니다.
+ */
EXPIRED,
+
+ /**
+ * 토큰이 유효하지 않은 상태를 나타냅니다.
+ */
INVALID
}
diff --git a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenUtil.java b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenUtil.java
index 24fe419..9a49a78 100644
--- a/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenUtil.java
+++ b/batch-quartz/src/main/java/com/spring/infra/security/jwt/JwtTokenUtil.java
@@ -5,19 +5,35 @@ import java.security.Key;
import java.util.Arrays;
import java.util.Base64;
+import javax.servlet.http.Cookie;
+
import org.springframework.stereotype.Component;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
-import jakarta.servlet.http.Cookie;
import lombok.extern.slf4j.Slf4j;
+/**
+ * JWT 토큰 관련 유틸리티 기능을 제공하는 클래스입니다.
+ *
+ * 이 클래스는 JWT 토큰의 상태 확인, 쿠키에서 토큰 추출, 서명 키 생성 등의 기능을 제공합니다.
+ *
+ * @author mindol
+ * @version 1.0
+ */
@Slf4j
@Component
public class JwtTokenUtil {
+ /**
+ * JWT 토큰의 상태를 확인합니다.
+ *
+ * @param token 검증할 JWT 토큰
+ * @param secretKey 토큰 검증에 사용할 비밀 키
+ * @return 토큰의 상태 (AUTHENTICATED, EXPIRED, INVALID)
+ */
public JwtTokenStatus getTokenStatus(String token, Key secretKey) {
try {
Jwts.parserBuilder()
@@ -34,6 +50,13 @@ public class JwtTokenUtil {
}
}
+ /**
+ * 쿠키에서 특정 접두사를 가진 토큰을 추출합니다.
+ *
+ * @param cookies 쿠키 배열
+ * @param tokenPrefix 토큰 접두사
+ * @return 추출된 토큰 값 (없으면 빈 문자열)
+ */
public String resolveTokenFromCookie(Cookie[] cookies, JwtTokenRule tokenPrefix) {
return Arrays.stream(cookies)
.filter(cookie -> cookie.getName().equals(tokenPrefix.getValue()))
@@ -42,15 +65,33 @@ public class JwtTokenUtil {
.orElse("");
}
+ /**
+ * 주어진 비밀 키로 서명 키를 생성합니다.
+ *
+ * @param secretKey 비밀 키 문자열
+ * @return 생성된 서명 키
+ */
public Key getSigningKey(String secretKey) {
String encodedKey = encodeToBase64(secretKey);
return Keys.hmacShaKeyFor(encodedKey.getBytes(StandardCharsets.UTF_8));
}
+ /**
+ * 문자열을 Base64로 인코딩합니다.
+ *
+ * @param secretKey 인코딩할 문자열
+ * @return Base64로 인코딩된 문자열
+ */
private String encodeToBase64(String secretKey) {
return Base64.getEncoder().encodeToString(secretKey.getBytes());
}
+ /**
+ * 토큰을 리셋하는 쿠키를 생성합니다.
+ *
+ * @param tokenPrefix 토큰 접두사
+ * @return 생성된 쿠키 객체
+ */
public Cookie resetToken(JwtTokenRule tokenPrefix) {
Cookie cookie = new Cookie(tokenPrefix.getValue(), null);
cookie.setMaxAge(0);
diff --git a/batch-quartz/src/main/resources/application.yml b/batch-quartz/src/main/resources/application.yml
index df03105..47fc998 100644
--- a/batch-quartz/src/main/resources/application.yml
+++ b/batch-quartz/src/main/resources/application.yml
@@ -44,6 +44,8 @@ spring:
show-sql: true
batch:
+ job:
+ enabled: true
jdbc:
initialize-schema: always