파일 일괄 이름 변경 도구
접두사·접미사·일련번호 추가, 찾아 바꾸기, 대소문자 변환, 확장자 수정 — 모두 브라우저에서 처리
파일을 여기에 드래그하거나 아래 버튼을 클릭하세요
모든 파일 형식과 개수 지원, 브라우저에서만 처리되며 절대 업로드되지 않음
파일 일괄 이름 변경이란?
파일 일괄 이름 변경은 정해진 규칙에 따라 여러 파일의 이름을 한 번에 바꾸는 작업입니다. 흔한 사례로는 카메라에서 옮겨온 IMG_1234.JPG 같은 파일을 2026-06-trip-001.jpg로 정리하거나, UI 디자인 에셋에 @2x_ 접두사를 붙이거나, 스캔된 영수증을 청구서 날짜순으로 일련번호를 매기는 작업이 있습니다. macOS Finder의 내장 이름 변경은 「찾아 바꾸기」와 「이름 + 카운터」 형식을 지원하지만 확장자는 다시 쓸 수 없습니다. Windows 탐색기의 Tab 이름 변경은 단순한 일련번호만 추가할 수 있습니다(PowerToys의 PowerRename은 정규식을 지원하지만 별도 설치가 필요). 그 이상으로 복잡한 작업은 보통 ReNamer나 Bulk Rename Utility 같은 데스크톱 앱, 또는 직접 작성한 PowerShell·셸 스크립트가 필요합니다. 이 도구는 접두사·접미사, 번호 매기기, 찾아 바꾸기, 대소문자, 확장자 같은 각 작업을 시각적인 컨트롤로 분해하고 실시간 미리보기와 중복 감지를 제공해, 다운로드 전에 결과를 확인할 수 있습니다. 모든 처리가 브라우저 메모리 안에서 진행되므로, 프로젝트 코드·고객명·개인 정보가 들어 있는 파일명도 사용자의 기기를 떠나지 않습니다.
사용 방법
사용 단계
- 업로드 영역에 파일을 드래그하거나 "파일 선택" 버튼을 클릭하세요. 여러 번 추가하면 목록에 누적됩니다
- "이름순 정렬 / 크기순 정렬"로 순서를 정리하거나, 각 행의 위·아래 화살표로 미세 조정하세요
- 세 개의 카드에서 규칙을 설정하세요. 접두사·접미사, 찾아 바꾸기, 번호 매기기, 대소문자, 확장자
- "새 이름" 열은 실시간으로 갱신됩니다. 파란색은 원본과 다름을, 빨간색은 다른 파일과 충돌함을 의미합니다
- "이 파일 다운로드"로 개별 저장하거나, "ZIP으로 다운로드"로 전체를 한 번에 받으세요
규칙 적용 순서
- 먼저 기본 이름을 교체합니다(비워 두면 원본 유지) — 원본 이름과 무관하게 모든 파일을 예컨대 "photo" + 일련번호 형태로 통일하고 싶을 때 유용합니다
- 그 다음 찾아 바꾸기가 기본 이름에만 적용되며, 확장자는 건드리지 않습니다
- 이어서 번호가 삽입됩니다. 접두사, 접미사, 또는 기본 이름 전체 대체 중에서 선택할 수 있습니다
- 접두사와 접미사가 결과를 감쌉니다
- 마지막으로 대소문자 변환과 확장자 처리가 진행되며, 확장자는 독립적으로 처리됩니다
활용 사례
기술 원리
이 도구 전체는 브라우저의 File API, Blob, URL.createObjectURL 위에서 동작하며, 모든 바이트는 메모리 안에 머무릅니다. 파일을 드래그하거나 선택하면 브라우저는 JavaScript에 File 객체(Blob의 서브클래스)를 JS 힙에 넘겨주고, 도구는 이름 변경을 위해 각 파일의 `name` 속성만 읽을 뿐 바이너리 내용에는 손대지 않습니다. 규칙은 서로 간섭하지 않도록 정해진 순서대로 적용됩니다. 먼저 기본 이름을 결정하고(사용자 입력이거나 원본 기본 이름), 확장자는 lastIndexOf('.')에서 분리합니다(.gitignore 같은 도트 파일은 확장자 없이 기본 이름으로만 취급). 다음으로 찾아 바꾸기가 String.prototype.split + Array.prototype.join 형태로 실행됩니다(정규식이 아닌 순수 문자열 매칭이므로 특수문자가 의도치 않게 매칭되지 않습니다). 이어서 일련번호를 `String(start + i).padStart(pad, '0')`로 계산해 기본 이름의 접두사·접미사·대체 위치에 넣습니다. 그런 다음 접두사·접미사가 결과를 감싸고, 대소문자 변환은 결합된 접두사+기본 이름+접미사 문자열 전체에 한 번에 적용되며, 확장자는 독립적으로 처리됩니다(유지·대문자·소문자·교체). 중복 감지는 미리보기 중에 새 이름들을 Map<string, number>로 카운트합니다. 두 번 이상 등장하는 이름은 duplicateSet에 들어가며, UI는 빨간색으로 강조 표시합니다. duplicateSet이 비어 있지 않은 상태에서 "ZIP으로 다운로드"를 클릭하면 오류 토스트가 표시되고 패키징이 중단되지만, 원본 파일 목록은 그대로 유지되므로 규칙을 조정한 뒤 다시 시도할 수 있습니다. 이 작업은 useMemo([files, opts]) 안에서 실행되므로, 규칙을 수정해도 파일 목록이 다시 렌더링되지 않고 증분 계산만 일어납니다. 단일 파일 다운로드는 File을 URL.createObjectURL로 감싸고, 가짜 `<a download>` 클릭을 트리거한 뒤 곧바로 URL을 해제합니다. ZIP 패키징은 첫 클릭 시점에 JSZip을 동적 import 합니다(약 80 KB로 첫 페인트에 영향 없음). 각 파일의 arrayBuffer()를 읽어 새 이름으로 기록하고, generateAsync({type:'blob', compression:'DEFLATE', compressionOptions:{level:6}})를 호출합니다. DEFLATE는 ZIP 표준 압축 방식이며, 레벨 6은 압축률과 속도의 균형점입니다. 규칙 계산은 파일 개수에 비례하는 O(n)이고, 패키징 시간은 총 바이트 수에 비례합니다. 브라우저는 일반적으로 File의 내용을 지연 읽기(lazy-read) 방식으로 처리하므로, arrayBuffer()를 호출할 때 비로소 디스크에서 바이트를 읽습니다. 따라서 수천 개 파일을 대기열에 두어도 미리보기 비용은 거의 들지 않으며, 메모리 피크는 "ZIP으로 다운로드" 시점에만 발생합니다.
- lastIndexOf('.')로 확장자를 분리합니다. 점이 인덱스 0에만 있는 경우(예: .gitignore)에는 확장자가 없는 것으로 간주하고 앞의 점을 기본 이름에 그대로 둡니다
- 찾아 바꾸기는 replaceAll 대신 String.prototype.split + Array.prototype.join을 사용해, 치환 문자열의 $1·$&가 의도치 않게 해석되는 일을 막습니다
- padStart(pad, '0')로 0 채움 번호를 생성합니다. pad=0이면 정렬이 필요 없는 경우를 위해 가공되지 않은 숫자를 그대로 출력합니다
- 대소문자 변환은 접두사·접미사가 결합된 후에 실행되므로, 기본 이름 전체 구간을 한 번에 정규화합니다. 확장자는 별도로 처리됩니다
- 중복 감지는 useMemo 내부에서 Map으로 실행됩니다. O(n) 재계산이며, UI는 강조 표시된 행의 className만 교체할 뿐 DOM을 다시 빌드하지 않습니다
- Blob URL은 URL.revokeObjectURL로 즉시 해제해 URL 할당 풀을 비웁니다. 헤비 유즈 환경에서 예약된 객체 URL이 빠르게 누적되기 때문입니다
- JSZip은 패키징이 시작될 때만 동적 import로 로드되므로, 약 80 KB의 코드가 첫 페인트나 LCP에 영향을 주지 않습니다
- DEFLATE 레벨 6은 브라우저 환경에서 가장 적절한 균형점입니다. 레벨 9는 1~2%의 추가 압축을 위해 2~3배의 시간이 들고, 이미 압축된 이미지·영상에는 거의 효과가 없습니다
예시
접두사 + 3자리 0 채움 번호 매기기
입력: photo.jpg, sunset.jpg, beach.jpg
규칙: 접두사=trip2026_, 시작=1, 자릿수=3, 위치=뒤
출력:
trip2026_photo001.jpg
trip2026_sunset002.jpg
trip2026_beach003.jpg기본 이름 전체 교체
입력: GH010001.MP4, GH010002.MP4, GH010003.MP4
규칙: base=SceneA_take, 시작=1, 자릿수=2, 위치=뒤, 확장자=소문자
출력:
SceneA_take01.mp4
SceneA_take02.mp4
SceneA_take03.mp4찾아 바꾸기로 불필요한 접미사 제거
입력: report_v1_FINAL.docx, summary_v1_FINAL.docx
규칙: 찾기=_v1_FINAL, 바꾸기=(빈 값), 대소문자=소문자
출력:
report.docx
summary.docx확장자 변경
입력: index.htm, about.htm, contact.htm
규칙: 확장자=교체, 새 확장자=html
출력:
index.html
about.html
contact.html접두사 + 공백→하이픈 + 소문자
입력: Banner Image.PNG, Hero Photo.JPG
규칙: 접두사=web-, 찾기=(공백), 바꾸기=-, 대소문자=소문자, 확장자=소문자
출력:
web-banner-image.png
web-hero-photo.jpg자주 묻는 질문
파일이 서버로 업로드되나요?
아니요. 파일 추가, 새 이름 생성, ZIP 패키징까지 모든 단계가 브라우저 안에서만 실행됩니다. 어떤 업로드 요청도 발생하지 않습니다. 브라우저 개발자 도구의 Network 패널에서 직접 확인할 수 있습니다.
.gitignore나 .bashrc는 왜 확장자가 없는 파일로 처리되나요?
도구는 마지막 점을 기준으로 확장자를 분리합니다. 다만 점이 이름 맨 앞에만 있는 도트 파일은 전체를 기본 이름으로 취급합니다. 숨김 파일을 표시하는 앞쪽 점을 확장자로 오인하지 않기 위함입니다.
새 이름이 충돌하면 어떻게 되나요?
미리보기 목록에서 중복된 이름을 빨간색으로 표시하고 개수 배지를 보여줍니다. 중복이 있는 상태에서 "ZIP으로 다운로드"를 클릭하면 오류 메시지와 함께 차단되지만, 파일 목록이 사라지지는 않으므로 규칙을 조정한 뒤 다시 시도하면 됩니다. 흔한 해결책은 번호 매기기를 켜거나, 자릿수를 늘리거나, 접두사·접미사를 추가하는 것입니다.
폴더 이름을 바꾸거나 폴더 구조를 유지할 수 있나요?
아직은 지원하지 않습니다. 현재 버전은 단일 평면 파일 목록을 다룹니다. 디렉토리 구조까지 일괄 처리해야 한다면 이 도구로 파일 이름을 정리한 뒤 ZIP 패키징 도구로 디렉토리 트리를 구성하세요.
찾아 바꾸기가 정규식을 지원하나요?
지원하지 않습니다. 의도적으로 split-join 기반의 리터럴 문자열 매칭만 사용합니다. 사용자가 치환 문자열에 $1, $& 같은 치환 문자열 토큰을 잘못 입력해도 의도치 않은 동작이 발생하지 않으며, 일반적인 정리 작업의 대부분은 평범한 매칭으로 충분히 처리할 수 있습니다.
파일을 몇 개까지 처리할 수 있나요?
개수에는 사실상 한계가 없습니다 — 미리보기 비용은 거의 0에 가깝습니다. 패키징은 브라우저 메모리에 의해 제한됩니다. 합계 용량이 매우 큰 경우(수 GB 이상) 단일 Blob 할당이 실패할 수 있는데, 그럴 때는 파일을 여러 배치로 나누어 각각 따로 패키징하세요.
다운로드한 ZIP의 비ASCII 파일명이 깨져 보입니다. 왜 그런가요?
JSZip은 기본적으로 UTF-8로 파일명을 기록하며, 최신 압축 해제 도구(macOS Archive Utility, Windows 11 탐색기, 7-Zip, WinRAR 5+)는 정상적으로 읽습니다. Windows 7·8의 구형 탐색기는 비라틴 문자를 잘못 디코딩할 수 있으므로, 이 경우 7-Zip이나 Bandizip을 사용하세요.
실수로 이름을 바꾼 경우 되돌릴 수 있나요?
이름 변경은 다운로드 시점에만 일어납니다 — "ZIP으로 다운로드"나 "이 파일 다운로드"를 클릭하기 전까지 디스크의 원본 파일은 그대로 유지됩니다. 미리보기는 완전히 되돌릴 수 있습니다. 규칙을 초기화하거나 수정하거나, 목록에서 개별 파일을 제거할 수 있습니다. 이미 다운로드한 후라면 동일한 원본 파일을 다시 사용해 규칙을 조정한 뒤 다시 다운로드하면 됩니다.