From c36f90972867e686ed77719b3ff1483726a65e67 Mon Sep 17 00:00:00 2001 From: hskwon Date: Mon, 15 Dec 2025 16:33:51 +0900 Subject: [PATCH] =?UTF-8?q?API=20=EB=A1=9C=EA=B7=B8=EC=97=90=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90/=ED=85=8C=EB=84=8C=ED=8A=B8=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=B0=8F=20=EA=B7=B8=EB=A3=B9=ED=95=91=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LogApiRequest 미들웨어에서 app('api_user'), app('tenant_id') 사용 - 5초 TTL 캐시 기반 group_id 생성으로 연관 API 호출 그룹핑 - group_id 컬럼 추가 마이그레이션 --- app/Http/Middleware/LogApiRequest.php | 39 ++++++++++++++++++- app/Models/ApiRequestLog.php | 2 + ...add_group_id_to_api_request_logs_table.php | 32 +++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 database/migrations/2025_12_15_160033_add_group_id_to_api_request_logs_table.php diff --git a/app/Http/Middleware/LogApiRequest.php b/app/Http/Middleware/LogApiRequest.php index ff64a4a..93a2c0e 100644 --- a/app/Http/Middleware/LogApiRequest.php +++ b/app/Http/Middleware/LogApiRequest.php @@ -77,6 +77,15 @@ protected function logRequest(Request $request, Response $response, float $start try { $durationMs = (int) ((microtime(true) - $startTime) * 1000); + // 사용자/테넌트 정보 가져오기 (ApiKeyMiddleware에서 설정된 값 우선) + $apiUser = app()->bound('api_user') ? app('api_user') : null; + $tenantId = app()->bound('tenant_id') ? app('tenant_id') : null; + $userId = $apiUser?->id ?? $request->user()?->id; + $tenantId = $tenantId ?? $request->user()?->current_tenant_id; + + // 그룹 ID 생성 (동일 tenant+user의 연속 요청 묶기) + $groupId = $this->getOrCreateGroupId($tenantId, $userId); + $logData = [ 'method' => $request->method(), 'url' => $request->fullUrl(), @@ -89,8 +98,9 @@ protected function logRequest(Request $request, Response $response, float $start 'duration_ms' => $durationMs, 'ip_address' => $request->ip(), 'user_agent' => $request->userAgent(), - 'user_id' => $request->user()?->id, - 'tenant_id' => $request->user()?->current_tenant_id ?? null, + 'user_id' => $userId, + 'tenant_id' => $tenantId, + 'group_id' => $groupId, ]; // DB 저장 @@ -163,4 +173,29 @@ protected function writeToLogFile(array $logData): void 'response_status' => $logData['response_status'], ]); } + + /** + * 그룹 ID 생성 또는 기존 그룹 ID 반환 + * 동일 tenant+user의 5초 내 요청은 같은 그룹으로 묶음 + */ + protected function getOrCreateGroupId(?int $tenantId, ?int $userId): string + { + $cacheKey = "api_log_group:{$tenantId}:{$userId}"; + $groupTtl = 5; // 5초 내 요청은 같은 그룹 + + // 캐시에서 기존 그룹 ID 확인 + $existingGroupId = cache()->get($cacheKey); + + if ($existingGroupId) { + // TTL 갱신 (연속 요청 시 그룹 유지) + cache()->put($cacheKey, $existingGroupId, $groupTtl); + return $existingGroupId; + } + + // 새 그룹 ID 생성 + $newGroupId = now()->format('Ymd_His_') . substr(md5(uniqid((string) mt_rand(), true)), 0, 8); + cache()->put($cacheKey, $newGroupId, $groupTtl); + + return $newGroupId; + } } \ No newline at end of file diff --git a/app/Models/ApiRequestLog.php b/app/Models/ApiRequestLog.php index 151efb3..931e91f 100644 --- a/app/Models/ApiRequestLog.php +++ b/app/Models/ApiRequestLog.php @@ -21,6 +21,7 @@ * @property string|null $user_agent * @property int|null $user_id * @property int|null $tenant_id + * @property string|null $group_id * @property \Carbon\Carbon $created_at */ class ApiRequestLog extends Model @@ -41,6 +42,7 @@ class ApiRequestLog extends Model 'user_agent', 'user_id', 'tenant_id', + 'group_id', ]; protected $casts = [ diff --git a/database/migrations/2025_12_15_160033_add_group_id_to_api_request_logs_table.php b/database/migrations/2025_12_15_160033_add_group_id_to_api_request_logs_table.php new file mode 100644 index 0000000..9ce4559 --- /dev/null +++ b/database/migrations/2025_12_15_160033_add_group_id_to_api_request_logs_table.php @@ -0,0 +1,32 @@ +string('group_id', 50)->nullable()->after('tenant_id')->comment('요청 그룹 ID (연관 API 묶음)'); + $table->index('group_id'); + $table->index(['tenant_id', 'user_id', 'created_at']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('api_request_logs', function (Blueprint $table) { + $table->dropIndex(['group_id']); + $table->dropIndex(['tenant_id', 'user_id', 'created_at']); + $table->dropColumn('group_id'); + }); + } +};