From e86b7869b9e14abea3f293f12a32c4b235f7e6a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 26 Feb 2026 20:13:26 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20[hr]=20=EC=82=AC=EC=9B=90=20?= =?UTF-8?q?=EC=B2=A8=EB=B6=80=ED=8C=8C=EC=9D=BC=EC=9D=84=20GCS=20=EB=93=80?= =?UTF-8?q?=EC=96=BC=20=EC=A0=80=EC=9E=A5=20=EB=B0=A9=EC=8B=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 업로드: 로컬 + GCS 동시 저장 (gcs_object_name, gcs_uri 기록) - 다운로드: GCS Signed URL 우선, 로컬 폴백 - 삭제: GCS + 로컬 모두 삭제, soft delete 처리 - DashboardCalendarController 패턴 준용 --- .../Api/Admin/HR/EmployeeController.php | 61 ++++++++++++++----- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Api/Admin/HR/EmployeeController.php b/app/Http/Controllers/Api/Admin/HR/EmployeeController.php index b1f22c13..b625f122 100644 --- a/app/Http/Controllers/Api/Admin/HR/EmployeeController.php +++ b/app/Http/Controllers/Api/Admin/HR/EmployeeController.php @@ -4,6 +4,7 @@ use App\Http\Controllers\Controller; use App\Models\Boards\File; +use App\Services\GoogleCloudStorageService; use App\Services\HR\EmployeeService; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -256,9 +257,9 @@ public function destroy(Request $request, int $id): JsonResponse|Response } /** - * 사원 첨부파일 업로드 + * 사원 첨부파일 업로드 (로컬 + GCS 듀얼 저장) */ - public function uploadFile(Request $request, int $id): JsonResponse + public function uploadFile(Request $request, int $id, GoogleCloudStorageService $gcs): JsonResponse { $employee = $this->employeeService->getEmployeeById($id); if (! $employee) { @@ -275,8 +276,18 @@ public function uploadFile(Request $request, int $id): JsonResponse foreach ($request->file('files') as $file) { $storedName = Str::random(40).'.'.$file->getClientOriginalExtension(); - $path = "tenants/{$tenantId}/employees/{$employee->id}"; - $file->storeAs($path, $storedName, 'tenant'); + $storagePath = "employees/{$tenantId}/{$employee->id}/{$storedName}"; + + // 로컬 저장 + Storage::disk('tenant')->put($storagePath, file_get_contents($file)); + + // GCS 업로드 + $gcsUri = null; + $gcsObjectName = null; + if ($gcs->isAvailable()) { + $gcsObjectName = $storagePath; + $gcsUri = $gcs->upload($file->getRealPath(), $gcsObjectName); + } $fileRecord = File::create([ 'tenant_id' => $tenantId, @@ -284,10 +295,12 @@ public function uploadFile(Request $request, int $id): JsonResponse 'document_type' => 'employee_profile', 'original_name' => $file->getClientOriginalName(), 'stored_name' => $storedName, - 'file_path' => $path.'/'.$storedName, + 'file_path' => $storagePath, 'mime_type' => $file->getMimeType(), 'file_size' => $file->getSize(), 'file_type' => strtolower($file->getClientOriginalExtension()), + 'gcs_object_name' => $gcsObjectName, + 'gcs_uri' => $gcsUri, 'uploaded_by' => auth()->id(), 'created_by' => auth()->id(), ]); @@ -303,9 +316,9 @@ public function uploadFile(Request $request, int $id): JsonResponse } /** - * 사원 첨부파일 삭제 + * 사원 첨부파일 삭제 (GCS + 로컬 모두 삭제) */ - public function deleteFile(int $id, int $fileId): JsonResponse + public function deleteFile(int $id, int $fileId, GoogleCloudStorageService $gcs): JsonResponse { $tenantId = session('selected_tenant_id'); @@ -319,16 +332,27 @@ public function deleteFile(int $id, int $fileId): JsonResponse return response()->json(['success' => false, 'message' => '파일을 찾을 수 없습니다.'], 404); } - Storage::disk('tenant')->delete($file->file_path); + // GCS 삭제 + if ($gcs->isAvailable() && $file->gcs_object_name) { + $gcs->delete($file->gcs_object_name); + } + + // 로컬 삭제 + if ($file->file_path && Storage::disk('tenant')->exists($file->file_path)) { + Storage::disk('tenant')->delete($file->file_path); + } + + $file->deleted_by = auth()->id(); + $file->save(); $file->delete(); return response()->json(['success' => true, 'message' => '파일이 삭제되었습니다.']); } /** - * 사원 첨부파일 다운로드 + * 사원 첨부파일 다운로드 (GCS Signed URL 우선, 로컬 폴백) */ - public function downloadFile(int $id, int $fileId) + public function downloadFile(int $id, int $fileId, GoogleCloudStorageService $gcs) { $tenantId = session('selected_tenant_id'); @@ -342,12 +366,21 @@ public function downloadFile(int $id, int $fileId) abort(404, '파일을 찾을 수 없습니다.'); } - $disk = Storage::disk('tenant'); - if (! $disk->exists($file->file_path)) { - abort(404, '파일이 서버에 존재하지 않습니다.'); + // GCS Signed URL로 리다이렉트 + if ($gcs->isAvailable() && $file->gcs_object_name) { + $signedUrl = $gcs->getSignedUrl($file->gcs_object_name, 60); + if ($signedUrl) { + return redirect($signedUrl); + } } - return $disk->download($file->file_path, $file->original_name); + // 로컬 폴백 + $disk = Storage::disk('tenant'); + if ($file->file_path && $disk->exists($file->file_path)) { + return $disk->download($file->file_path, $file->original_name); + } + + abort(404, '파일이 서버에 존재하지 않습니다.'); } /**