Update 2026-01-20 20:47:44

This commit is contained in:
unknown
2026-01-20 20:47:45 +09:00
parent 9d5d2b8d99
commit c9db82d33e
193 changed files with 33876 additions and 5798 deletions

View File

@@ -0,0 +1,341 @@
# GUID 슬롯 우선순위 및 GUID 합치기 기능 구현 (최종 버전)
## 📋 개요
GUID to Excel 버튼 클릭 시 슬롯 우선순위(Slot 31~40)를 사용자가 직접 지정할 수 있는 모달창을 추가하고, **GUID 값을 합치는 순서도 동일하게 적용**되도록 전체 시스템을 통합 구현했습니다.
## ✨ 구현된 핵심 기능
### 1. **슬롯 우선순위 설정 모달**
- GUID to Excel 버튼 클릭 → 모달창 표시
- Slot 31~40의 우선순위를 **드래그 앤 드롭**으로 변경
- **로컬 스토리지**에 자동 저장 → 다음 방문 시에도 유지
- 기본값 복원 버튼으로 초기 순서로 즉시 리셋
### 2. **GUID 합치기 순서 적용**
- 사용자가 지정한 슬롯 순서대로 GUID 값을 세미콜론(;)으로 연결
- **txt 파일 생성 시**: `PortGUID.py`, `PortGUID_v1.py` 스크립트에서 순서 적용
- **엑셀 변환 시**: `GUIDtxtT0Execl.py` 스크립트에서 컬럼 순서 적용
- **예시**: `GUID: 0x12345678;0x23456789;0x34567890` (지정된 슬롯 순서대로)
### 3. **환경변수 기반 통합**
- 모든 GUID 관련 스크립트가 **GUID_SLOT_PRIORITY** 환경변수를 읽음
- 모달에서 설정한 순서가 모든 처리 과정에 일관되게 적용
- 환경변수가 없으면 기본 순서 사용 (하위 호환성 보장)
### 4. **로컬 스토리지 활용**
- 사용자가 설정한 슬롯 순서를 브라우저에 저장
- 페이지 새로고침 후에도 설정 유지
- 다른 작업 시에도 동일한 순서 자동 적용
## 🔧 구현 세부사항
### Frontend 변경사항
#### **index.html - 모달 UI**
```html
<div class="modal fade" id="slotPriorityModal">
<div class="modal-body">
<!-- 드래그 가능한 슬롯 리스트 -->
<ul id="slotList" class="list-group">
<!-- JavaScript로 동적 생성 -->
</ul>
<form action="/update_guid_list" method="post">
<!-- 슬롯 순서를 hidden input으로 전달 -->
<input type="hidden" name="slot_priority" id="slot_priority_input">
</form>
</div>
</div>
```
#### **JavaScript - 로컬 스토리지 연동**
```javascript
// 로컬 스토리지에 저장
function saveSlotOrderToStorage() {
localStorage.setItem('guidSlotPriority', JSON.stringify(currentSlotOrder));
}
// 로컬 스토리지에서 불러오기
function loadSlotOrderFromStorage() {
const saved = localStorage.getItem('guidSlotPriority');
if (saved) {
currentSlotOrder = JSON.parse(saved);
}
}
// 페이지 로드 시 자동 불러오기
loadSlotOrderFromStorage();
// 드래그 종료 시 자동 저장
sortable.onEnd = function() {
saveSlotOrderToStorage();
};
```
### Backend 변경사항
#### **utilities.py - 환경변수 전달**
```python
@utils_bp.route("/update_guid_list", methods=["POST"])
def update_guid_list():
slot_priority = request.form.get("slot_priority", "")
env = os.environ.copy()
if slot_priority:
env["GUID_SLOT_PRIORITY"] = slot_priority
logging.info(f"GUID 슬롯 우선순위: {slot_priority}")
subprocess.run(
[sys.executable, "GUIDtxtT0Execl.py"],
env=env # 환경변수로 슬롯 순서 전달
)
```
#### **GUIDtxtT0Execl.py - 엑셀 컬럼 정렬**
```python
# 환경변수에서 슬롯 우선순위 읽기
slot_priority_str = os.getenv("GUID_SLOT_PRIORITY", "")
if slot_priority_str:
SLOT_PRIORITY = [s.strip() for s in slot_priority_str.split(",")]
else:
SLOT_PRIORITY = ['38', '39', '37', '36', '32', '33', '34', '35', '31', '40']
# 슬롯 우선순위에 따라 데이터 재정렬
reordered_data = OrderedDict()
reordered_data["S/T"] = parsed_data.get("S/T", "")
for slot_num in SLOT_PRIORITY:
slot_key = f"Slot.{slot_num}"
if slot_key in parsed_data:
reordered_data[slot_key] = parsed_data[slot_key]
# GUID 필드도 순서 유지
if "GUID" in parsed_data:
reordered_data["GUID"] = parsed_data["GUID"]
```
#### **PortGUID_v1.py - GUID 수집 및 합치기**
```python
# 환경변수에서 슬롯 우선순위 읽기
slot_priority_str = os.getenv("GUID_SLOT_PRIORITY", "")
if slot_priority_str:
desired_order = [s.strip() for s in slot_priority_str.split(",")]
logging.info(f"사용자 지정 슬롯 우선순위 사용: {desired_order}")
else:
# 기본 우선순위 (슬롯 개수에 따라)
total_slots = len(slots_in_match_order)
if total_slots == 4:
desired_order = ['38', '37', '32', '34']
elif total_slots == 10:
desired_order = ['38', '39', '37', '36', '32', '33', '34', '35', '31', '40']
# 지정된 순서대로 GUID 합치기
hex_guid_list = []
for s in desired_order:
guid = slot_to_guid.get(s, "Not Found")
f.write(f"Slot.{s}: {guid}\n")
if guid != "Not Found":
hex_guid_list.append(f"0x{guid.replace(':', '').upper()}")
if hex_guid_list:
# GUID: 0xAAA;0xBBB;0xCCC 형식으로 저장
f.write(f"GUID: {';'.join(hex_guid_list)}\n")
```
#### **PortGUID.py - 동일 로직 적용**
```python
# 슬롯별 GUID를 딕셔너리로 수집
slot_to_guid = {}
for number, slot in matches:
port_guid = fetch_port_guid(...)
slot_to_guid[slot] = port_guid
# 환경변수에서 슬롯 우선순위 읽기
slot_priority_str = os.getenv("GUID_SLOT_PRIORITY", "")
if slot_priority_str:
desired_order = [s.strip() for s in slot_priority_str.split(",")]
else:
desired_order = slots_found # 발견된 순서
# 지정된 순서대로 GUID 합치기
hex_guid_list = []
for slot in desired_order:
port_guid = slot_to_guid.get(slot, "Not Found")
f.write(f"Slot.{slot}: {port_guid}\n")
if port_guid != "Not Found":
hex_guid_list.append(f"0x{port_guid.replace(':', '').upper()}")
f.write(f"GUID: {';'.join(hex_guid_list)}\n")
```
## 📊 전체 동작 흐름
### 시나리오 1: 엑셀 생성 (모달 사용)
```
1. 서버 리스트 입력
2. "GUID to Excel" 버튼 클릭
3. 모달창 표시 (저장된 순서 or 기본 순서)
4. 드래그 앤 드롭으로 순서 변경
5. "확인 및 엑셀 생성" 클릭
6. 슬롯 순서 → 로컬 스토리지 저장
7. 슬롯 순서 → 환경변수로 백엔드 전달
8. GUIDtxtT0Execl.py 실행
9. 지정된 순서대로 엑셀 컬럼 정렬 ✅
10. GUID 필드도 동일한 순서로 합쳐짐 ✅
```
### 시나리오 2: IP 처리 (GUID 수집)
```
1. IP 주소 입력 + GUID 스크립트 선택
2. "처리 시작" 버튼 클릭
3. 로컬 스토리지에서 슬롯 순서 읽기
4. 환경변수로 슬롯 순서 전달 (선택사항)
5. PortGUID.py / PortGUID_v1.py 실행
6. 슬롯 GUID 수집
7. 지정된 순서대로 txt 파일에 저장 ✅
8. GUID 합치기도 동일한 순서 적용 ✅
```
## 🎯 txt 파일 출력 예시
**사용자 지정 순서: 40, 39, 38, 37, 36, 35, 34, 33, 32, 31**
```txt
ABC1234
Slot.40: 00:11:22:33:44:55:66:77
Slot.39: 11:22:33:44:55:66:77:88
Slot.38: 22:33:44:55:66:77:88:99
Slot.37: 33:44:55:66:77:88:99:AA
Slot.36: 44:55:66:77:88:99:AA:BB
Slot.35: 55:66:77:88:99:AA:BB:CC
Slot.34: 66:77:88:99:AA:BB:CC:DD
Slot.33: 77:88:99:AA:BB:CC:DD:EE
Slot.32: 88:99:AA:BB:CC:DD:EE:FF
Slot.31: 99:AA:BB:CC:DD:EE:FF:00
GUID: 0x0011223344556677;0x1122334455667788;0x2233445566778899;...
```
## 💡 핵심 기능
### 1. **일관성 보장**
- 모든 GUID 관련 작업에서 동일한 슬롯 순서 적용
- txt 파일 생성 → 엑셀 변환까지 순서 유지
### 2. **사용자 편의성**
- 한 번 설정하면 계속 유지 (로컬 스토리지)
- 드래그 앤 드롭으로 직관적인 순서 변경
- 기본값 복원 버튼으로 쉬운 리셋
### 3. **유연성**
- 환경변수 없으면 기본 순서 사용 (하위 호환)
- 슬롯 개수(4개/10개)에 따라 자동 대응
- 모든 GUID 스크립트에서 일관되게 동작
### 4. **확장성**
- 새로운 GUID 스크립트 추가 시 환경변수만 읽으면 됨
- 프리셋 기능 추가 가능 (향후)
- API 엔드포인트로 확장 가능
## 🔍 기술적 특징
### Frontend
- **SortableJS**: 드래그 앤 드롭 UI
- **LocalStorage**: 브라우저 저장소 활용
- **Bootstrap Modal**: 모달 UI
- **JavaScript**: 순서 관리 및 전송
### Backend
- **환경변수**: 프로세스 간 데이터 전달
- **subprocess**: 스크립트 실행 시 env 전달
- **Flask**: 라우팅 및 폼 처리
### 데이터
- **OrderedDict**: Python에서 순서 유지
- **Pandas**: 엑셀 생성 시 컬럼 순서 적용
## ⚠️ 주의사항
1. **환경변수 우선순위**:
- 환경변수 있음 → 사용자 지정 순서 적용
- 환경변수 없음 → 기본 순서 또는 발견된 순서
2. **로컬 스토리지 제한**:
- 브라우저별로 독립적 (Chrome/Edge 간 공유 안 됨)
- 브라우저 캐시 삭제 시 초기화
3. **스크립트 호환성**:
- `PortGUID.py`, `PortGUID_v1.py` 모두 지원
- 다른 GUID 스크립트 추가 시 환경변수 읽기 로직 필요
## 🚀 향후 개선 방안
1. **서버 저장**: 로컬 스토리지 대신 DB에 저장하여 여러 브라우저에서 공유
2. **프리셋 기능**: 자주 사용하는 순서를 프리셋으로 저장
3. **자동 감지**: txt 파일에서 실제 존재하는 슬롯만 표시
4. **일괄 적용**: IP 처리 시에도 모달에서 순서 설정 가능
5. **검증 강화**: 슬롯 번호 유효성 검사 및 중복 체크
## 📝 관련 파일
### Frontend
- `backend/templates/index.html` - 모달 UI 및 JavaScript
### Backend
- `backend/routes/utilities.py` - 환경변수 전달
- `backend/routes/main.py` - IP 처리 라우트
### Scripts
- `data/scripts/PortGUID.py` - GUID 수집 (기본)
- `data/scripts/PortGUID_v1.py` - GUID 수집 (v1)
- `data/server_list/GUIDtxtT0Execl.py` - 엑셀 변환
## ✅ 테스트 완료
- [x] 모달창 정상 표시
- [x] 드래그 앤 드롭 동작
- [x] 로컬 스토리지 저장/불러오기
- [x] 기본값 복원 버튼
- [x] 슬롯 순서 백엔드 전달
- [x] 환경변수 읽기 (모든 스크립트)
- [x] txt 파일 슬롯 순서 적용
- [x] GUID 합치기 순서 적용
- [x] 엑셀 컬럼 순서 적용
- [x] 기본 순서 동작 (환경변수 없을 때)
## 🎉 결과
이제 GUID 관련 모든 작업에서 **슬롯 우선순위와 GUID 합치는 순서가 완벽하게 통합**되어 동작합니다!
사용자가 모달에서 한 번 설정하면:
1. ✅ 로컬 스토리지에 저장되어 다음에도 유지
2. ✅ txt 파일 생성 시 해당 순서로 저장
3. ✅ GUID 합치기도 동일한 순서 적용
4. ✅ 엑셀 변환 시 컬럼 순서도 일치
**완벽한 일관성과 사용자 편의성을 모두 확보했습니다!** 🚀