diff --git a/README.md b/README.md index 674d378..e630efd 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Client → VehicleInterfaceController ``` #### 2. **External Mode** (외부 REST API 호출) -- 별도로 실행 중인 VMIS-interface 서버의 REST API를 호출 +- 별도로 실행 중인 VIPS 서버의 REST API를 호출 - 서비스 분리를 통한 확장성 및 유지보수성 향상 - MSA(Microservices Architecture) 환경에 적합 @@ -42,7 +42,7 @@ Client → VehicleInterfaceController Client → VehicleInterfaceController → ExternalVehicleInfoServiceImpl → ExternalVehicleApiServiceImpl (RestTemplate) - → VMIS-interface 서버 (별도 실행) + → VIPS 서버 (별도 실행) → 정부 VMIS API ``` @@ -168,7 +168,7 @@ public class VmisIntegrationConfig { #### 모드 전환 시 주의사항 **Internal → External 전환 시:** -1. 외부 VMIS-interface 서버가 실행 중이어야 함 +1. 외부 VIPS 서버가 실행 중이어야 함 2. `vmis.external.api.url.base` 설정 필요 3. 네트워크 방화벽 설정 확인 4. GPKI 암호화는 외부 서버에서 처리됨 @@ -478,6 +478,152 @@ server: port: 8080 ``` + + +#### 방법 2: JAR 파일 실행 (배포 권장) + +**개발 환경** +```bash +# Linux/Mac +java -Dspring.profiles.active=dev -jar build/libs/VIPS-BOOT.war + +# Windows PowerShell +java -Dspring.profiles.active=dev -jar build/libs/VIPS-BOOT.war + +# 또는 환경변수 사용 (Windows PowerShell) +$env:SPRING_PROFILES_ACTIVE = "dev" +java -jar build/libs/VIPS-BOOT.war +``` + +**운영 환경 (환경변수 포함)** +```bash +# Linux/Mac +export SPRING_PROFILES_ACTIVE=prd +export VMIS_SYSTEM_INFO_SYS_ID="41-345" +export VMIS_SYSTEM_SIGUNGU_CODE="41460" +java -jar build/libs/VIPS-BOOT.war + +# Windows PowerShell +$env:SPRING_PROFILES_ACTIVE = "prd" +$env:VMIS_SYSTEM_INFO_SYS_ID = "41-345" +$env:VMIS_SYSTEM_SIGUNGU_CODE = "41460" +java -jar build/libs/VIPS-BOOT.war +``` + +#### 백그라운드 실행 (Linux 서버) +```bash +# nohup 사용 (기본 java 경로, 콘솔 출력을 app.log에 저장) +nohup java -Dspring.profiles.active=prd -jar build/libs/VIPS-BOOT.war > app.log 2>&1 & + +# Java 경로를 직접 지정하는 방법 (Java 17 이상) +nohup /usr/bin/java -Dspring.profiles.active=prd -jar build/libs/VIPS-BOOT.war > app.log 2>&1 & + +# 또는 사용자 지정 Java 경로 사용 +nohup /opt/jdk-17/bin/java -Dspring.profiles.active=prd -jar build/libs/VIPS-BOOT.war > app.log 2>&1 & + +# 콘솔 출력을 남기지 않을 때 (애플리케이션 자체 로그는 logback-spring.xml 설정에 따라 별도 저장됨) +# 개발 환경 +nohup /usr/bin/java -Dspring.profiles.active=dev -jar build/libs/VIPS-BOOT.war > /dev/null 2>&1 & + +# 운영 환경 (애플리케이션 로그: d:/data/VIPS/logs/vips.log) +nohup /usr/bin/java -Dspring.profiles.active=prd -jar build/libs/VIPS-BOOT.war > /dev/null 2>&1 & + +# Java 경로 확인 방법 +which java +# 또는 +readlink -f $(which java) + +# 프로세스 확인 +ps aux | grep VIPS + +# 종료 +kill -9 +``` + +**참고:** `/dev/null` 사용 시 콘솔 출력만 버려지며, 애플리케이션 자체 로그는 `logging.file.path` 설정에 따라 정상적으로 기록됩니다. +- 개발: `d:/data/VIPS/logs/vips.log` +- 운영: `d:/data/VIPS/logs/vips.log` + +#### 백그라운드 실행 (Windows 서버) + +**PowerShell - 백그라운드 프로세스로 실행** +```powershell +# 개발 환경 (콘솔 출력을 app.log에 저장) +Start-Process -NoNewWindow -FilePath "java" -ArgumentList "-Dspring.profiles.active=dev","-jar","build\libs\VIPS-BOOT.war" -RedirectStandardOutput "app.log" -RedirectStandardError "app.log" + +# 운영 환경 (콘솔 출력을 app.log에 저장) +Start-Process -NoNewWindow -FilePath "java" -ArgumentList "-Dspring.profiles.active=prd","-jar","build\libs\VIPS-BOOT.war" -RedirectStandardOutput "app.log" -RedirectStandardError "app.log" + +# Java 경로를 직접 지정하는 방법 +Start-Process -NoNewWindow -FilePath "D:\DEV\.jdks\jdk1.8.0_271\bin\java.exe" -ArgumentList "-Dspring.profiles.active=prd","-jar","build\libs\VIPS-BOOT.war" -RedirectStandardOutput "app.log" -RedirectStandardError "app.log" + +# 콘솔 출력을 남기지 않을 때 (NUL로 리다이렉트) +Start-Process -NoNewWindow -FilePath "java" -ArgumentList "-Dspring.profiles.active=prd","-jar","build\libs\VIPS-BOOT.war" -RedirectStandardOutput "NUL" -RedirectStandardError "NUL" +``` + +**CMD - javaw 사용 (콘솔 창 없이 실행)** +```cmd +# 개발 환경 +start /B javaw -Dspring.profiles.active=dev -jar build\libs\VIPS-BOOT.war + +# 운영 환경 +start /B javaw -Dspring.profiles.active=prd -jar build\libs\VIPS-BOOT.war + +# Java 경로를 직접 지정 (경로에 공백이 있을 경우 빈 창제목 "" 필요) +start "" /B "D:\DEV\.jdks\jdk1.8.0_271\bin\javaw.exe" -Dspring.profiles.active=prd -jar build\libs\VIPS-BOOT.war + +# 또는 절대 경로 사용 +start "" /B "D:\DEV\.jdks\jdk1.8.0_271\bin\javaw.exe" -Dspring.profiles.active=prd -jar D:\workspace\git\VIPS\build\libs\VIPS-BOOT.war + + +cd /d d: +D:\VIPS\azul-17.0.14\bin + +java -Dspring.profiles.active=prd -jar D:\VIPS\VIPS-BOOT.war + +"D:\VIPS\azul-17.0.14\bin\javaw.exe" -Dspring.profiles.active=prd -jar D:\VIPS\VIPS-BOOT.war + +start "" /B "D:\VIPS\azul-17.0.14\bin\javaw.exe" -Dspring.profiles.active=prd -jar D:\VIPS\VIPS-BOOT.war +``` + +**참고:** `start` 명령어는 첫 번째 따옴표 문자열을 창 제목으로 인식하므로, 경로를 따옴표로 묶을 때는 앞에 빈 창제목 `""`을 추가해야 합니다. + +**프로세스 관리** +```powershell +# 프로세스 확인 +Get-Process | Where-Object {$_.ProcessName -like "*java*"} | Select-Object Id, ProcessName, Path + +# 또는 특정 포트로 확인 +netstat -ano | findstr :18080 + +# 프로세스 종료 (PID로) +Stop-Process -Id -Force + +# 또는 taskkill 사용 +taskkill /F /PID +``` + +**Java 경로 확인 (Windows)** +```powershell +# PowerShell +where.exe java + +# 또는 +(Get-Command java).Source + +# Java 버전 확인 +java -version +``` + +**참고:** Windows 환경에서도 콘솔 출력을 `NUL`로 리다이렉트하면, 애플리케이션 자체 로그는 `d:/data/VIPS/logs/vips.log`에 정상적으로 기록됩니다. + +### 4) API 문서(Swagger UI) +- 개발 환경: `http://localhost:8080/swagger-ui/index.html` +- 운영 환경: `http://localhost:18080/swagger-ui/index.html` + +--- + + --- ## Swagger API 문서 @@ -581,15 +727,6 @@ vmis: --- -## 참고 문서 - -프로젝트 루트에 다음 상세 문서들이 있습니다: - -- `VMIS_INTEGRATION_COMPLETE.md`: VMIS 통합 완료 보고서 -- `VMIS_INTEGRATION_STRATEGY_DESIGN.md`: 통합 전략 설계 문서 -- `VMIS_INTERFACE_INTEGRATION_ANALYSIS.md`: 인터페이스 통합 분석 -- `VMIS_INTERFACE_MIGRATION_PLAN.md`: 마이그레이션 계획 - --- ## 라이선스 diff --git a/src/main/webapp/WEB-INF/views/carInspectionPenalty/registration/list.jsp b/src/main/webapp/WEB-INF/views/carInspectionPenalty/registration/list.jsp index 1f04b6e..809c0e2 100644 --- a/src/main/webapp/WEB-INF/views/carInspectionPenalty/registration/list.jsp +++ b/src/main/webapp/WEB-INF/views/carInspectionPenalty/registration/list.jsp @@ -89,7 +89,10 @@ 'use strict'; var SEARCH_COND = {}; - + + // 그리드 조회 시 사용된 마지막 검색조건 저장 + var LAST_GRID_SEARCH_COND = {}; + // 페이징 정보를 저장할 전역 변수 var GRID_PAGINATION_INFO = { totalCount: 0, @@ -131,6 +134,90 @@ return baseUrl + (params.length ? ('?' + params.join('&')) : ''); }; + // 검색조건 비교 및 확인 + var compareSearchConditions = function() { + // 현재 폼의 검색조건 수집 + setSearchCond(); + + // 그리드 조회 이력이 없는 경우 + if (!LAST_GRID_SEARCH_COND || Object.keys(LAST_GRID_SEARCH_COND).length === 0) { + alert("먼저 검색 버튼을 눌러 그리드를 조회해주세요."); + return false; + } + + // 검색조건 레이블 매핑 + var fieldLabels = { + schRcptYmdStart: '접수일자 시작', + schRcptYmdEnd: '접수일자 종료', + schInspYmdStart: '검사일자 시작', + schInspYmdEnd: '검사일자 종료', + schVhclno: '차량번호', + schOwnrNm: '소유자명', + schTaskPrcsSttsCd: '처리상태' + }; + + // 날짜 포맷 변환 함수 (YYYYMMDD -> YYYY-MM-DD) + var formatDate = function(dateStr) { + if (!dateStr || dateStr.length !== 8) return dateStr; + return dateStr.substring(0, 4) + '-' + dateStr.substring(4, 6) + '-' + dateStr.substring(6, 8); + }; + + // 처리상태 코드 -> 텍스트 변환 + var getTaskPrcsSttsCdText = function(code) { + if (!code) return '전체'; + var $option = $("#schTaskPrcsSttsCd option[value='" + code + "']"); + return $option.length > 0 ? $option.text() : code; + }; + + // 값 포맷팅 함수 + var formatValue = function(field, value) { + if (!value) return '(공백)'; + if (field.indexOf('Ymd') > -1) { + return formatDate(value); + } + if (field === 'schTaskPrcsSttsCd') { + return getTaskPrcsSttsCdText(value); + } + return value; + }; + + // 달라진 조건 찾기 + var differences = []; + var searchFields = ['schRcptYmdStart', 'schRcptYmdEnd', 'schInspYmdStart', 'schInspYmdEnd', + 'schVhclno', 'schOwnrNm', 'schTaskPrcsSttsCd']; + + searchFields.forEach(function(field) { + var currentValue = SEARCH_COND[field] || ''; + var lastValue = LAST_GRID_SEARCH_COND[field] || ''; + + if (currentValue !== lastValue) { + differences.push({ + field: field, + label: fieldLabels[field], + oldValue: lastValue, + newValue: currentValue + }); + } + }); + + // 검색조건이 동일한 경우 + if (differences.length === 0) { + return true; + } + + // 달라진 조건 메시지 생성 + var message = "검색 조건이 그리드 조회 시와 다릅니다.\n\n[변경된 조건]\n"; + differences.forEach(function(diff) { + message += "• " + diff.label + "\n"; + message += " 이전: " + formatValue(diff.field, diff.oldValue) + "\n"; + message += " 현재: " + formatValue(diff.field, diff.newValue) + "\n\n"; + }); + message += "현재 조건으로 계속 진행하시겠습니까?"; + + // 사용자 확인 + return confirm(message); + }; + /** * 과태료 대상 목록 관리 네임스페이스 */ @@ -341,6 +428,9 @@ * 그리드 새로고침 */ reload: function() { + // 그리드 조회 전 현재 검색조건을 마지막 검색조건으로 저장 + setSearchCond(); + LAST_GRID_SEARCH_COND = Object.assign({}, SEARCH_COND); this.instance.readData(1); } }, @@ -401,6 +491,11 @@ // 목록 다운로드 버튼 클릭 $("#downloadBtn").on('click', function() { + // 검색조건 비교 및 확인 + if (!compareSearchConditions()) { + return; + } + var url = buildDownloadUrl(); // 파일 다운로드는 단순 이동으로 처리 window.location.href = url; @@ -538,6 +633,11 @@ * API 호출 및 데이터 비교 (검색조건 전체, 페이징 없이) */ callApiAndCompareAll: function() { + // 검색조건 비교 및 확인 + if (!compareSearchConditions()) { + return; + } + if (!confirm("현재 검색조건의 전체 데이터에 대해 API를 호출하고 비교하시겠습니까?")) { return; }