resolver->resolve($providerId, $purpose, $policyKey, $channel); $hookContext = array_merge($context, [ 'provider_id' => $providerId, 'purpose' => $purpose, 'policy_key' => $policyKey, 'render_hint' => $renderHint, 'channel' => $channel, 'target' => $target, 'data' => $data, ]); if ($resolved === null) { HookManager::doAction('core.identity.message.resolve_failed', $hookContext); Log::warning('[IDV] 메시지 정의/템플릿 미해석으로 발송 건너뜀', [ 'provider_id' => $providerId, 'purpose' => $purpose, 'policy_key' => $policyKey, 'render_hint' => $renderHint, 'channel' => $channel, ]); return false; } $template = $resolved['template']; $rendered = $template->replaceVariables($data); $hookContext['definition_id'] = $resolved['definition']->id; $hookContext['template_id'] = $template->id; $hookContext['rendered'] = $rendered; HookManager::doAction('core.identity.message.before_send', $hookContext); try { if ($channel === 'mail') { $mailable = new IdentityMessageMail( renderedSubject: $rendered['subject'], renderedBody: $rendered['body'], recipientEmail: $target, providerId: $providerId, scopeType: $resolved['definition']->scope_type->value, scopeValue: (string) $resolved['definition']->scope_value, ); Mail::to($target)->send($mailable); } else { // 미래 채널 확장 — 현재는 mail 만 지원 HookManager::applyFilters( 'core.identity.message.send_'.$channel, null, $hookContext ); } HookManager::doAction('core.identity.message.after_send', $hookContext); return true; } catch (\Throwable $e) { HookManager::doAction('core.identity.message.send_failed', array_merge($hookContext, [ 'error_message' => $e->getMessage(), ])); Log::warning('[IDV] 메시지 발송 실패', [ 'provider_id' => $providerId, 'purpose' => $purpose, 'policy_key' => $policyKey, 'render_hint' => $renderHint, 'channel' => $channel, 'error' => $e->getMessage(), ]); return false; } } }