개발그래머
Java WatchService를 이용하여 파일 감지하기 본문
개요
- 운영 업무를 하다 보면 추가해야 될 것들, 변경해야 될 것들, 등록해줘야 할 것들이 생기는데 주로 csv파일(개발자) 혹은 엑셀 파일(업무담당자)로 전달받게 된다.
- 유저 자동 가입 처리라던지, csv 파일에 해당하는 값으로 변경한다던지 소소한 잡일들이 많이 생기는데 생각외로 많은 시간을 할애하게 되고 업무의 흐름을 방해하여 자동화하기로 하였다.
WatchService 란?
- Java NIO(Non-blocking I/O) 패키지의 일부로서 파일 시스템의 변경 사항을 감시하고 관찰하는 데 사용되며 파일 또는 디렉토리의 생성, 수정, 삭제 등의 이벤트를 감지할 때 활용됨
- 파일 시스템의 특정 디렉토리에 대한 변경 사항을 모니터링하기 위해 사용되며 감시 대상 디렉토리에 대한 이벤트가 발생하면 이를 감지하고 애플리케이션에 알리며 이를 통해 파일 시스템의 변경 사항에 반응하여 적절한 조치를 취할 수 있음
사용법
@Component
class DirectoryWatchService {
private val watchService: WatchService
private val logger: Logger = LoggerFactory.getLogger(DirectoryWatchService::class.java)
init {
watchService = try {
FileSystems.getDefault().newWatchService()
} catch (e: IOException) {
logger.error("IOException : ", e)
throw e
}
}
fun watch() {
val fullFilePath = "/Users/im-yohwan/Downloads"
val dir = Paths.get(fullFilePath);
try {
dir.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE)
while (true) {
val key = watchService.take()
for (pollEvent in key.pollEvents()) {
val kind = pollEvent.kind()
val ev: WatchEvent<Path> = pollEvent as WatchEvent<Path>
val filename = ev.context()
when (kind) {
OVERFLOW -> {
logger.info("OVERFLOW")
}
ENTRY_CREATE -> {
logger.info("Created: $filename");
}
ENTRY_MODIFY -> {
logger.info("Modified: $filename");
}
ENTRY_DELETE -> {
logger.info("Deleted: $filename");
}
}
}
val valid = key.reset()
if (!valid) {
break
}
}
} catch (e: IOException) {
logger.info("IOException : ", e)
}
}
}
fullFilePath에 감시를 원하는 경로를 지정하면 되고 pollEvents에서 어떠한 변경사항들이 발생하였는지 알 수 있다.
- OVERFLOW = 이벤트가 손실되거나 폐기되었을 수 있음을 나타내는 특별 이벤트
- ENTRY_CREATED = 디렉터리에 항목이 생성됨
- ENTRY_MODIFIED = 디렉터리에 항목이 수정됨
- ENTRY_DELETE = 디렉터리에 항목이 삭제됨
위 이벤트들을 바탕으로 원하는 액션을 줄 수 있으며 주로 ENTRY_CREATED를 사용하게 된다.
@Component
class DirectoryWatchScheduler(
private val directoryWatchService: DirectoryWatchService
) {
private val logger: Logger = LoggerFactory.getLogger(DirectoryWatchScheduler::class.java)
@Scheduled(fixedDelay = 10000)
fun watchDirectory() {
logger.info("start watchDirectory")
try {
directoryWatchService.watch()
} catch (e: Exception) {
logger.info("Exception : ", e)
}
}
}
또한, Spring Scheduler와 같이 사용하여 해당 watchService가 다운되더라도 재실행할 수 있다.
주의사항
- 리눅스 서버에서 vim으로 사용하여 파일 생성시 스왑파일도 감지가 되므로 꼭 특정 파일 이름을 정해두고 사용하는 것이 좋다.
- 한글 파일 사용시 번거로울 수 있으므로 영어 이름 파일을 사용하는 것을 추천한다.
- 팀원들과 어떤식으로 사용할지 상의하고 문서화하자.
'Java' 카테고리의 다른 글
프로퍼티 동적으로 구성하기 (0) | 2024.05.12 |
---|---|
[자바스터디 번외] 문자열, 콜렉션, 스트림 (0) | 2023.09.24 |
'filter()' and 'map()' can be swapped (0) | 2023.07.31 |
[자바스터디 15주차] 람다식 (0) | 2023.07.24 |
[자바스터디 14주차] Generic (0) | 2023.07.18 |