diff --git a/.env b/.env index ab46ae0..f01722d 100644 --- a/.env +++ b/.env @@ -12,11 +12,13 @@ #-------------------------------------------------------------------- # ENVIRONMENT #-------------------------------------------------------------------- +APP_SERVER_NAME = "TEST-SERVER-01" +CI_ENVIRONMENT = development # CI_ENVIRONMENT = production #-------------------------------------------------------------------- # APP #-------------------------------------------------------------------- -app.baseURL = 'http://test2.admin.confirms.co.kr/' +app.baseURL = 'http://test2-admin.confirms.co.kr/' # If you have trouble with `.`, you could also use `_`. # app_baseURL = '' # app.forceGlobalSecureRequests = false diff --git a/app/Commands/NaverWorker.php b/app/Commands/NaverWorker.php index d5a56ea..580e25b 100644 --- a/app/Commands/NaverWorker.php +++ b/app/Commands/NaverWorker.php @@ -29,7 +29,7 @@ class NaverWorker extends BaseCommand while (true) { // 메인 큐 및 재시도 큐에서 데이터 꺼내기 (Blocking Pop, 5초 타임아웃) // LIFO (lPush/brPop) 사용 시: ['naver:queue:retry', 'naver:queue'] - $item = $redis->brPop(['naver:queue'], 5); + $item = $redis->brPop(['naver:worker_queue'], 5); if ($item) { $payload = json_decode($item[1], true); diff --git a/app/Config/Filters.php b/app/Config/Filters.php index 2d029f6..cca04dc 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -35,6 +35,7 @@ class Filters extends BaseFilters 'pagecache' => PageCache::class, 'performance' => PerformanceMetrics::class, 'auth' => \App\Filters\AuthCheck::class, + 'jsInjector' => \App\Filters\JavascriptInjector::class, ]; /** @@ -84,13 +85,15 @@ class Filters extends BaseFilters 'index.php/login/*', // /index.php/login/* 'register', // 회원가입 등 'register/*', - 'api/*', // 필요하면 API는 예외 + 'kiso/*', // 필요하면 API는 예외 ], ], ], 'after' => [ // 'honeypot', // 'secureheaders', + 'jsInjector', // 모든 페이지 응답 후에 실행 + 'toolbar', ], ]; diff --git a/app/Controllers/KisoController.php b/app/Controllers/KisoController.php index 331d7ed..d7af24a 100644 --- a/app/Controllers/KisoController.php +++ b/app/Controllers/KisoController.php @@ -16,10 +16,10 @@ class KisoController extends BaseController public function vrfcReq() { // 1. 요청 방식에 따라 데이터 파싱 - if ($this->request->getMethod() === 'post') { + if ( $this->request->is('post') ) { // POST 방식: JSON Body에서 데이터 가져오기 $data = $this->request->getJSON(true); - } elseif ($this->request->getMethod() === 'get') { + } else if ( $this->request->is('get') ) { // GET 방식: Query Parameter에서 데이터 가져오기 $data = $this->request->getGet(); } else { @@ -29,7 +29,7 @@ class KisoController extends BaseController } // 2. 필수 항목 검증 - $requiredKeys = ['articleNumbr', 'reqeustType', 'requestDatetime']; + $requiredKeys = ['articleNumber', 'requestType', 'requestDatetime']; foreach ($requiredKeys as $key) { // 파싱된 데이터($data) 내에 키가 없거나 값이 비어있는지 확인 @@ -43,32 +43,30 @@ class KisoController extends BaseController } // 3. Redis 연결 및 예외 처리 + // 3. Redis 연결 및 직접 푸시 try { - // CI4 Cache Service 인스턴스를 가져옴. 기본 핸들러가 Redis여야 함. - // (또는 Services::cache('redis')를 사용해 RedisHandler를 명시적으로 요청) - $redis = \Config\Services::cache(); + $redis = new \Redis(); + // Docker 환경이므로 host를 'redis'로 설정 + $success = $redis->connect('redis', 6379); - // Redis 핸들러가 맞는지 확인 (선택 사항) - if (!($redis->getHandler() instanceof RedisHandler)) { - throw new \Exception('Cache handler is not Redis. Check Config/Cache.php $handler setting.'); + if (!$success) { + throw new \Exception('Redis connection failed'); } - // 요청에 재시도 횟수 초기화 + + $redis->select(10); // 10번 DB 선택 + + // 데이터 준비 $data['retry_count'] = 0; - // RedisHandler의 getClient()를 사용하여 원본 \Redis 객체를 가져옵니다. - // 주의: 모든 RedisHandler가 getClient()를 제공하는 것은 아니지만, CI4 내장 RedisHandler는 제공합니다. - $client = $redis->getHandler()->getClient(); - - // 큐에 push - $client->lPush('naver:queue', json_encode($data)); + // 리스트에 데이터 삽입 (이 명령어가 실행되어야 monitor에 LPUSH가 뜹니다) + $redis->lPush('naver:queue', json_encode($data)); } catch (\Exception $e) { - log_message('error', 'Redis connection failed: ' . $e->getMessage()); - return $this->response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR) - ->setJSON([ - 'resultCode' => 'E999', - 'resultMessage' => 'Internal server error (Queue system unavailable)' - ]); + log_message('error', 'Redis Push Error: ' . $e->getMessage()); + return $this->response->setStatusCode(500)->setJSON([ + 'resultCode' => 'E999', + 'resultMessage' => 'Redis Connection Error' + ]); } // 4. 성공 응답 @@ -76,7 +74,7 @@ class KisoController extends BaseController ->setJSON([ 'resultCode' => 'S000', 'resultMessage' => 'Request successfully queued for processing', - 'articleNumbr' => $data['articleNumbr'] + 'articleNumber' => $data['articleNumber'] ]); } } \ No newline at end of file diff --git a/app/Filters/JavascriptInjector.php b/app/Filters/JavascriptInjector.php new file mode 100644 index 0000000..fee49ff --- /dev/null +++ b/app/Filters/JavascriptInjector.php @@ -0,0 +1,39 @@ +getHeaderLine('Content-Type'), 'text/html') === false) return; + + // .env에서 서버 이름 가져오기 (없으면 'Unknown' 또는 컨테이너ID) + $serverAlias = env('APP_SERVER_NAME') ?? gethostname(); + $envMode = ENVIRONMENT; + + $scriptTag = " + + "; + + $body = $response->getBody(); + if (strpos($body, '') !== false) { + $response->setBody(str_replace('', $scriptTag . '', $body)); + } + } +} \ No newline at end of file diff --git a/app/Views/layouts/footer.php b/app/Views/layouts/footer.php index f273d1d..0d87401 100644 --- a/app/Views/layouts/footer.php +++ b/app/Views/layouts/footer.php @@ -34,4 +34,24 @@ --> + + + + + \ No newline at end of file diff --git a/public/common/js/de.js b/public/common/js/de.js new file mode 100644 index 0000000..450533e --- /dev/null +++ b/public/common/js/de.js @@ -0,0 +1,43 @@ +(function() { + // 1. 환경 데이터 가져오기 (없으면 기본값 production) + const info = window.SERVER_INFO || { alias: 'UNKNOWN', env: 'production' }; + + // 2. 운영 환경이면 실행 중단 (표시 안 함) + if (info.env === 'production') { + return; + } + + // 3. 테스트/로컬 환경일 때 스타일 설정 (강렬한 빨간색) + const bgColor = '#dc3545'; // 경고 의미의 빨간색 + const textColor = '#ffffff'; + const borderColor = '#a71d2a'; // 더 어두운 빨간색 테두리 + + // 4. 상태바 생성 및 스타일 적용 + const statusDiv = document.createElement('div'); + Object.assign(statusDiv.style, { + position: 'fixed', + bottom: '0', + left: '0', + width: '100%', + height: '32px', + backgroundColor: bgColor, + color: textColor, + textAlign: 'center', + fontSize: '14px', + lineHeight: '32px', + fontWeight: '900', + zIndex: '2147483647', // 최상단 레이어 보장 + opacity: '1', + pointerEvents: 'none', // 클릭 방해 금지 + boxShadow: '0 -4px 15px rgba(0,0,0,0.4)', + borderTop: `3px solid ${borderColor}`, + letterSpacing: '0.5px', + fontFamily: 'system-ui, -apple-system, sans-serif' + }); + + // 5. 출력 문구 (서버 이름 강조) + statusDiv.innerHTML = `⚠️ [TEST SERVER] NAME: ${info.alias} | HOST: ${window.location.hostname} ⚠️`; + + // 6. 문서에 추가 + document.body.appendChild(statusDiv); +})(); \ No newline at end of file