[개발 깨알 상식_Tips] / 임시 디렉터리 잔여 파일과 테스트 착시.md

임시 디렉터리 잔여 파일과 테스트 착시

조회

2026년 7월 4일 | 개발 깨알 상식_Tips


임시 디렉터리 생성, 실행, 확인, 정리 흐름을 보여 주는 도식
임시 작업 공간은 만드는 것보다 지우는 기준까지 같이 있어야 다음 실행의 착시를 줄인다.

임시 디렉터리를 대충 하나 만들어 쓰면 처음에는 편하다. 문제는 그 디렉터리가 다음 실행의 입력처럼 남는 순간부터 시작된다. 테스트가 깨져야 하는데 예전 산출물이 그대로 있어서 통과하고, 스크립트는 새로 만든 파일인 줄 알고 다음 단계로 넘어간다. 겉으로는 녹색불인데 실제로는 오래된 파일을 읽은 셈이라, 나중에 원인을 찾으면 허무하다. 이런 실패는 로그가 시끄럽지 않아서 더 늦게 발견된다.

나는 이런 류의 문제를 몇 번 겪고 나서 임시 작업 공간을 세 가지로 본다. 첫째, 매번 고유한 위치를 만든다. 둘째, 실패해도 지워질 경로를 미리 등록한다. 셋째, 필요한 산출물이 정말 이번 실행에서 나왔는지 확인한다. 이 셋 중 하나만 빠져도 임시 디렉터리는 안전한 격리 공간에서 작은 캐시로 바뀐다.

같은 tmp 경로가 만드는 제일 조용한 실패

가장 흔한 패턴은 /tmp/my-test 같은 고정 경로를 계속 쓰는 것이다. 첫 실행에서 result.json이 생기고, 두 번째 실행에서는 앞 단계가 실패했는데도 뒤 단계가 그 파일을 읽는다. 로그에는 파일이 “있다”고만 나오니 한참 뒤에야 새로 생성한 산출물이 아니었다는 걸 알아차린다. 그래서 임시 경로는 이름이 예쁜 것보다 이번 실행과만 묶여 있는지가 더 중요하다. 같은 경로를 다시 쓸수록 이 확인은 더 흐려진다.

mktemp -d는 이 부분을 꽤 단순하게 만들어 준다. 사람이 직접 suffix를 붙이는 대신 충돌 가능성이 낮은 디렉터리를 만들고, 그 경로를 변수 하나에 담아 다음 명령에서만 쓴다. 나는 여기서 경로를 길게 꾸미기보다, 로그 첫 줄에 임시 경로를 한 번 찍고 나머지는 그 안에서만 움직이는 쪽을 선호한다. 실패했을 때도 “어느 실행의 찌꺼기인가”를 좁히기 쉽고, 재현 범위도 작게 접힌다.

trap으로 고정하는 실패 경로 계약

trap을 붙이는 이유를 단순히 청소라고만 보면 가끔 빠뜨리게 된다. 내가 보는 핵심은 스크립트가 어느 지점에서 끝나든 같은 정리 경로를 탄다는 계약이다. 중간 assertion에서 멈추든, 네트워크 호출이 실패하든, 사람이 Ctrl-C로 끊든, 임시 디렉터리가 계속 남아 있으면 다음 실행이 오염될 수 있다.

tmpdir=$(mktemp -d)
cleanup() { rm -rf "$tmpdir"; }
trap cleanup EXIT INT TERM

# 이후 작업은 "$tmpdir" 아래에서만 수행

이 정도만 있어도 고정 tmp 경로를 쓰는 것보다 훨씬 낫다. 다만 무조건 지우는 게 항상 답은 아니다. 디버깅이 필요한 실패라면 보존 모드를 따로 두는 편이 좋다. 예를 들어 환경변수로 cleanup을 끄거나, 실패 시 경로를 마지막 줄에 남기고 수동 확인 후 지우는 식이다. 이때도 기본값은 삭제로 두고, 보존은 명시적으로 켜야 한다. 그래야 임시 파일이 늘 남는 상태를 디버깅 편의라고 착각하지 않는다. 중요한 건 평소 동작과 디버깅 동작이 섞이지 않는 것이다.

생성 확인은 존재 여부보다 이번 실행 여부

