From dbe3ed698ab29b522f8187d4a2d15d9a6c0f944a Mon Sep 17 00:00:00 2001 From: hskwon Date: Mon, 10 Nov 2025 13:59:48 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=8A=A4=EC=BC=80=EC=A4=84=EB=9F=AC=20?= =?UTF-8?q?Laravel=2012=20=ED=91=9C=EC=A4=80=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EC=A0=84=ED=99=98=20+=20=EB=A1=9C=EA=B7=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - routes/console.php에 스케줄러 마이그레이션 (Laravel 12 표준) - appendOutputTo로 실행 결과 로그 기록 (storage/logs/scheduler.log) - onSuccess/onFailure로 성공/실패 이벤트 로그 (storage/logs/laravel.log) - app/Console/Kernel.php schedule() 메서드 정리 - CURRENT_WORKS.md 업데이트 --- CURRENT_WORKS.md | 141 ++++++++++++++++++++++++++++++++++++++++- app/Console/Kernel.php | 4 +- routes/console.php | 24 +++++++ 3 files changed, 166 insertions(+), 3 deletions(-) diff --git a/CURRENT_WORKS.md b/CURRENT_WORKS.md index 65e6e50..11ee54d 100644 --- a/CURRENT_WORKS.md +++ b/CURRENT_WORKS.md @@ -1,6 +1,6 @@ # SAM API 저장소 작업 현황 -## 2025-11-10 (일) - API 토큰 관리 시스템 구현 (액세스/리프레시 토큰 분리) +## 2025-11-10 (일) - API 토큰 관리 시스템 구현 (액세스/리프레시 토큰 분리 + 자동 정리) ### 주요 작업 - **액세스/리프레시 토큰 분리**: 액세스 토큰(2시간), 리프레시 토큰(7일) 독립 관리 @@ -8,6 +8,7 @@ ### 주요 작업 - **토큰 갱신 엔드포인트**: POST /api/v1/refresh (리프레시 토큰으로 새 토큰 발급) - **보안 강화**: 리프레시 토큰 일회성 사용, 사용자당 1개 리프레시 토큰만 유지 - **에러 처리**: TOKEN_EXPIRED 에러 코드로 프론트엔드 자동 리프레시 지원 +- **자동 정리 스케줄러**: 만료 토큰 자동 삭제 (매일 새벽 3:20) ### 추가된 파일: - `app/Services/AuthService.php` - 토큰 발급/갱신 통합 서비스 (119줄) @@ -1381,4 +1382,142 @@ ### Git 커밋 준비: --- +## 2025-11-10 (일) - 스케줄러 Laravel 12 표준 방식 전환 + 로그 기록 + +### 주요 작업 +- **Laravel 12 표준 방식 적용**: Kernel.php → routes/console.php로 스케줄러 마이그레이션 +- **로그 기록 기능 추가**: 실행 결과 및 성공/실패 이벤트 로그 +- **스케줄러 정리**: Kernel.php 레거시 코드 정리 + +### 수정된 파일: +- `routes/console.php` - Laravel 12 표준 스케줄러 정의 + 로그 기록 +- `app/Console/Kernel.php` - schedule() 메서드 정리 (주석 처리) + +### 작업 내용: + +#### 1. routes/console.php 마이그레이션 (Laravel 12 표준) + +**변경 전 (Kernel.php):** +```php +protected function schedule(Schedule $schedule): void +{ + $schedule->command('audit:prune')->dailyAt('03:10'); + $schedule->command('sanctum:prune-expired --hours=24')->dailyAt('03:20'); +} +``` + +**변경 후 (routes/console.php):** +```php +use Illuminate\Support\Facades\Schedule; + +// 감사 로그 정리 (매일 새벽 03:10) +Schedule::command('audit:prune') + ->dailyAt('03:10') + ->appendOutputTo(storage_path('logs/scheduler.log')) + ->onSuccess(function () { + \Illuminate\Support\Facades\Log::info('✅ audit:prune 스케줄러 실행 성공', ['time' => now()]); + }) + ->onFailure(function () { + \Illuminate\Support\Facades\Log::error('❌ audit:prune 스케줄러 실행 실패', ['time' => now()]); + }); + +// 만료 토큰 정리 (매일 새벽 03:20) +Schedule::command('sanctum:prune-expired --hours=24') + ->dailyAt('03:20') + ->appendOutputTo(storage_path('logs/scheduler.log')) + ->onSuccess(function () { + \Illuminate\Support\Facades\Log::info('✅ sanctum:prune-expired 스케줄러 실행 성공', ['time' => now()]); + }) + ->onFailure(function () { + \Illuminate\Support\Facades\Log::error('❌ sanctum:prune-expired 스케줄러 실행 실패', ['time' => now()]); + }); +``` + +#### 2. Kernel.php 정리 + +**app/Console/Kernel.php:** +```php +protected function schedule(Schedule $schedule): void +{ + // Laravel 12부터는 routes/console.php에서 스케줄러를 정의합니다. + // Schedule::command() 방식 사용 +} +``` + +#### 3. 로그 기록 방식 + +**2가지 로그 파일:** + +1. **storage/logs/scheduler.log** - 명령어 실행 결과 + ``` + Pruned 0 audit log rows older than 390 days. + Tokens expired for more than [24 hours] pruned successfully. + ``` + +2. **storage/logs/laravel.log** - 성공/실패 이벤트 + ``` + [2025-11-10 03:10:15] production.INFO: ✅ audit:prune 스케줄러 실행 성공 {"time":"2025-11-10 03:10:15"} + [2025-11-10 03:20:20] production.INFO: ✅ sanctum:prune-expired 스케줄러 실행 성공 {"time":"2025-11-10 03:20:20"} + ``` + +#### 4. 스케줄러 확인 방법 + +**등록 확인:** +```bash +php artisan schedule:list + +# 결과: +# 10 3 * * * php artisan audit:prune ................. Next Due: 13시간 후 +# 20 3 * * * php artisan sanctum:prune-expired ... Next Due: 13시간 후 +``` + +**로그 확인:** +```bash +# 실행 결과 확인 +cat storage/logs/scheduler.log +tail -f storage/logs/scheduler.log # 실시간 모니터링 + +# 성공/실패 이벤트 확인 +tail -f storage/logs/laravel.log | grep "스케줄러" + +# 성공 로그만 +grep "✅" storage/logs/laravel.log + +# 실패 로그만 +grep "❌" storage/logs/laravel.log +``` + +### 기술 세부사항: + +#### Laravel 11+ 스케줄러 아키텍처 변경 +- **Laravel 10 이하**: app/Console/Kernel.php의 schedule() 메서드 +- **Laravel 11+**: routes/console.php에서 Schedule 파사드 사용 +- **이점**: + - 라우트와 함께 콘솔 명령 관리 + - 더 간결한 구조 + - 향후 유지보수 용이 + +#### 로그 기록 전략 +- **appendOutputTo**: 명령어 stdout/stderr를 파일에 추가 +- **onSuccess/onFailure**: 실행 결과에 따라 Laravel Log 기록 +- **비동기 처리**: Log 파사드가 자동으로 처리 + +### 예상 효과: + +1. **표준 방식 준수**: Laravel 12 공식 권장 방식 +2. **실행 추적**: 스케줄러 실행 이력 확인 가능 +3. **문제 진단**: 실패 로그로 즉시 문제 파악 +4. **운영 편의성**: 로그 파일 분석으로 시스템 모니터링 + +### 다음 작업: + +- [ ] Frontend 토큰 갱신 로직 구현 (권장) +- [ ] 토큰 만료 모니터링 대시보드 (선택) + +### Git 커밋: +798d514 - feat: API 토큰 관리 시스템 구현 (액세스/리프레시 토큰 분리) +(다음 커밋 예정: feat: 스케줄러 Laravel 12 표준 방식 전환 + 로그 기록) + +--- + (이전 작업 내역은 그대로 유지...) \ No newline at end of file diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 36c552c..a9eb0cd 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -20,8 +20,8 @@ class Kernel extends ConsoleKernel protected function schedule(Schedule $schedule): void { - // 매일 새벽 03:10에 감사 로그 정리(환경값 기반 보관기간) - $schedule->command('audit:prune')->dailyAt('03:10'); + // Laravel 12부터는 routes/console.php에서 스케줄러를 정의합니다. + // Schedule::command() 방식 사용 } protected function commands(): void diff --git a/routes/console.php b/routes/console.php index 3c9adf1..4fa4eb9 100644 --- a/routes/console.php +++ b/routes/console.php @@ -2,7 +2,31 @@ use Illuminate\Foundation\Inspiring; use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\Schedule; Artisan::command('inspire', function () { $this->comment(Inspiring::quote()); })->purpose('Display an inspiring quote'); + +// 스케줄러 정의 (Laravel 12 표준 방식) +// 매일 새벽 03:10에 감사 로그 정리 (환경값 기반 보관기간) +Schedule::command('audit:prune') + ->dailyAt('03:10') + ->appendOutputTo(storage_path('logs/scheduler.log')) + ->onSuccess(function () { + \Illuminate\Support\Facades\Log::info('✅ audit:prune 스케줄러 실행 성공', ['time' => now()]); + }) + ->onFailure(function () { + \Illuminate\Support\Facades\Log::error('❌ audit:prune 스케줄러 실행 실패', ['time' => now()]); + }); + +// 매일 새벽 03:20에 만료된 토큰 정리 (만료 후 24시간 보관) +Schedule::command('sanctum:prune-expired --hours=24') + ->dailyAt('03:20') + ->appendOutputTo(storage_path('logs/scheduler.log')) + ->onSuccess(function () { + \Illuminate\Support\Facades\Log::info('✅ sanctum:prune-expired 스케줄러 실행 성공', ['time' => now()]); + }) + ->onFailure(function () { + \Illuminate\Support\Facades\Log::error('❌ sanctum:prune-expired 스케줄러 실행 실패', ['time' => now()]); + });