무엇이 바뀌었고 무엇을 해야 하는지 알려주는 변경 로그 작성하기
원시 변경 메모를 변경 내용, 사용자 조치, 검증 단계가 구분된 변경 로그로 정리합니다. 합성 소프트웨어 업데이트 예제를 이용해 변경을 만든 사람이 아닌 동료에게도 유용한 릴리스 기록을 만드는 방법을 확인합니다.
간단한 팀 파일명 규칙을 정하고 합성 폴더에서 검사한 뒤, 어떤 파일도 이름을 바꾸거나 삭제하지 않고 검토용 보고서를 작성합니다. 검사기는 구조 오류, 잘못된 날짜, 허용되지 않은 확장자를 구분할 수 있습니다.
이런 분께 맞아요파일을 공유하거나 보관하기 전에 예측 가능한 파일명 규칙과 간단한 자동 검사를 적용하려는 팀을 위한 안내입니다.
이 예제에서는 YYYYMMDD_project_document_vNN.ext 형식을 사용합니다. 날짜는 숫자 8자리이며 실제 존재하는 달력 날짜여야 합니다. project와 document에는 소문자 영문자와 숫자를 사용하고 필요하면 하이픈으로 연결합니다. 버전은 v 다음에 정확히 숫자 2개를 사용합니다. 허용 확장자는 pdf, docx, xlsx, csv, txt입니다.
YYYYMMDD_project_document_vNN.ext
Example:
20260920_alpha_test-plan_v01.pdf아래 파일명은 이 글을 위해 작성한 합성 데이터입니다. 준비용 스크립트를 create_file_naming_demo.py로 저장하세요. 빈 파일 8개를 만들며 그중 4개는 규칙을 따르고 4개는 의도적으로 규칙을 위반합니다.
from pathlib import Path
SOURCE = Path("outputs") / "file_naming_demo"
FILENAMES = [
"20260920_alpha_test-plan_v01.pdf",
"20260920_alpha_results_v02.csv",
"20260921_beta_meeting-notes_v03.txt",
"20261001_beta_budget_v01.xlsx",
"2026-09-20_alpha_notes_v01.txt",
"20260920_Alpha_notes_v01.txt",
"20260920_alpha_notes_final.txt",
"20260230_beta_results_v01.csv",
]
SOURCE.parent.mkdir(parents=True, exist_ok=True)
SOURCE.mkdir() # Stop if the synthetic source already exists.
for filename in FILENAMES:
target = SOURCE / filename
with target.open("xb"):
pass
처음 4개 파일명은 PASS가 예상됩니다. 다섯 번째는 YYYYMMDD 대신 하이픈이 들어간 날짜를 사용합니다. 여섯 번째는 project 토큰에 대문자가 있습니다. 일곱 번째는 vNN 대신 final을 사용합니다. 여덟 번째는 문자열 구조는 맞지만 2026-02-30이라는 존재하지 않는 날짜를 사용합니다.
| 파일명 | 예상 상태 | 이유 |
|---|---|---|
| 20260920_alpha_test-plan_v01.pdf | PASS | 구조가 맞고 날짜도 유효함 |
| 20260920_alpha_results_v02.csv | PASS | 구조가 맞고 날짜도 유효함 |
| 20260921_beta_meeting-notes_v03.txt | PASS | 구조가 맞고 날짜도 유효함 |
| 20261001_beta_budget_v01.xlsx | PASS | 구조가 맞고 날짜도 유효함 |
| 2026-09-20_alpha_notes_v01.txt | FAIL | STRUCTURE_ERROR |
| 20260920_Alpha_notes_v01.txt | FAIL | STRUCTURE_ERROR |
| 20260920_alpha_notes_final.txt | FAIL | STRUCTURE_ERROR |
| 20260230_beta_results_v01.csv | FAIL | INVALID_DATE |
따라서 예상 결과는 검사 파일 8개, PASS 4개, FAIL 4개입니다. 실패 3개는 구조 문제이고, 1개는 구조는 맞지만 달력상 날짜가 잘못되었습니다.
다음 스크립트를 check_file_names.py로 저장하세요. 파일명만 읽고 별도 출력 폴더에 CSV 보고서를 작성합니다. 원본 파일을 이름 변경, 이동, 수정, 삭제하지 않습니다.
import csv
import re
from datetime import datetime
from pathlib import Path
SOURCE = Path("outputs") / "file_naming_demo"
OUTPUT_DIR = Path("outputs") / "file_naming_result"
REPORT = OUTPUT_DIR / "file_naming_report.csv"
ALLOWED_EXTENSIONS = {"pdf", "docx", "xlsx", "csv", "txt"}
NAME_PATTERN = re.compile(
r"^(?P<date>[0-9]{8})_"
r"(?P<project>[a-z0-9]+(?:-[a-z0-9]+)*)_"
r"(?P<document>[a-z0-9]+(?:-[a-z0-9]+)*)_"
r"(?P<version>v[0-9]{2})\."
r"(?P<extension>[a-z0-9]+)$"
)
def check_filename(filename: str) -> tuple[str, str]:
match = NAME_PATTERN.fullmatch(filename)
if match is None:
return "FAIL", "STRUCTURE_ERROR"
extension = match.group("extension")
if extension not in ALLOWED_EXTENSIONS:
return "FAIL", "UNSUPPORTED_EXTENSION"
try:
datetime.strptime(match.group("date"), "%Y%m%d")
except ValueError:
return "FAIL", "INVALID_DATE"
return "PASS", ""
def main() -> None:
if not SOURCE.is_dir():
raise FileNotFoundError(f"Source folder not found: {SOURCE}")
if OUTPUT_DIR.exists():
raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")
files = sorted(path for path in SOURCE.iterdir() if path.is_file())
results = []
for path in files:
status, issue = check_filename(path.name)
results.append({
"filename": path.name,
"status": status,
"issue": issue,
})
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir()
with REPORT.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(
stream,
fieldnames=["filename", "status", "issue"],
)
writer.writeheader()
writer.writerows(results)
passed = sum(row["status"] == "PASS" for row in results)
failed = len(results) - passed
print(f"Files checked: {len(results)}.")
print(f"Passed: {passed}; failed: {failed}.")
print(f"Report: {REPORT.as_posix()}")
if __name__ == "__main__":
main()
python check_file_names.py보고서에는 원본 파일마다 한 행씩 있어야 합니다. 검사 전에 파일명을 알파벳순으로 정렬하므로 출력 순서는 준비용 스크립트 목록이 아니라 정렬된 파일명 순서를 따릅니다.
| 예상 항목 | 값 |
|---|---|
| 검사 파일 | 8 |
| PASS | 4 |
| FAIL | 4 |
| STRUCTURE_ERROR | 3 |
| INVALID_DATE | 1 |
아래 예상 콘솔 출력은 합성 파일명과 검사기를 바탕으로 손으로 도출한 결과이며 실제 실행 로그가 아닙니다.
Files checked: 8.
Passed: 4; failed: 4.
Report: outputs/file_naming_result/file_naming_report.csv| 문제 | 확인할 사항 |
|---|---|
| STRUCTURE_ERROR가 너무 많음 | 문서화한 팀 규칙이 사람들이 실제로 사용하는 방식과 맞는지 확인하세요. |
| 대문자나 공백이 자주 나타남 | 파일마다 임의로 수정하지 말고 금지할지 허용할지 규칙을 명확하게 결정하세요. |
| 형식은 정상인 날짜가 실패함 | YYYYMMDD 문자열이 실제 달력 날짜인지 확인하세요. |
| final이나 latest가 반복적으로 사용됨 | 명시적인 버전 번호를 사용하고 승인 또는 배포 상태는 별도 규칙으로 정의하세요. |
| 이름 변경 후 참조가 깨짐 | 종속 시스템과 링크를 평가하기 전에는 자동 이름 변경을 적용하지 마세요. |
파일명 규칙은 버전 관리 시스템, 문서 관리 시스템, 메타데이터를 대신할 수 없습니다. 파일명이 v03이라고 해서 실제 내용이 v02보다 최신이거나, 올바른 사람이 승인했거나, 올바른 프로젝트에 연결되었다는 뜻은 아닙니다.
이 예제는 한 폴더 바로 아래의 파일만 검사합니다. 하위 폴더를 재귀적으로 검사하지 않고, 여러 공유 드라이브 전체에서 이름의 고유성을 확인하지 않으며, 파일 내용이나 project 토큰이 실제 프로젝트와 일치하는지도 검증하지 않습니다.
팀 규칙을 변경할 때는 적용 시작일을 기록하고 기존 파일을 그대로 인정할지 새 규칙으로 변경할지 결정하세요. 실용적인 규칙은 사람들이 기억할 수 있을 정도로 단순하면서도 자동 검사가 의미 있는 결과를 낼 정도로 명확해야 합니다.
2026-09-20 · 예제 수동 검토 · 대상: Python 3.12 · 표준 라이브러리: csv, datetime, pathlib, re · 실행하지 않음
설명과 예제는 직접 작성했습니다. 관련 동작과 개념은 아래 공식 자료에서 확인할 수 있습니다.