diff --git a/app/Http/Controllers/FileViewController.php b/app/Http/Controllers/FileViewController.php index 5730ada5..1ce6fc73 100644 --- a/app/Http/Controllers/FileViewController.php +++ b/app/Http/Controllers/FileViewController.php @@ -2,40 +2,48 @@ namespace App\Http\Controllers; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; /** - * R2 파일 프록시 (MNG 세션 인증으로 API 파일 스트리밍) + * R2 파일 Presigned URL 리다이렉트 * - * MNG는 Blade(서버사이드)이므로 API의 /files/{id}/view를 직접 호출 시 - * sanctum 인증 문제가 발생. MNG 세션 인증으로 API를 프록시하여 파일 스트리밍. + * API에서 R2 presigned URL을 발급받아 브라우저를 직접 R2로 리다이렉트. + * presigned URL은 5분간 캐시하여 동일 이미지 반복 요청 시 API 호출 최소화. */ class FileViewController extends Controller { public function show(int $id) { - $baseUrl = config('services.api.base_url', 'https://api.sam.kr'); - $apiKey = config('services.api.key') ?: '42Jfwc6EaRQ04GNRmLR5kzJp5UudSOzGGqjmdk1a'; - $token = session('api_access_token', ''); + $cacheKey = "file_presigned_url:{$id}"; - $response = Http::baseUrl($baseUrl) - ->withoutVerifying() - ->withHeaders([ - 'X-API-KEY' => $apiKey, - 'X-TENANT-ID' => 287, // TODO: session('selected_tenant_id', 1) 로 복원 - ]) - ->withToken($token) - ->timeout(15) - ->get("/api/v1/files/{$id}/view"); + $url = Cache::remember($cacheKey, now()->addMinutes(5), function () use ($id) { + $baseUrl = config('services.api.base_url', 'https://api.sam.kr'); + $apiKey = config('services.api.key'); + $token = session('api_access_token', ''); - if (! $response->successful()) { + $response = Http::baseUrl($baseUrl) + ->withoutVerifying() + ->withHeaders([ + 'X-API-KEY' => $apiKey, + 'X-TENANT-ID' => session('selected_tenant_id', 1), + ]) + ->withToken($token) + ->timeout(10) + ->get("/api/v1/files/{$id}/presigned-url"); + + if (! $response->successful()) { + return null; + } + + return $response->json('data.url'); + }); + + if (! $url) { + Cache::forget($cacheKey); abort(404); } - return response($response->body(), 200, [ - 'Content-Type' => $response->header('Content-Type', 'image/png'), - 'Content-Disposition' => 'inline', - 'Cache-Control' => 'private, max-age=3600', - ]); + return redirect($url); } }