Appia의 IT세상

파이썬 임시 파일, 실행 끝나면 지워야 한다 — Path.unlink()로 뒷정리하기 본문

카테고리 없음

파이썬 임시 파일, 실행 끝나면 지워야 한다 — Path.unlink()로 뒷정리하기

Appia 2026. 7. 9. 22:34
반응형

▲ 파이썬 임시 파일, 실행 끝나면 지워야 한다 — Path.unlink()로 뒷정리하기

파이썬으로 업무 자동화를 하다 보면 중간에 '임시 파일'을 만드는 경우가 많습니다. 여러 PDF를 하나로 합치거나, 엑셀을 잠깐 PDF로 변환하거나, 압축을 풀었다가 다시 묶거나 — 결과물을 만드는 과정에서 잠깐 필요했다가 볼일이 끝나는 파일들이죠.

문제는 자동화 스크립트가 매일, 매시간 돈다는 겁니다. 이 임시 파일을 안 지우면 폴더에 merged.pdf, merged (1).pdf … 하루하루 쓰레기가 쌓입니다. 그래서 실전 코드 끝에는 늘 이 한 줄이 붙습니다.

if merged_path.exists():
    merged_path.unlink()          # 볼일 끝난 임시 파일 삭제

짧지만 exists()를 먼저 보는지, unlink()가 정확히 무슨 뜻인지 알고 쓰는 분은 의외로 적습니다. 오늘 이 두 줄을 제대로 뜯어보겠습니다.


📋 목차
  1. 왜 '뒷정리'가 필요한가 — 자동화는 매일 돈다
  2. Path.unlink() — pathlib로 파일 지우기
  3. 왜 exists()를 먼저 확인하나
  4. 더 깔끔하게 — unlink(missing_ok=True)
  5. 실전 — 실패해도 반드시 지운다 (try / finally)
  6. 꼭 알아야 할 주의점 2가지
  7. 마무리

1. 왜 '뒷정리'가 필요한가 — 자동화는 매일 돈다

예를 들어 팀별 보고서 PDF 여러 개를 하나로 합쳐 메일로 보내는 자동화가 있다고 합시다. 과정은 이렇습니다.

① 팀별 PDF를 하나로 병합merged.pdf 생성 (임시)
② 이 merged.pdf를 메일에 첨부해 발송
③ 발송 끝 → merged.pdf는 이제 필요 없음 → 삭제

merged.pdf최종 산출물이 아니라 '거쳐 가는' 파일입니다. 메일만 나가면 역할이 끝나죠. 그런데 ③번을 빼먹으면? 이 자동화가 매일 아침 돌 때마다 임시 파일이 남아, 한 달이면 폴더가 엉망이 되고 어떤 게 진짜 최신본인지도 헷갈리게 됩니다.

💡 핵심 관점 — 자동화 코드는 "한 번 잘 도는 것"이 아니라 "수백 번 돌아도 깨끗한 것"이 목표입니다. 만든 임시 파일은 만든 코드가 직접 치우는 것이 원칙이에요.

2. Path.unlink() — pathlib로 파일 지우기

파이썬 pathlib에서 파일 하나를 삭제하는 메서드가 바로 .unlink()입니다. 이름이 낯설 수 있는데, 리눅스에서 파일 삭제를 뜻하는 전통적인 용어가 unlink라 그대로 가져온 겁니다.

from pathlib import Path

merged_path = Path("output") / "merged.pdf"

merged_path.unlink()          # 이 파일 하나를 삭제

예전 방식인 os.remove()와 하는 일은 똑같습니다. 다만 경로를 Path 객체로 다루면 / 로 경로를 잇고, .exists() · .unlink()한 객체에서 자연스럽게 이어 쓸 수 있어 요즘은 pathlib을 권합니다.

하고 싶은 일 pathlib 방식
파일 삭제 path.unlink()
빈 폴더 삭제 path.rmdir()
폴더 통째로(안 내용까지) 삭제 shutil.rmtree(path)

unlink()딱 '파일 하나' 전용입니다. 폴더에는 못 씁니다(6번에서 다시 얘기합니다).


3. 왜 exists()를 먼저 확인하나

이제 맨 앞의 코드로 돌아옵니다. 왜 그냥 지우지 않고 if merged_path.exists():있는지 먼저 확인했을까요?

답은 간단합니다. 없는 파일을 지우려 하면 에러가 나기 때문입니다.

merged_path.unlink()          # 파일이 없으면?

# FileNotFoundError: [Errno 2] No such file or directory: 'output\merged.pdf'
# 여기서 프로그램이 멈춰버린다

"이미 없으면 어차피 지울 필요도 없는데 왜 에러야?" 싶지만, 파이썬은 "지우라고 했는데 지울 대상이 없다"를 문제 상황으로 봅니다. 그래서 병합이 중간에 실패해서 merged.pdf가 아예 안 만들어진 경우, 뒷정리 코드가 오히려 새로운 에러를 터뜨리는 어이없는 일이 벌어집니다.

if merged_path.exists():      # 있을 때만
    merged_path.unlink()      # 지운다 → 에러 없음