임시 디렉터리를 써도 확인이 약하면 같은 문제가 반복된다. 파일이 존재하는지만 보면 이전 단계가 실제로 실행됐는지 알 수 없다. 그래서 나는 산출물 확인을 할 때 파일 존재, 크기, 수정 시각, 내부 marker 중 하나를 같이 본다. 특히 JSON이나 리포트 파일이라면 실행 ID, 입력 파일명, record count 같은 작은 값을 같이 넣어 두면 재사용 착시를 줄일 수 있다.

테스트에서는 이 차이가 더 크게 느껴진다. 테스트가 output.json 하나만 찾으면, 이전 실행에서 남은 파일 때문에 통과할 수 있다. 반대로 이번 입력 이름이 본문에 들어 있는지, 기대한 개수의 record가 있는지, 빈 배열이 아닌지까지 보면 실패 위치가 앞당겨진다. 나는 이 확인을 cleanup 뒤보다 후속 단계 직전에 한 번 더 둔다. 그 시점이 실제로 산출물을 소비하는 자리라서, 잘못된 파일을 가장 싸게 멈출 수 있기 때문이다. 결국 cleanup trap은 파일 삭제와 다음 단계가 믿어도 되는 산출물인지 확인하는 습관이 같이 있어야 한다.

남겨야 할 것과 지워야 할 것의 분리

모든 임시 파일을 끝까지 숨기면 나중에 디버깅이 불편하다. 반대로 전부 남기면 작업 폴더가 금방 쓰레기장이 된다. 내가 요즘 쓰는 기준은 단순하다. 재현에 필요한 작은 로그와 입력 요약은 별도 위치에 남기고, 중간 산출물과 다운로드 찌꺼기는 trap으로 지운다. 남기는 파일은 이름에 실행 ID나 입력 해시를 붙이고, 지우는 파일은 tmpdir 안으로만 몰아넣는다.

이렇게 나누면 cleanup이 공격적으로 돌아도 불안하지 않다. 필요한 증거는 이미 밖으로 빼 두었고, tmpdir 안에는 다시 만들 수 있는 파일만 있으니까. 에이전트나 CI가 끼어 있는 작업에서는 이 구분이 더 중요하다. 실패 로그만 보고 다음 패치를 해야 하는데, tmpdir에 이전 실행 산출물이 섞여 있으면 원인과 결과가 뒤엉킨다.

삭제 명령에도 안전장치가 필요하다

cleanup을 넣었다고 해서 바로 안심할 수는 없다. 지우는 명령은 항상 변수 실수에 민감하다. tmpdir이 비어 있거나 예상 밖의 상위 경로를 가리키면 정리 명령 자체가 사고가 된다. 그래서 나는 삭제 전에 경로가 비어 있지 않은지, 기대한 prefix 아래인지, 실제 디렉터리인지 확인하는 작은 guard를 둔다. 임시 파일을 지우려다 작업 폴더를 지우는 실수는 한 번이면 충분하다.

또 하나는 cleanup 로그다. 성공 로그를 길게 남길 필요는 없지만, 실패했을 때 지우려던 경로와 실패 이유는 남기는 편이 좋다. 특히 권한 문제나 열린 파일 핸들 때문에 삭제가 실패하면, 다음 실행의 오염 원인이 바로 그 줄에 있다. 조용한 cleanup 실패는 조용한 테스트 통과만큼 위험하다.

작은 스크립트일수록 먼저 넣는 이유

큰 배치 작업에서는 다들 임시 경로를 신경 쓴다. 이상하게 작은 재현 스크립트에서는 이 부분을 대충 넘기기 쉽다. 그런데 작은 스크립트일수록 자주 고쳐 실행하고, 실패한 상태에서 다시 돌리는 횟수가 많다. 그래서 잔여 파일이 만든 착시도 오히려 더 자주 나온다.

내 기준은 이제 꽤 고정됐다. 두 번 이상 실행할 스크립트라면 고유 tmpdir을 만들고, trap으로 정리하고, 필수 산출물 확인을 넣는다. 코드 몇 줄이 늘지만, “왜 통과했지?”를 뒤늦게 묻는 시간을 줄여 준다. 여기에 디버깅용 보존 옵션까지 좁게 열어 두면 평소에는 깨끗하게 지우고, 필요할 때만 실패 현장을 남길 수 있다. 임시 디렉터리는 잠깐 쓰는 공간이지만, 그 잠깐이 다음 판단을 속이지 않게 만드는 쪽이 결국 더 빠르다.

댓글

홈으로 돌아가기

검색 결과

"" 검색 결과입니다.