수백 개의 폴더가 있는 프로젝트를 관리해보신 적이 있으신가요? 아니면 회사의 방대한 문서 저장소를 체계적으로 정리해야 했던 경험이 있으신가요?
이런 상황에서 폴더 구조를 수동으로 문서화하는 것은 지루하고 시간 소모적인 작업입니다. 더구나 실수하기도 쉽죠. 이런 고민을 해결하기 위해 Python을 활용한 스마트한 해결책을 만들어보려고 합니다.
flowchart LR
A[폴더 선택] --> B[구조 분석]
B --> C[데이터 처리]
C --> D[엑셀 생성]
subgraph Process["처리 과정"]
B
C
end
style A fill:#f9f,stroke:#333,stroke-width:2px
style D fill:#bbf,stroke:#333,stroke-width:2px
기술 스택 살펴보기
이 프로젝트는 Python의 강력한 라이브러리들을 활용하여 구축됩니다. 각 라이브러리의 역할과 특징을 자세히 살펴보겠습니다.
| 라이브러리 | 주요 기능 | 사용 목적 | 특징 |
|---|---|---|---|
| tkinter | GUI 구현 | 사용자 인터페이스 제공 | Python 기본 내장, 가벼움 |
| pandas | 데이터 처리 | 폴더 정보 구조화 | 강력한 데이터 분석 기능 |
| os | 파일 시스템 접근 | 폴더 구조 탐색 | 크로스 플랫폼 지원 |
| datetime | 시간 정보 처리 | 파일 생성/수정 시간 | 정밀한 시간 계산 |
필요한 라이브러리 설치
# 프로젝트에 필요한 라이브러리 설치
pip install pandas
# tkinter는 대부분의 Python 설치에 기본 포함되어 있습니다
classDiagram
class SystemCore {
+init_components()
+start_processing()
+handle_events()
}
class FileSystem {
+scan_directories()
+get_metadata()
+validate_paths()
}
class DataProcessor {
+process_folder_info()
+create_excel()
+validate_data()
}
class UserInterface {
+show_dialog()
+update_progress()
+display_results()
}
SystemCore --> FileSystem
SystemCore --> DataProcessor
SystemCore --> UserInterface
이렇게 구성된 기술 스택은 안정적이고 효율적인 시스템 구축을 가능하게 합니다. 특히 tkinter를 사용한 GUI는 가볍고 반응성이 좋아 사용자 경험을 크게 향상시킵니다.
핵심 기능 구현하기
이제 시스템의 핵심 기능들을 하나씩 구현해보겠습니다. 각 기능은 모듈화되어 있어 유지보수가 쉽고, 필요한 경우 확장도 가능합니다.
1. 폴더 선택 인터페이스
사용자가 쉽게 폴더를 선택할 수 있도록 직관적인 인터페이스를 구현합니다.
def select_folder():
"""
사용자 친화적인 폴더 선택 대화상자를 제공합니다.
Returns:
str: 선택된 폴더의 경로
"""
# tkinter 루트 윈도우 생성
root = tk.Tk()
root.withdraw() # 기본 tkinter 창 숨기기
# 폴더 선택 대화상자 표시
folder_path = filedialog.askdirectory(
title='폴더를 선택해주세요',
mustexist=True # 실제 존재하는 폴더만 선택 가능
)
return folder_path
2. 폴더 정보 수집기
선택된 폴더 내의 모든 정보를 효율적으로 수집하는 시스템입니다.
sequenceDiagram
participant User as 사용자
participant System as 시스템
participant FileSystem as 파일시스템
participant DataProcessor as 데이터처리기
User->>System: 폴더 선택
System->>FileSystem: 경로 탐색
FileSystem->>System: 폴더 목록 전달
System->>DataProcessor: 메타데이터 추출 요청
DataProcessor->>System: 처리된 데이터 반환
System->>User: 결과 표시
def collect_folder_info(path):
"""
지정된 경로의 모든 폴더 정보를 수집합니다.
Args:
path (str): 검색할 디렉토리 경로
Returns:
list: 폴더 정보 목록
"""
folder_info = []
# 지정된 경로의 모든 항목 순회
for item in os.listdir(path):
full_path = os.path.join(path, item)
# 폴더인 경우에만 정보 수집
if os.path.isdir(full_path):
# 생성 시간과 수정 시간 가져오기
created_time = datetime.fromtimestamp(os.path.getctime(full_path))
modified_time = datetime.fromtimestamp(os.path.getmtime(full_path))
# 폴더 정보 저장
folder_info.append({
'폴더명': item,
'전체 경로': full_path,
'생성일': created_time,
'수정일': modified_time
})
return folder_info
3. 데이터 정규화 엔진
수집된 데이터를 일관된 형식으로 변환하고 검증하는 정규화 엔진을 구현합니다. 이 과정에서 데이터의 품질을 보장하고 이후 처리 과정을 원활하게 만듭니다.
flowchart TD
A[원본 데이터] --> B[경로 정규화]
B --> C[날짜 형식 표준화]
C --> D[데이터 검증]
D --> E{검증 통과?}
E -->|Yes| F[정규화된 데이터]
E -->|No| G[오류 처리]
def normalize_folder_data(folder_info):
"""
폴더 정보를 정규화하고 검증합니다.
Args:
folder_info (dict): 원본 폴더 정보
Returns:
dict: 정규화된 폴더 정보
Raises:
ValueError: 데이터 형식이 잘못된 경우
"""
try:
normalized = folder_info.copy()
# 1. 경로 정규화 - Windows/Linux 경로 구분자 통일
normalized['전체 경로'] = os.path.normpath(normalized['전체 경로'])
# 2. 폴더명 정규화 - 앞뒤 공백 제거
normalized['폴더명'] = normalized['폴더명'].strip()
# 3. 날짜 형식 표준화
for date_field in ['생성일', '수정일']:
if isinstance(normalized[date_field], str):
try:
normalized[date_field] = datetime.strptime(
normalized[date_field],
'%Y-%m-%d %H:%M:%S'
)
except ValueError as e:
raise ValueError(f"잘못된 날짜 형식: {date_field}, {str(e)}")
# 4. 데이터 유효성 검증
if not all(key in normalized for key in ['폴더명', '전체 경로', '생성일', '수정일']):
raise ValueError("필수 필드가 누락되었습니다")
return normalized
except Exception as e:
raise ValueError(f"데이터 정규화 실패: {str(e)}")
정규화 엔진은 다음과 같은 주요 기능을 수행합니다:
| 기능 | 설명 | 중요도 |
|---|---|---|
| 경로 정규화 | 운영체제별 경로 구분자 통일 | 필수 |
| 날짜 표준화 | 다양한 형식의 날짜를 통일된 형식으로 변환 | 중요 |
| 데이터 검증 | 필수 필드 존재 여부 및 데이터 형식 확인 | 필수 |
| 오류 처리 | 데이터 처리 과정의 예외 상황 관리 | 중요 |
성능 최적화 전략
대규모 폴더 구조를 처리할 때는 성능 최적화가 필수적입니다. 메모리 사용량을 최소화하면서도 처리 속도를 최적화하는 방법을 살펴보겠습니다.
1. 메모리 효율적인 처리
flowchart TD
A[입력 데이터] --> B[청크 분할]
B --> C[메모리 할당]
C --> D[데이터 처리]
D --> E[메모리 해제]
E --> F[다음 청크]
F -.-> B
class MemoryEfficientProcessor:
def __init__(self, chunk_size=1000):
"""
메모리 효율적인 처리를 위한 초기화
Args:
chunk_size (int): 한 번에 처리할 폴더 수
"""
self.chunk_size = chunk_size
self.current_chunk = []
self.processed_count = 0
def process_folders(self, root_path):
"""
대용량 폴더 구조를 청크 단위로 처리
Args:
root_path (str): 처리할 루트 경로
"""
for folder_path, _, _ in os.walk(root_path):
folder_data = self._get_folder_metadata(folder_path)
self.current_chunk.append(folder_data)
# 청크 크기에 도달하면 처리
if len(self.current_chunk) >= self.chunk_size:
self._process_current_chunk()
def _process_current_chunk(self):
"""현재 청크 처리 및 메모리 정리"""
if not self.current_chunk:
return
# DataFrame 생성 및 처리
df_chunk = pd.DataFrame(self.current_chunk)
self._save_chunk_to_temp(df_chunk)
# 메모리 정리
self.processed_count += len(self.current_chunk)
self.current_chunk.clear()
2. 비동기 처리 시스템
사용자 인터페이스의 응답성을 높이기 위해 비동기 처리 시스템을 구현합니다.
sequenceDiagram
participant UI as 사용자 인터페이스
participant Scanner as 폴더 스캐너
participant Worker as 작업자 스레드
participant Storage as 저장소
UI->>Scanner: 폴더 스캔 요청
Scanner->>Worker: 비동기 작업 시작
Worker->>Storage: 청크 단위 처리
Storage-->>Worker: 저장 완료
Worker-->>Scanner: 진행상황 업데이트
Scanner-->>UI: UI 업데이트
async def scan_folders_async(root_path):
"""
폴더 구조를 비동기적으로 스캔
Args:
root_path (str): 스캔할 루트 경로
Returns:
list: 처리된 폴더 정보 목록
"""
async def process_single_folder(folder_path):
# 비동기로 폴더 정보 수집
stats = await aiopath.AsyncPath(folder_path).stat()
return {
'폴더명': os.path.basename(folder_path),
'전체 경로': folder_path,
'생성일': datetime.fromtimestamp(stats.st_ctime),
'수정일': datetime.fromtimestamp(stats.st_mtime)
}
tasks = []
# 비동기로 모든 폴더 처리
async for entry in aiofiles.os.walk(root_path):
if await aiopath.AsyncPath(entry).is_dir():
tasks.append(process_single_folder(entry))
return await asyncio.gather(*tasks)
보안 및 데이터 무결성
파일 시스템을 다루는 프로그램이기에, 보안과 데이터 무결성은 특히 중요합니다. 시스템 폴더 보호부터 사용자 데이터 보호까지, 종합적인 보안 시스템을 구현해보겠습니다.
1. 접근 제어 시스템
flowchart TD
A[접근 요청] --> B{시스템 폴더?}
B -->|Yes| C[접근 거부]
B -->|No| D{제한 경로?}
D -->|Yes| C
D -->|No| E{권한 확인}
E -->|부족| C
E -->|충분| F[접근 허용]
class SecurityManager:
def __init__(self):
"""보안 관리자 초기화"""
self.restricted_paths = set()
self.allowed_patterns = []
def add_restricted_path(self, path):
"""
접근 제한 경로 추가
Args:
path (str): 제한할 경로
"""
self.restricted_paths.add(os.path.normpath(path))
def is_safe_path(self, path):
"""
경로의 안전성 검증
Args:
path (str): 검사할 경로
Returns:
bool: 안전한 경로 여부
"""
normalized_path = os.path.normpath(path)
# 시스템 폴더 보호
system_paths = ['/sys', '/proc', '/etc', 'C:\\Windows']
if any(normalized_path.startswith(sys_path)
for sys_path in system_paths):
return False
# 제한된 경로 체크
return not any(
normalized_path.startswith(restricted)
for restricted in self.restricted_paths
)
2. 데이터 검증 시스템
데이터의 정확성과 일관성을 보장하기 위한 포괄적인 검증 시스템을 구현합니다.
| 검증 항목 | 검증 방법 | 처리 방식 |
|---|---|---|
| 경로 유효성 | 실제 존재하는 경로인지 확인 | os.path.exists() 사용 |
| 권한 검증 | 읽기/쓰기 권한 확인 | os.access() 사용 |
| 데이터 형식 | 필드 타입 및 형식 검증 | isinstance() 검사 |
| 무결성 검사 | 데이터 일관성 확인 | 체크섬 비교 |
class DataValidator:
def __init__(self):
"""데이터 검증 시스템 초기화"""
self.validation_rules = {}
self.error_logs = []
def validate_folder_data(self, folder_info):
"""
폴더 정보 검증
Args:
folder_info (dict): 검증할 폴더 정보
Returns:
bool: 검증 통과 여부
"""
try:
# 1. 필수 필드 검증
required_fields = {'폴더명', '전체 경로', '생성일', '수정일'}
if not all(field in folder_info for field in required_fields):
raise ValueError("필수 필드 누락")
# 2. 경로 유효성 검증
if not os.path.exists(folder_info['전체 경로']):
raise ValueError("유효하지 않은 경로")
# 3. 날짜 형식 검증
for date_field in ['생성일', '수정일']:
if not isinstance(folder_info[date_field], datetime):
raise ValueError(f"잘못된 날짜 형식: {date_field}")
return True
except Exception as e:
self.error_logs.append(str(e))
return False
사용자 인터페이스 구현
직관적이고 사용하기 쉬운 인터페이스는 프로그램의 성패를 좌우합니다. 사용자 경험을 최우선으로 고려한 인터페이스를 구현해보겠습니다.
classDiagram
class MainWindow {
+init_components()
+create_widgets()
+place_widgets()
+bind_events()
}
class EventHandler {
+handle_folder_select()
+handle_process_start()
+handle_process_complete()
}
class ProgressBar {
+update_progress()
+reset()
+show_status()
}
MainWindow --> EventHandler
MainWindow --> ProgressBar
class FolderManagerGUI:
def __init__(self):
"""GUI 초기화"""
self.root = tk.Tk()
self.root.title("폴더 관리 시스템")
self.setup_ui()
def setup_ui(self):
"""UI 구성요소 설정"""
# 메인 프레임
self.main_frame = ttk.Frame(self.root, padding="10")
self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 폴더 선택 버튼
self.select_btn = ttk.Button(
self.main_frame,
text="폴더 선택",
command=self.select_folder
)
self.select_btn.grid(row=0, column=0, pady=5)
# 진행바
self.progress = ttk.Progressbar(
self.main_frame,
orient=tk.HORIZONTAL,
length=300,
mode='determinate'
)
self.progress.grid(row=1, column=0, pady=5)
def select_folder(self):
"""폴더 선택 처리"""
folder_path = filedialog.askdirectory(
title='처리할 폴더 선택'
)
if folder_path:
self.start_processing(folder_path)
def start_processing(self, path):
"""폴더 처리 시작"""
self.progress['value'] = 0
# 처리 시작
try:
processor = FolderProcessor(path)
processor.process(
progress_callback=self.update_progress
)
except Exception as e:
messagebox.showerror("오류", str(e))
def update_progress(self, value):
"""진행 상황 업데이트"""
self.progress['value'] = value
self.root.update_idletasks()
이벤트 처리 시스템
사용자 인터페이스의 모든 동작을 부드럽게 처리하기 위한 이벤트 시스템을 구현합니다.
class EventHandler:
def __init__(self):
"""이벤트 처리 시스템 초기화"""
self.event_queue = Queue()
self.handlers = defaultdict(list)
self._running = True
def register_handler(self, event_type, handler):
"""
이벤트 핸들러 등록
Args:
event_type (str): 이벤트 유형
handler (callable): 처리할 함수
"""
self.handlers[event_type].append(handler)
def process_events(self):
"""이벤트 처리 루프"""
while self._running:
try:
event_type, data = self.event_queue.get(timeout=0.1)
self._process_event(event_type, data)
except Empty:
continue
def _process_event(self, event_type, data):
"""
개별 이벤트 처리
Args:
event_type (str): 이벤트 유형
data: 이벤트 데이터
"""
if event_type in self.handlers:
for handler in self.handlers[event_type]:
try:
handler(data)
except Exception as e:
logging.error(f"이벤트 처리 오류: {str(e)}")
실전 활용 가이드
이제 우리가 만든 시스템을 실제 환경에서 어떻게 활용할 수 있는지 살펴보겠습니다. 특히 대규모 프로젝트나 기업 환경에서의 실전 사용 사례를 중심으로 설명하겠습니다.
1. 프로젝트 구조 분석
class ProjectAnalyzer:
def __init__(self):
"""프로젝트 구조 분석기 초기화"""
self.analysis_results = {}
self.patterns = set()
def analyze_structure(self, root_path):
"""
프로젝트 구조 분석 수행
Args:
root_path (str): 분석할 프로젝트 루트 경로
Returns:
dict: 분석 결과
"""
try:
structure_metrics = {
'depth_analysis': self._analyze_depth(root_path),
'naming_patterns': self._analyze_naming(root_path),
'modification_timeline': self._create_timeline(root_path)
}
return structure_metrics
except Exception as e:
logging.error(f"구조 분석 중 오류 발생: {str(e)}")
raise
def _analyze_depth(self, path, current_depth=0):
"""
폴더 깊이 분석
Args:
path (str): 분석할 경로
current_depth (int): 현재 깊이
Returns:
dict: 깊이 분석 결과
"""
if current_depth > 50: # 무한 순환 방지
return {'max_depth': current_depth}
depths = [current_depth]
for item in os.scandir(path):
if item.is_dir():
sub_analysis = self._analyze_depth(item.path, current_depth + 1)
depths.append(sub_analysis['max_depth'])
return {
'max_depth': max(depths),
'avg_depth': sum(depths) / len(depths)
}
graph TD
A[프로젝트 루트] --> B[소스 코드]
A --> C[리소스]
A --> D[문서]
B --> E[모듈1]
B --> F[모듈2]
C --> G[이미지]
C --> H[데이터]
D --> I[API 문서]
D --> J[사용자 가이드]
style A fill:#f9f,stroke:#333,stroke-width:2px
style B fill:#bbf,stroke:#333,stroke-width:2px
style C fill:#bfb,stroke:#333,stroke-width:2px
style D fill:#fbf,stroke:#333,stroke-width:2px
| 분석 지표 | 의미 | 적정 범위 | 주의사항 |
|---|---|---|---|
| 최대 깊이 | 가장 깊은 폴더 레벨 | 3-7 레벨 | 너무 깊은 구조는 피하기 |
| 평균 깊이 | 전체 폴더의 평균 깊이 | 2-4 레벨 | 일관된 깊이 유지 |
| 폴더당 항목 수 | 각 폴더의 하위 항목 수 | 5-15개 | 과도한 항목은 분할 고려 |
| 이름 일관성 | 폴더 명명 규칙 준수도 | 90% 이상 | 명확한 규칙 수립 필요 |
시스템 최적화 및 향후 발전 방향
이 시스템의 실용성과 확장성을 더욱 높이기 위한 향후 발전 방향을 살펴보겠습니다.
gantt
title 시스템 확장 계획
dateFormat YYYY-MM-DD
section 기능 확장
원격 저장소 지원 :2024-01-01, 30d
클라우드 연동 :2024-02-01, 45d
section 성능 개선
분산 처리 구현 :2024-03-15, 60d
실시간 동기화 :2024-05-15, 45d
section 보안 강화
암호화 구현 :2024-07-01, 30d
접근 제어 개선 :2024-08-01, 45d
| 개선 영역 | 세부 내용 | 우선순위 | 구현 복잡도 |
|---|---|---|---|
| 원격 저장소 지원 | FTP, WebDAV 프로토콜 통합 | 높음 | 중간 |
| 클라우드 연동 | 주요 클라우드 서비스 API 통합 | 중간 | 높음 |
| 분산 처리 | 대규모 폴더 구조의 병렬 처리 | 높음 | 매우 높음 |
| 실시간 동기화 | 변경 사항 자동 감지 및 반영 | 중간 | 높음 |
class SystemOptimizer:
def __init__(self):
"""시스템 성능 최적화 초기화"""
self.cache = LRUCache(maxsize=1000)
self.performance_metrics = defaultdict(list)
def optimize_scanning(self, folder_path):
"""
폴더 스캔 최적화
Args:
folder_path (str): 스캔할 폴더 경로
Returns:
dict: 최적화된 스캔 결과
"""
# 캐시된 결과 확인
if folder_path in self.cache:
return self.cache[folder_path]
# 병렬 처리를 위한 작업 분할
with ThreadPoolExecutor() as executor:
chunks = self._split_into_chunks(folder_path)
results = list(executor.map(self._scan_chunk, chunks))
# 결과 통합
combined_results = self._merge_results(results)
self.cache[folder_path] = combined_results
return combined_results
이렇게 구현된 폴더 관리 시스템은 단순한 폴더 목록화 도구를 넘어, 프로젝트 관리와 시스템 분석을 위한 강력한 도구로 활용될 수 있습니다. 지속적인 개선과 사용자 피드백을 통해 더욱 실용적인 도구로 발전시켜 나갈 수 있을 것입니다.
전체코드
import os
from datetime import datetime
import pandas as pd
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from collections import defaultdict
from queue import Queue, Empty
import asyncio
import logging
from concurrent.futures import ThreadPoolExecutor
from threading import Thread
class LRUCache:
"""최근 사용된 항목을 캐싱하는 클래스"""
def __init__(self, maxsize=1000):
self.maxsize = maxsize
self.cache = {}
self.usage = []
def __contains__(self, key):
return key in self.cache
def __getitem__(self, key):
if key in self.cache:
self.usage.remove(key)
self.usage.append(key)
return self.cache[key]
raise KeyError(key)
def __setitem__(self, key, value):
if key in self.cache:
self.usage.remove(key)
elif len(self.cache) >= self.maxsize:
oldest = self.usage[0]
del self.cache[oldest]
self.usage.pop(0)
self.cache[key] = value
self.usage.append(key)
class SecurityManager:
"""보안 관리 시스템"""
def __init__(self):
self.restricted_paths = set()
self.allowed_patterns = []
def add_restricted_path(self, path):
"""제한된 경로 추가"""
self.restricted_paths.add(os.path.normpath(path))
def is_safe_path(self, path):
"""경로의 안전성 검증"""
normalized_path = os.path.normpath(path)
# 시스템 폴더 보호
system_paths = ['/sys', '/proc', '/etc', 'C:\\Windows']
if any(normalized_path.startswith(sys_path)
for sys_path in system_paths):
return False
return not any(
normalized_path.startswith(restricted)
for restricted in self.restricted_paths
)
class DataValidator:
"""데이터 검증 시스템"""
def __init__(self):
self.validation_rules = {}
self.error_logs = []
def validate_folder_data(self, folder_info):
"""폴더 정보 검증"""
try:
required_fields = {'폴더명', '전체 경로', '생성일', '수정일'}
if not all(field in folder_info for field in required_fields):
raise ValueError("필수 필드 누락")
if not os.path.exists(folder_info['전체 경로']):
raise ValueError("유효하지 않은 경로")
for date_field in ['생성일', '수정일']:
if not isinstance(folder_info[date_field], datetime):
raise ValueError(f"잘못된 날짜 형식: {date_field}")
return True
except Exception as e:
self.error_logs.append(str(e))
return False
class EventHandler:
"""이벤트 처리 시스템"""
def __init__(self):
self.event_queue = Queue()
self.handlers = defaultdict(list)
self._running = True
def register_handler(self, event_type, handler):
"""이벤트 핸들러 등록"""
self.handlers[event_type].append(handler)
def emit_event(self, event_type, data=None):
"""이벤트 발생"""
self.event_queue.put((event_type, data))
def process_events(self):
"""이벤트 처리 루프"""
while self._running:
try:
event_type, data = self.event_queue.get(timeout=0.1)
self._process_event(event_type, data)
except Empty:
continue
def _process_event(self, event_type, data):
"""개별 이벤트 처리"""
if event_type in self.handlers:
for handler in self.handlers[event_type]:
try:
handler(data)
except Exception as e:
logging.error(f"이벤트 처리 오류: {str(e)}")
class ProgressMonitor:
"""진행 상황 모니터링"""
def __init__(self):
self.total_items = 0
self.processed_items = 0
self.start_time = None
self.update_callbacks = []
def start_monitoring(self, total_items):
"""모니터링 시작"""
self.total_items = total_items
self.processed_items = 0
self.start_time = datetime.now()
def update_progress(self, completed_items):
"""진행 상황 업데이트"""
self.processed_items = completed_items
progress = (completed_items / self.total_items) * 100
for callback in self.update_callbacks:
callback(progress)
class FolderProcessor:
"""폴더 처리 시스템"""
def __init__(self, security_manager=None, data_validator=None):
self.security_manager = security_manager or SecurityManager()
self.data_validator = data_validator or DataValidator()
self.progress_monitor = ProgressMonitor()
def process_folder(self, folder_path, callback=None):
"""폴더 처리 메인 함수"""
try:
if not self.security_manager.is_safe_path(folder_path):
raise ValueError("접근이 제한된 경로입니다")
folder_info = self._collect_folder_info(folder_path)
if not self.data_validator.validate_folder_data(folder_info):
raise ValueError("데이터 검증 실패")
if callback:
callback(folder_info)
return folder_info
except Exception as e:
logging.error(f"폴더 처리 중 오류: {str(e)}")
raise
def _collect_folder_info(self, path):
"""폴더 정보 수집"""
return {
'폴더명': os.path.basename(path),
'전체 경로': path,
'생성일': datetime.fromtimestamp(os.path.getctime(path)),
'수정일': datetime.fromtimestamp(os.path.getmtime(path))
}
class FolderManagerGUI:
"""GUI 클래스"""
def __init__(self):
self.root = tk.Tk()
self.root.title("폴더 관리 시스템")
self.processor = FolderProcessor()
self.setup_ui()
def setup_ui(self):
"""UI 설정"""
self.main_frame = ttk.Frame(self.root, padding="10")
self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 폴더 선택 버튼
self.select_btn = ttk.Button(
self.main_frame,
text="폴더 선택",
command=self.select_folder
)
self.select_btn.grid(row=0, column=0, pady=5)
# 진행바
self.progress = ttk.Progressbar(
self.main_frame,
orient=tk.HORIZONTAL,
length=300,
mode='determinate'
)
self.progress.grid(row=1, column=0, pady=5)
def select_folder(self):
"""폴더 선택 처리"""
folder_path = filedialog.askdirectory(
title='처리할 폴더 선택'
)
if folder_path:
self.start_processing(folder_path)
def start_processing(self, path):
"""처리 시작"""
self.progress['value'] = 0
try:
folder_info = self.processor.process_folder(
path,
callback=self.update_progress
)
self.save_to_excel(folder_info)
except Exception as e:
messagebox.showerror("오류", str(e))
def update_progress(self, value):
"""진행 상황 업데이트"""
self.progress['value'] = value
self.root.update_idletasks()
def save_to_excel(self, folder_info):
"""엑셀 파일로 저장"""
try:
df = pd.DataFrame([folder_info])
current_time = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f'폴더정보_{current_time}.xlsx'
df.to_excel(filename, index=False)
messagebox.showinfo("완료", f"파일이 저장되었습니다: {filename}")
except Exception as e:
messagebox.showerror("저장 오류", str(e))
def main():
"""메인 함수"""
app = FolderManagerGUI()
app.root.mainloop()
if __name__ == "__main__":
main()