exists()로 한 번 걸러주면, 파일이 있든 없든 이 코드는 조용히 제 할 일만 합니다. 자동화에서 "있으면 지우고, 없으면 그냥 넘어가라"는 게 딱 우리가 원하는 동작이죠.

▲ exists() 없이 삭제하면 FileNotFoundError로 멈춤 / exists() 체크 후에는 조용히 통과


4. 더 깔끔하게 — unlink(missing_ok=True)

사실 파이썬 3.8 이상이라면 이 2줄을 1줄로 줄일 수 있습니다. unlink()missing_ok=True 옵션을 주면 "없으면 그냥 넘어가라"는 뜻이 됩니다.

# 3.8 이상 — 이 한 줄이면 exists() 체크가 필요 없다
merged_path.unlink(missing_ok=True)

동작은 if exists(): unlink()사실상 같습니다. 파일이 있으면 지우고, 없으면 FileNotFoundError알아서 삼켜줍니다.

▲ exists() 먼저 확인하는 방식과 missing_ok=True 방식 — 동작은 같고 표현만 다르다

💡 그럼 뭘 쓰나 — 짧게는 unlink(missing_ok=True)가 깔끔합니다. 다만 팀에 3.7 이하 환경이 섞여 있다면 이 옵션이 없어 에러가 나므로, 그때는 if exists() 방식이 안전합니다. 두 방식의 뜻이 같다는 것만 알면 됩니다.

5. 실전 — 실패해도 반드시 지운다 (try / finally)

한 걸음 더 가봅시다. 메일 발송이 중간에 실패하면 어떻게 될까요? 아래처럼 짜면, 발송에서 에러가 나는 순간 아래 unlink()까지 도달하지 못하고 임시 파일이 남습니다.

merged_path = merge_pdfs(team_files)   # 병합 → 임시 파일 생성
send_mail(merged_path)                 # ← 여기서 실패하면
merged_path.unlink(missing_ok=True)    # ← 이 줄은 실행되지 않는다 (임시 파일 잔존)

그래서 "성공하든 실패하든 뒷정리는 반드시" 하려면 try / finally로 감싸줍니다. finally 블록은 에러가 나든 안 나든 무조건 실행되거든요.

merged_path = merge_pdfs(team_files)   # 병합 → 임시 파일 생성
try:
    send_mail(merged_path)             # 실패할 수도 있는 작업
finally:
    merged_path.unlink(missing_ok=True)  # 성공/실패 무관 — 임시 파일은 항상 정리
💡 왜 finally인가 — 뒷정리를 finally에 두면 "작업이 실패해도 임시 파일은 남지 않는다"가 보장됩니다. 발송 실패는 실패대로 위로 올라가 알람이 울리고, 임시 파일은 임시 파일대로 깨끗이 치워지는 거죠. 실패 처리와 뒷정리는 별개라는 감각이 중요합니다.

▲ send_mail()이 성공하든 실패하든 finally의 unlink()는 무조건 실행된다


6. 꼭 알아야 할 주의점 2가지

unlink()는 폴더에 쓸 수 없다.

unlink()파일 전용입니다. 폴더에 쓰면 IsADirectoryError(윈도우는 PermissionError)가 납니다. 빈 폴더는 rmdir(), 안에 파일이 든 폴더째로 지우려면 shutil.rmtree()를 씁니다.

② 휴지통이 아니다 — 즉시, 영구 삭제된다.

⚠️ unlink()로 지운 파일은 휴지통으로 가지 않습니다. 곧바로 사라지고 되돌릴 수 없어요. 그래서 삭제 대상 경로가 정확한지 — 특히 사용자에게 받은 경로나 조립한 경로를 지울 때는 두 번 확인해야 합니다. "임시 파일만" 지우도록 내가 만든 파일 경로를 그대로 넘기는 게 안전합니다.

휴지통으로 보내고 싶다면 send2trash 같은 별도 라이브러리가 있지만, 내가 방금 만든 임시 파일을 치우는 용도라면 그냥 unlink()로 충분합니다.


7. 마무리

if merged_path.exists(): merged_path.unlink() — 이 두 줄은 단순한 파일 삭제가 아니라, "내가 만든 임시 파일은 내가 치운다"는 자동화의 기본 예의입니다. 이 한 줄이 있고 없고가, 한 달 뒤 폴더의 깨끗함을 가릅니다.

핵심 정리
  1. Path.unlink() = 파일 하나 삭제 (os.remove와 동일)
  2. 없는 파일을 지우면 FileNotFoundError → 그래서 exists()를 먼저 본다
  3. 3.8+ 는 unlink(missing_ok=True) 한 줄로 대체 가능
  4. 실패해도 정리하려면 try / finally에 넣는다
  5. 폴더는 rmdir/shutil.rmtree · 휴지통 없이 영구 삭제임에 주의

이 "임시 파일 뒷정리" 패턴은 PDF 병합·변환·압축을 다루는 자동화 프로젝트마다 그대로 등장합니다. 결과물은 남기고 과정의 흔적은 지우는, 깔끔하게 도는 자동화의 마무리거든요. 다음 글에서는 tempfile 모듈로 애초에 안전한 임시 파일을 만드는 법을 다뤄보겠습니다.

반응형
Comments