Python os.replace 사용법: 임시 파일로 JSON 결과를 저장하고 교체하기
요약: 결과 파일을 직접 덮어쓰는 도중 프로그램이 종료되면 다음 작업이 불완전한 파일을 읽을 수 있다. 같은 디렉터리에 임시 파일을 완성한 뒤 교체하는 패턴과 그 한계를 설명한다.
문제와 배경
예약 작업이 JSON 결과를 저장하고 다른 프로그램이 이를 읽는 구조를 생각해 보자. 기존 파일을 쓰기 모드로 연 뒤 중간에 실패하면 정상 결과까지 잃을 수 있다.
핵심 내용
os.replace()는 대상 파일이 있으면 권한이 허용하는 경우 교체한다. 서로 다른 파일시스템 사이에서는 실패할 수 있으며, 공식 문서는 성공한 이름 변경의 원자성을 설명한다. 따라서 임시 파일을 대상과 같은 디렉터리에 만드는 방식이 유용하다.
다만 원자적인 교체와 정전 이후의 영속성, 여러 작성자 간 충돌 방지는 서로 다른 문제다.
실무 코드 예시
다음은 단일 작성자가 JSON 결과를 저장하는 설명용 예시다.
운영 적용 전: 기존 결과 파일과 관련 설정을 백업하고, 테스트 환경에서 쓰기 실패·프로세스 종료·권한·동시 실행 조건을 검증한다. 아래 코드는 대상 파일을 교체한다.
from pathlib import Path
import json
import os
import tempfile
target = Path("result.json")
payload = {"status": "ok", "count": 3}
temporary = None
try:
with tempfile.NamedTemporaryFile(
mode="w",
encoding="utf-8",
dir=target.parent,
prefix=f".{target.name}.",
suffix=".tmp",
delete=False,
) as file:
temporary = Path(file.name)
json.dump(payload, file, ensure_ascii=False)
file.write("\n")
file.flush()
os.fsync(file.fileno())
os.replace(temporary, target)
temporary = None
finally:
if temporary is not None:
temporary.unlink(missing_ok=True)
파일 내용 쓰기와 닫기가 끝난 뒤 교체한다. 독자는 교체 전 결과 또는 교체 후 결과를 읽도록 설계하되, 실제 파일시스템과 공유 환경에서 동작을 검증한다.
주의사항
- 강제 종료되면 정리 코드가 실행되지 않아 임시 파일이 남을 수 있다.
- 여러 작성자가 동시에 실행하면 나중 교체가 앞선 결과를 덮어쓸 수 있다.
- 새 임시 파일의 권한·소유권이 기존 결과 파일과 다를 수 있다.
- 네트워크 공유와 Windows의 파일 열기 상태에서는 별도 제약이 있을 수 있다.
- 이 예시는 디렉터리 동기화까지 포함한 정전 영속성을 보장하지 않는다.
- JSON 문법이 올바른 것과 업무 결과가 올바른 것도 별도로 검증해야 한다.
운영자 체크리스트
- 임시 파일과 대상이 같은 파일시스템에 있는가?
- 쓰기가 끝난 후 교체하는가?
- 파일 권한과 동시 실행을 검토했는가?
- 남은 임시 파일의 정리 정책이 있는가?
- 읽는 프로그램이 실패를 감지할 수 있는가?
정리
임시 파일 작성 후 교체하는 패턴은 불완전한 결과 노출을 줄이는 데 도움이 된다. 동시 실행과 권한, 영속성까지 필요한 수준으로 보완해야 운영에 사용할 수 있다.
참고자료
'자동화·AI' 카테고리의 다른 글
| Python subprocess.run 사용법: 종료 코드·시간 초과·실행 실패 처리하기 (0) | 2026.10.23 |
|---|---|
| Python RotatingFileHandler 사용법: 자동화 로그 크기와 보관 개수 제한하기 (0) | 2026.10.23 |
| AIOps RAG 검색 결과가 없을 때: Qdrant score_threshold와 근거 부족 응답 설계 (0) | 2026.10.13 |
| AIOps RAG 프롬프트 인젝션 대응: 검색 문서와 운영 실행 권한 분리하기 (0) | 2026.10.12 |
| Prometheus 수집 누락 경보: up과 absent_over_time으로 감시 공백 찾기 (0) | 2026.10.11 |