# 6. 핵심 기능 상세 (Core Features) > **문서 버전**: 1.0 > **최종 업데이트**: 2025-11-15 --- ## 6.1 PSD 포스터 자동 생성 ### 6.1.1 기능 개요 템플릿 PSD 파일과 머신 데이터를 결합하여 맞춤형 포스터를 자동으로 생성합니다. **주요 프로세스**: 1. 사용자 입력 (방향, 로고타입, 머신 ID) 2. 템플릿 선택 3. 템플릿 PSD 로드 4. 머신 이미지 배치 5. 텍스트 레이어 교체 6. PSD 저장 --- ### 6.1.2 템플릿 선택 메커니즘 시스템은 사용자 입력에 따라 적절한 템플릿을 자동으로 선택합니다. **선택 기준**: - 방향 (orientation): `vertical` 또는 `horizontal` - 로고타입 (logotype): `grandOpen`, `renewalOpen` 등 - 머신 수: 입력된 머신 ID 개수 **템플릿 경로 구성**: ``` /data/psd_template/{orientation}/{logotype}/machine_{count}/m{count}/s0/{uuid}/{uuid}.psd ``` **예시**: - 입력: `orientation=vertical`, `logotype=grandOpen`, `machineIds="1,107"` - 경로: `/data/psd_template/vertical/grandOpen/machine_2/m2/s0/.../uuid.psd` --- ### 6.1.3 이미지 배치 프로세스 머신 이미지를 템플릿의 플레이스홀더 레이어에 배치합니다. **단계**: 1. **레이어 탐색** - 패턴: `machine_{order}` (예: `machine_1`, `machine_2`) - 스마트 오브젝트 레이어 식별 2. **이미지 로드** - 경로: `/data/machine/{machineId}/main.png` - 이미지 검증 (형식, 크기) 3. **스마트 오브젝트 교체** - 기존 스마트 오브젝트 내용 교체 - 또는 임베디드 스마트 오브젝트로 변환 4. **크기 조정** - 플레이스홀더 크기에 맞게 자동 조정 - 비율 유지 --- ### 6.1.4 스마트 오브젝트 처리 템플릿의 링크된 스마트 오브젝트를 임베디드 형식으로 변환하여 이식성을 보장합니다. **변환 프로세스**: ```powershell # 스마트 오브젝트 레이어 감지 $smartObjectLayer = $psd.Layers | Where-Object { $_.IsSmartObject } # 임베디드로 변환 $smartObjectLayer.ConvertToEmbedded() # 내용 교체 $smartObjectLayer.ReplaceContents($newImagePath) ``` **장점**: - PSD 파일 이동 시 링크 깨짐 방지 - 외부 의존성 제거 - 파일 자체 완결성 --- ## 6.2 머신 이름 레이어 자동 교체 ### 6.2.1 기능 개요 및 배경 템플릿의 머신 이름 텍스트 레이어를 사전 렌더링된 PNG 이미지로 자동 교체하여 다음 문제를 해결합니다: **해결하는 문제**: - 폰트 설치 의존성 제거 - 크로스 플랫폼 텍스트 렌더링 일관성 - 디자인 품질 보장 **동작**: - 템플릿의 텍스트 레이어 → 사전 렌더링 PNG 이미지로 대체 - 각 머신의 `machine-text/` 디렉토리에서 이미지 로드 - 원본 레이어 위치 및 크기 상속 --- ### 6.2.2 동작 원리 ``` 1. 템플릿 메타데이터 JSON 읽기 └─> {uuid}.json → "machine_name_image": "gtwcs.png" 2. 머신별 이미지 파일 복사 └─> /data/machine/107/machine-text/gtwcs.png → /data/working/.../machine-text/107/gtwcs.png 3. 텍스트 레이어 탐색 └─> "machine-name_g01 #1", "machine-name_g02 #1" 패턴 검색 4. 레이어 속성 추출 └─> 위치 (Left, Top), 크기 (Width, Height) 5. 이미지 스케일 계산 └─> Fit-to-bounds + 중앙 정렬 6. 텍스트 레이어 삭제 및 이미지 레이어 삽입 └─> 래스터 레이어로 PNG 삽입 7. PSD 저장 ``` --- ### 6.2.3 이미지-레이어 매핑 전략 #### 레이어 명명 규칙 템플릿 내 머신 이름 텍스트 레이어는 다음 패턴을 따릅니다: **패턴**: `machine-name_g{order} #1` **예시**: - 1번 머신: `machine-name_g01 #1` - 2번 머신: `machine-name_g02 #1` - 3번 머신: `machine-name_g03 #1` #### 레이어 탐색 알고리즘 ```powershell function Find-MachineNameLayer { param( $psdDocument, $machineOrder # 1, 2, 3... ) $pattern = "machine-name_g{0:D2} #1" -f $machineOrder $layer = $psdDocument.Layers | Where-Object { $_.Name -eq $pattern } return $layer } ``` --- ### 6.2.4 JSON 메타데이터 활용 #### 메타데이터 파일 위치 템플릿 PSD와 동일한 디렉토리: ``` /data/psd_template/vertical/grandOpen/.../uuid/ ├── uuid.psd └── uuid.json ``` #### JSON 스키마 ```json { "machine_name_image": "gtwcs.png" } ``` #### 동작 시나리오 **시나리오 1: JSON 파일 존재** ``` 1. JSON 파일 읽기 2. "machine_name_image" 필드 추출 3. 해당 파일명 사용 ``` **시나리오 2: JSON 파일 없음** ``` 1. 경고 로그 출력 2. 기본값 "gtwcs.png" 사용 3. Working directory에 JSON 파일 자동 생성 ``` **로그 예시**: ``` [WARN] Template metadata JSON not found: /data/psd_template/.../uuid.json [INFO] Using default machine name image: gtwcs.png [INFO] Auto-created template metadata JSON in working directory ``` --- ### 6.2.5 이미지 스케일링 알고리즘 #### Fit-to-bounds 방식 이미지를 텍스트 레이어 영역에 완전히 맞추되, 비율을 유지합니다. **알고리즘**: ```powershell function Get-ScaledImageDimensions { param( $imageWidth, # 원본 이미지 너비 $imageHeight, # 원본 이미지 높이 $boundWidth, # 텍스트 레이어 너비 $boundHeight # 텍스트 레이어 높이 ) # 가로/세로 비율 계산 $scaleX = $boundWidth / $imageWidth $scaleY = $boundHeight / $imageHeight # 더 작은 스케일 선택 (전체가 들어가도록) $scale = [Math]::Min($scaleX, $scaleY) # 스케일된 크기 계산 $newWidth = [int]($imageWidth * $scale) $newHeight = [int]($imageHeight * $scale) # 중앙 정렬 오프셋 계산 $offsetX = [int](($boundWidth - $newWidth) / 2) $offsetY = [int](($boundHeight - $newHeight) / 2) return @{ Width = $newWidth Height = $newHeight OffsetX = $offsetX OffsetY = $offsetY Scale = $scale } } ``` #### 중앙 정렬 스케일된 이미지를 텍스트 레이어 영역의 중앙에 배치합니다. ``` ┌─────────────────────────────┐ │ 텍스트 레이어 영역 │ │ │ │ ┌─────────────┐ │ │ │ 이미지 │ │ ← 중앙 정렬 │ └─────────────┘ │ │ │ └─────────────────────────────┘ ``` #### Lanczos 리샘플링 고품질 이미지 스케일링을 위해 Lanczos 알고리즘 사용: ```powershell $resamplingMethod = [Aspose.PSD.ResamplingMethod]::Lanczos3 $image.Resize($newWidth, $newHeight, $resamplingMethod) ``` --- ### 6.2.6 Edge Cases 처리 #### Case 1: 이미지 파일 누락 **상황**: `/data/machine/107/machine-text/gtwcs.png` 파일 없음 **동작**: ``` 1. 경고 로그 출력 2. 해당 머신의 레이어 교체 건너뛰기 3. 다른 머신 계속 처리 4. JSON 출력에 "skipped_image_not_found" 상태 기록 ``` **로그**: ``` [WARN] Machine name image not found: /data/machine/107/machine-text/gtwcs.png [INFO] Skipping machine name layer replacement for machine 107 ``` --- #### Case 2: 레이어 미존재 **상황**: 템플릿에 `machine-name_g01 #1` 레이어 없음 **동작**: ``` 1. 경고 로그 출력 2. 레이어 교체 건너뛰기 3. 포스터 생성 계속 진행 ``` --- #### Case 3: 크기 불일치 (극단적) **상황**: 이미지 크기가 텍스트 레이어보다 2배 이상 크거나 0.5배 이하 **동작**: ``` 1. 경고 로그 출력 2. 스케일링 진행 3. 품질 확인 필요 메시지 ``` **로그**: ``` [WARN] Extreme scaling detected: scale factor = 3.2x [WARN] Please verify the output quality ``` --- ## 6.3 JSON 출력 모드 ### 6.3.1 Success Response 스키마 ```json { "status": "success", "result": { "psdPath": "/data/working/20250115143022-uuid/file.psd", "workingDirectory": "/data/working/20250115143022-uuid", "templateUuid": "36cc0517-bc80-43b7-9ff6-bd947b2136e7", "machineIds": [1, 107, 205], "startTime": "2025-01-15 14:30:22", "endTime": "2025-01-15 14:30:45", "duration": 23.5 } } ``` --- ### 6.3.2 Error Response 스키마 ```json { "status": "error", "error": { "message": "Template not found", "type": "TemplateNotFoundException", "stackTrace": "at Select-Template() line 142...", "timestamp": "2025-01-15 14:30:45", "duration": 1.2, "workingDirectory": "/data/working/20250115143022-uuid" } } ``` --- ### 6.3.3 확장 필드 #### machine_name_layer_replacements ```json "machine_name_layer_replacements": [ { "machineId": 107, "layerName": "machine-name_g01 #1", "imagePath": "/data/working/.../machine-text/107/gtwcs.png", "status": "success", "scaleFactor": 1.2 }, { "machineId": 205, "layerName": "machine-name_g02 #1", "imagePath": "/data/working/.../machine-text/205/gtwcs.png", "status": "skipped_image_not_found" } ] ``` #### template_metadata ```json "template_metadata": { "path": "/data/working/.../template.json", "imageFilename": "gtwcs.png", "autoCreated": false } ``` --- ## 다음 단계 - **[7. API 레퍼런스](doc_7_api_reference.md)**: 함수 상세 레퍼런스 - **[10. 데이터 스키마](doc_10_data_schema.md)**: JSON 스키마 상세 --- **[← 목차로 돌아가기](doc_index.md)**