2025. 7. 28. 20:41ㆍLanguages/JAVA
🦜 업무 또는 공부하다 마주친 문제에 대해서, 구글링을 해보며 공부한 내용입니다.
📝 TOCTOU : Time of Check to Time of Use
싱글 스레드가 아닌 멀티 스레드 환경에서, 하나의 리소스를 가지고 여러 스레드가 경쟁하는 상황이 발생할 수 있습니다. 만약 이런 경우는, Reentrant Lock, Synchronized 와 같이 비관적 락의 관점에서 접근하거나 Atomic 처럼 낙관적 락의 관점에서 어떻게 자원을 점유할지 고민할 수 있습니다. 그런데 이런 기법은 애플리케이션의 수준에서의 접근입니다.
만약 자원에 접근할 때, OS 수준까지 내려가면 어떻게 될까요? 이 때 발생할 수 있는 대표적인 문제 중 하나가 TOCTOU입니다.
String path = "(파일 경로)";
File myFile = new File(path);
if(myFile.exist()) {
if(file.delete()) {
//중략
}
}
1) 파일이 경로에 있는지 확인하고, 2) 있는 경우 파일을 삭제하고 싶다면, 위와 같이 코드를 작성할 수 있습니다. 그런데 가끔 이럴 때 TOCTOU 문제가 발생하게 됩니다.
TOCTOU란 무엇일까요? 위키피디아에서는 다음과 같이 소개하고 있습니다.
In software development, time-of-check to time-of-use (TOCTOU, TOCTTOU or TOC/TOU) is
a class of software bugs caused by a race condition
involving the checking of the state of a part of a system (such as a security credential)
and the use of the results of that check.
- 위키피디아(https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)
경쟁 조건(Race Condition)에서 발생할 수 있는 SW 버그로서, 1) check 하고 2) use 하는 시간 사이에 리소스의 상태가 바뀌면 발생할 수 있는 문제가 TOCTOU입니다.
예를 들어 파일을 생성하는 모듈과 파일을 다운로드하는 모듈이 나뉘어 있다고 생각해봅시다. 파일을 다운로드 받을 때 파일이 있는지 체크했는데, 이후 파일을 다운로드하려고 행동하니 파일이 없거나 다른 파일일 수 있습니다. 파일 생성하는 모듈에서 파일을 바꾸거나 새롭게 생성한 것이겠지요!
따라서 TOCTOU 문제를 회피하거나 문제가 발생하는 상황을 줄여보고 싶다면, 코드를 다음과 같이 작성할 수 있습니다.
String path = "(파일 경로)";
Path myPath = Paths.get(path);
if(Files.deleteIfExist(myPath)) {
//중략
}
파일이 있다면 삭제하는 로직을 하나로 합치는 겁니다. 예를 들어, deleteIfExist()는 내부적으로 원자적 시스템 호출을 사용한다고 합니다.
이렇게 코드를 작성해서, 최대한 TOCTOU를 막아보면 좋을 것 같습니다.
References
'Languages > JAVA' 카테고리의 다른 글
| [JAVA] 값 복사 vs 참조 복사 (0) | 2025.02.25 |
|---|---|
| [JAVA] Time (1) | 2025.02.20 |
| [JAVA] Stream++ (1) | 2024.10.05 |
| [JAVA] Optional (2) | 2024.09.08 |
| [JAVA] max() (0) | 2024.04.04 |