✅ 개발환경
Java 8
Spring Boot 2.7
ShedLock 4.44.0
MySQL (JDBC Template 기반)
초반에 java8인데 ShedLock 5.10.1 버전 사용하려해서 계속 에러 이슈 있었다.. 후
| Gradle 의존성 (build.gradle)
dependencies {
implementation 'net.javacrumbs.shedlock:shedlock-spring:4.44.0'
implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:4.44.0'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'mysql:mysql-connector-java:8.0.33'
}
| ShedLock 테이블 생성 (필수)
CREATE TABLE shedlock (
name VARCHAR(64) NOT NULL PRIMARY KEY,
lock_until TIMESTAMP(3) NOT NULL,
locked_at TIMESTAMP(3) NOT NULL,
locked_by VARCHAR(255) NOT NULL
);
💡 이 테이블이 없으면 ShedLock이 동작하지 않습니다.
| ShedLock 설정 클래스
jdbc 사용할 경우 ShedLock 설정 클래스를 수동으로 무조건 생성해 줘야 한다.
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@Configuration
public class ShedLockConfig {
@Bean
public LockProvider lockProvider(ObjectProvider<DataSource> provider) {
// DataSource를 바로 주입 받으려다 실패할 경우 발생하여 아래와 같이 안전하게 처리
DataSource dataSource = provider.getIfAvailable();
if (dataSource == null) {
throw new IllegalStateException("DataSource not found!");
}
return new JdbcTemplateLockProvider(
JdbcTemplateLockProvider.Configuration.builder()
.withJdbcTemplate(new JdbcTemplate(dataSource))
//.usingDbTime() 생략 → 시스템 시간 사용
.build()
);
}
}
log4jdbc 사용하면 .usingDbTime() 호출 시 에러가 발생하여 생략하고 시스템 시간을 사용했다.
db 시간을 사용하고 싶으면 com.mysql.cj.jdbc.Driver 사용하면 된다.
또한, dataSource 값을 가져오려면 jdbc 프로퍼티 설정이 되어 있어야한다.
| application.properties 예시
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/your_db?serverTimezone=Asia/Seoul
spring.datasource.username=your_user
spring.datasource.password=your_password
spring.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy
| 스케줄러 클래스
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyJob {
/*
* lockAtLeastFor 작업이 빨리 끝나도 최소 이 시간만큼 락 유지
* lockAtMostFor 락을 최대 이 시간까지만 유지
*/
@Scheduled(cron = "0 0/1 * * * *") // 매 1분마다 실행
@SchedulerLock(name = "MyJob_scheduledTask", lockAtLeastFor = "PT5S", lockAtMostFor = "PT10S")
public void scheduledTask() {
System.out.println("스케줄 실행됨: " + System.currentTimeMillis());
runTask() // 실행 작업
System.out.println("스케줄 종료됨: " + System.currentTimeMillis());
}
}
| @EnableScheduling 설정 (보통 메인 클래스에 붙임)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class YourApp {
public static void main(String[] args) {
SpringApplication.run(YourApp.class, args);
}
}
여기까지 하면 ShedLock 스케줄러를 사용할 수 있다.
테스트를 해보다가 스케줄러가 겹칠 경우, 메세지를 띄워서 확인하고 싶었다.
그래서 아래와 같이 적용했다.
| LockConfiguration (응용)
스케줄러가 이미 동작 중일 경우에 메세지를 띄우고 싶다면
아래와 같이 LockConfiguration 을 사용하면 된다.
@Scheduled(cron = "*/2 * * * * *")
public void myScheduledTask() {
System.out.println("스케쥴러");
LockConfiguration lockConfig = new LockConfiguration(
Instant.now(),
"MyScheduledJob",
Duration.ofSeconds(30), // lockAtMostFor
Duration.ofSeconds(10) // lockAtLeastFor
);
SimpleLock lock = null;
try {
lock = lockProvider.lock(lockConfig).orElse(null);
if (lock == null) {
System.out.println("[INFO] 이미 실행 중입니다. 다음 주기를 기다립니다.");
return;
}
// 본 작업 실행
System.out.println("[INFO] 작업 시작: " + Instant.now());
runMyTask();
System.out.println("[INFO] 작업 종료: " + Instant.now());
} catch (Exception e) {
Thread.currentThread().interrupt();
System.out.println("[ERROR] 작업 중단됨: " + e.getMessage());
} finally {
if (lock != null) {
lock.unlock();
}
}
}
스케쥴러를 2초마다 동작하도록 하고, 스케줄러가 최소 10초 동안은 lock 을 유지하도록 하고 실행을 해보았다.
그럼 다음과 같이 log 가 찍히는 것을 확인할 수 있다.
runTask() 에는 DB insert 하는 로직을 넣어두었는데, 10초마다 데이터가 들어가는 것을 확인했다.



'Web' 카테고리의 다른 글
| [ spring ] 스케줄러 중복 실행 이슈 및 해결 (0) | 2025.06.04 |
|---|---|
| [ spring ] 최초 폐쇄망(내부망) 순수 gradle 환경 세팅 (0) | 2025.04.02 |
| [ spring ] egovframework(전자정부프레임워크) log4j 이슈해결 maven & gradle (0) | 2025.04.01 |
| [ spring ] egovframework(전자정부프레임워크) 3.9.0 적용 maven & gradle (0) | 2025.04.01 |
| [ Gradle ] gradle exclude dependency (gradle 의존성 제외) (0) | 2025.03.31 |