@@ -370,20 +370,67 @@ export class AIDevTeamApp {
370370
371371 // Graceful shutdown을 위한 신호 핸들러 설정
372372 setupSignalHandlers ( ) : void {
373+ let shutdownInProgress = false ;
374+
373375 const signalHandler = ( signal : string ) => {
376+ if ( shutdownInProgress ) {
377+ console . log ( `\n⚠️ ${ signal } 신호가 이미 처리 중입니다. 강제 종료하려면 다시 한 번 신호를 보내세요.` ) ;
378+ return ;
379+ }
380+
381+ shutdownInProgress = true ;
374382 console . log ( `\n📡 ${ signal } 신호 수신됨. Graceful shutdown 시작...` ) ;
383+
384+ // 강제 종료 타이머 (30초 후)
385+ const forceExitTimeout = setTimeout ( ( ) => {
386+ console . error ( '⚠️ Graceful shutdown이 30초 내에 완료되지 않아 강제 종료합니다.' ) ;
387+ process . exit ( 1 ) ;
388+ } , 30000 ) ;
389+
375390 this . stop ( )
376391 . then ( ( ) => {
392+ clearTimeout ( forceExitTimeout ) ;
377393 console . log ( '✅ Graceful shutdown 완료' ) ;
378394 process . exit ( 0 ) ;
379395 } )
380396 . catch ( ( error ) => {
397+ clearTimeout ( forceExitTimeout ) ;
381398 console . error ( '❌ Graceful shutdown 실패:' , error ) ;
382399 process . exit ( 1 ) ;
383400 } ) ;
384401 } ;
385402
386- process . on ( 'SIGTERM' , ( ) => signalHandler ( 'SIGTERM' ) ) ;
387- process . on ( 'SIGINT' , ( ) => signalHandler ( 'SIGINT' ) ) ;
403+ // 두 번째 신호 수신 시 즉시 강제 종료
404+ let signalCount = 0 ;
405+ const forceSignalHandler = ( signal : string ) => {
406+ signalCount ++ ;
407+
408+ if ( signalCount === 1 ) {
409+ signalHandler ( signal ) ;
410+ } else if ( signalCount >= 2 ) {
411+ console . log ( `\n⚡ 두 번째 ${ signal } 신호 수신됨. 즉시 강제 종료합니다.` ) ;
412+ process . exit ( 1 ) ;
413+ }
414+ } ;
415+
416+ process . on ( 'SIGTERM' , ( ) => forceSignalHandler ( 'SIGTERM' ) ) ;
417+ process . on ( 'SIGINT' , ( ) => forceSignalHandler ( 'SIGINT' ) ) ;
418+
419+ // 처리되지 않은 promise rejection 핸들링
420+ process . on ( 'unhandledRejection' , ( reason , promise ) => {
421+ console . error ( 'Unhandled Rejection at:' , promise , 'reason:' , reason ) ;
422+ this . logger ?. error ( 'Unhandled promise rejection' , { reason, promise } ) ;
423+ } ) ;
424+
425+ // 처리되지 않은 예외 핸들링
426+ process . on ( 'uncaughtException' , ( error ) => {
427+ console . error ( 'Uncaught Exception:' , error ) ;
428+ this . logger ?. error ( 'Uncaught exception' , { error } ) ;
429+
430+ // 정리 후 종료
431+ this . stop ( )
432+ . finally ( ( ) => process . exit ( 1 ) )
433+ . catch ( ( ) => process . exit ( 1 ) ) ;
434+ } ) ;
388435 }
389436}
0 commit comments