-
Spring Boot 애플리케이션 종료 시 안전하게 파일 백업 처리하기Tech/SpringBoot 2025. 6. 8. 21:55반응형
Spring Boot 애플리케이션을 개발할 때, 서비스 종료 시 파일 백업이나 리소스 정리 같은 작업이 필요한 경우가 많습니다. 이 글에서는 애플리케이션 종료 시 안전하게 파일을 백업하는 방법을 두 가지 방식으로 소개합니다.
- @PreDestroy를 이용한 Spring Bean 종료 훅
- JVM 레벨에서 작동하는 Shutdown Hook
✅ 환경 설정 (Gradle)
// build.gradle.kts plugins { id("org.springframework.boot") version "3.2.5" id("io.spring.dependency-management") version "1.1.4" kotlin("jvm") version "1.9.23" kotlin("plugin.spring") version "1.9.23" } dependencies { implementation("org.springframework.boot:spring-boot-starter") }
✅ 방식 1. @PreDestroy로 백업 처리하기
import jakarta.annotation.PreDestroy import org.springframework.stereotype.Service import java.io.File import java.nio.file.Files import java.nio.file.StandardCopyOption @Service class FileBackupService { private val sourceFile = File("data/main.csv") private val backupFile = File("backup/main_backup.csv") fun doSomethingWithFile() { println("파일 작업 수행 중...") } @PreDestroy fun backupOnShutdown() { println("애플리케이션 종료 중: 파일 백업 시작") try { if (sourceFile.exists()) { backupFile.parentFile.mkdirs() Files.copy(sourceFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING) println("파일 백업 완료: ${backupFile.absolutePath}") } else { println("백업할 원본 파일이 없습니다.") } } catch (e: Exception) { println("백업 실패: ${e.message}") } } }
✔ 실행 확인용 Runner
import org.springframework.boot.CommandLineRunner import org.springframework.stereotype.Component @Component class FileRunner(private val fileBackupService: FileBackupService) : CommandLineRunner { override fun run(vararg args: String?) { fileBackupService.doSomethingWithFile() println("애플리케이션이 곧 종료됩니다. Ctrl+C 또는 종료 버튼을 누르세요.") } }
✅ 방식 2. JVM Shutdown Hook으로 백업 처리하기
@PreDestroy보다 더 강력하고, Spring 컨텍스트 밖에서도 동작 가능한 방식입니다.
import org.springframework.stereotype.Component import java.io.File import java.nio.file.Files import java.nio.file.StandardCopyOption import javax.annotation.PostConstruct @Component class JvmShutdownFileBackup { private val sourceFile = File("data/main.csv") private val backupFile = File("backup/main_backup.csv") @PostConstruct fun registerShutdownHook() { Runtime.getRuntime().addShutdownHook(Thread { println("[ShutdownHook] JVM 종료 감지됨. 파일 백업 시작...") try { if (sourceFile.exists()) { backupFile.parentFile.mkdirs() Files.copy(sourceFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING) println("[ShutdownHook] 파일 백업 성공: ${backupFile.absolutePath}") } else { println("[ShutdownHook] 원본 파일 없음.") } } catch (e: Exception) { println("[ShutdownHook] 백업 중 오류 발생: ${e.message}") } }) println("Shutdown Hook 등록 완료") } }
✅ 요약 비교
방식 설명
@PreDestroy Spring 관리 Bean이 정상 종료될 때만 동작 Shutdown Hook JVM 종료 감지하여 Spring 컨텍스트 이전에도 동작 가능 kill -9 (SIGKILL) 어떤 방식도 감지 불가능 (OS에서 강제 종료되므로 예외 없음)
✅ 마무리
- 일반적인 Spring 앱에서는 @PreDestroy만으로 충분한 경우가 많습니다.
- 하지만 보다 확실한 종료 처리가 필요하다면 JVM Shutdown Hook을 함께 사용하세요.
- 두 방식을 함께 쓰면 더 안전한 종료 처리를 보장할 수 있습니다.
백업 외에도 로그 정리, 외부 연결 해제 등 다양한 종료 처리를 이 방식에 확장해보세요!
반응형'Tech > SpringBoot' 카테고리의 다른 글
MongoDB 파일 저장소로 사용하기 (1) 2024.11.18 확장 가능한 서비스 구현 패턴 (0) 2024.11.17 Spring Boot에서 RestControllerAdvice 사용 방법 (0) 2024.11.17 Spring Batch를 이용한 클러스터링과 분산 처리 설정 및 구현 방법 (0) 2023.12.26 Quartz를 이용한 클러스터링 설정과 구현 방법 (0) 2023.12.26