From bea56a8e303089d0b653f1840a9b133bfade78b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B1=EC=98=81?= Date: Wed, 5 Nov 2025 10:42:45 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + build.gradle | 3 - .../client/GovernmentApiClient.java | 40 +---- .../interfaceapp/service/RequestEnricher.java | 6 +- .../vmis/interfaceapp/util/NewGpkiUtil.java | 56 +++---- src/main/resources/application-dev.yml | 16 ++ src/main/resources/application-prd.yml | 16 ++ src/main/resources/application.yml | 58 ++----- src/main/resources/logback-spring.xml | 147 ++++++++++++++++++ 9 files changed, 227 insertions(+), 116 deletions(-) create mode 100644 src/main/resources/logback-spring.xml diff --git a/.gitignore b/.gitignore index 1de4b95..778e131 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ /.gradle/ /build/ /gradle/ +/.claude/settings.local.json diff --git a/build.gradle b/build.gradle index b048499..82198f5 100644 --- a/build.gradle +++ b/build.gradle @@ -29,9 +29,6 @@ dependencies { // GPKI JNI local library implementation files('lib/libgpkiapi_jni_1.5.jar') - // Log4j 1.x for legacy util (NewGpkiUtil). Consider replacing with SLF4J in future. - implementation 'log4j:log4j:1.2.17' - // Configuration metadata annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' diff --git a/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java b/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java index 97da794..5e77dd7 100644 --- a/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java +++ b/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java @@ -10,13 +10,13 @@ import com.vmis.interfaceapp.model.common.Envelope; import com.vmis.interfaceapp.model.ledger.LedgerRequest; import com.vmis.interfaceapp.model.ledger.LedgerResponse; import com.vmis.interfaceapp.util.TxIdUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestTemplate; +import lombok.extern.slf4j.Slf4j; + import java.nio.charset.StandardCharsets; /** @@ -55,22 +55,10 @@ import java.nio.charset.StandardCharsets; * @see GpkiService * @see VmisProperties */ +@Slf4j @Component public class GovernmentApiClient { - /** - * SLF4J 로거 인스턴스 - * - *

모든 API 호출, 에러, 응답에 대한 로그를 기록합니다. - * 로그 레벨별 용도:

- * - */ - private static final Logger log = LoggerFactory.getLogger(GovernmentApiClient.class); - /** * Spring RestTemplate * @@ -358,18 +346,6 @@ public class GovernmentApiClient { * VMIS_SEOUL * 필수 * - * - * REGION_CODE - * 지역 코드 (시군구 코드) - * 11010 (서울 종로구) - * 선택 - * - * - * DEPT_CODE - * 부서 코드 - * TRANS_001 - * 선택 - * * * *

문자 인코딩:

@@ -426,16 +402,6 @@ public class GovernmentApiClient { // 호출하는 시스템을 식별하는 필수 값 headers.add("INFO_SYS_ID", props.getSystem().getInfoSysId()); - // 10. 지역 코드 (선택 사항) - // 시군구 코드 (예: 11010 = 서울특별시 종로구) - // null이 아닌 경우에만 헤더에 추가 - if (props.getSystem().getRegionCode() != null) headers.add("REGION_CODE", props.getSystem().getRegionCode()); - - // 11. 부서 코드 (선택 사항) - // 호출하는 부서의 코드 - // null이 아닌 경우에만 헤더에 추가 - if (props.getSystem().getDepartmentCode() != null) headers.add("DEPT_CODE", props.getSystem().getDepartmentCode()); - // 구성 완료된 헤더 반환 return headers; } diff --git a/src/main/java/com/vmis/interfaceapp/service/RequestEnricher.java b/src/main/java/com/vmis/interfaceapp/service/RequestEnricher.java index f2674d1..52c9645 100644 --- a/src/main/java/com/vmis/interfaceapp/service/RequestEnricher.java +++ b/src/main/java/com/vmis/interfaceapp/service/RequestEnricher.java @@ -4,10 +4,10 @@ import com.vmis.interfaceapp.config.properties.VmisProperties; import com.vmis.interfaceapp.model.basic.BasicRequest; import com.vmis.interfaceapp.model.common.Envelope; import com.vmis.interfaceapp.model.ledger.LedgerRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; +import lombok.extern.slf4j.Slf4j; + /** * Populates incoming request models with values from YAML configuration. * Unconditionally overwrites the listed fields per requirement: @@ -15,9 +15,9 @@ import org.springframework.stereotype.Component; * - CNTC_INFO_CODE (service specific) * - CHARGER_ID, CHARGER_IP, CHARGER_NM */ +@Slf4j @Component public class RequestEnricher { - private static final Logger log = LoggerFactory.getLogger(RequestEnricher.class); private final VmisProperties props; diff --git a/src/main/java/com/vmis/interfaceapp/util/NewGpkiUtil.java b/src/main/java/com/vmis/interfaceapp/util/NewGpkiUtil.java index 6dc2b00..77acd0d 100644 --- a/src/main/java/com/vmis/interfaceapp/util/NewGpkiUtil.java +++ b/src/main/java/com/vmis/interfaceapp/util/NewGpkiUtil.java @@ -4,16 +4,16 @@ import java.io.File; import java.util.HashMap; import java.util.Map; -import org.apache.log4j.Logger; - import com.gpki.gpkiapi_jni; import com.gpki.gpkiapi.GpkiApi; import com.gpki.gpkiapi.cert.X509Certificate; import com.gpki.gpkiapi.crypto.PrivateKey; import com.gpki.gpkiapi.storage.Disk; +import lombok.extern.slf4j.Slf4j; + +@Slf4j public class NewGpkiUtil { - private static Logger logger = Logger.getLogger(NewGpkiUtil.class); byte[] myEnvCert, myEnvKey, mySigCert, mySigKey; private Map targetServerCertMap = new HashMap(); @@ -35,11 +35,11 @@ public class NewGpkiUtil { public void init() throws Exception { GpkiApi.init(gpkiLicPath); gpkiapi_jni gpki = this.getGPKI(); - if(logger.isDebugEnabled()){ + if(log.isDebugEnabled()){ if(gpki.API_GetInfo()==0) - logger.debug(gpki.sReturnString); + log.debug(gpki.sReturnString); else - logger.error(gpki.sDetailErrorString); + log.error(gpki.sDetailErrorString); } if(targetServerIdList!=null){ String certIdList[] = targetServerIdList.split(","); @@ -51,7 +51,7 @@ public class NewGpkiUtil { } } - logger.info("Loading gpki certificate : myServerId=" + log.info("Loading gpki certificate : myServerId=" + this.getMyServerId()); X509Certificate _myEnvCert = Disk.readCert(this @@ -76,12 +76,12 @@ public class NewGpkiUtil { testGpki(gpki); } this.finish(gpki); - logger.info("GpkiUtil initialized"); + log.info("GpkiUtil initialized"); } private void load(gpkiapi_jni gpki, String certId) throws Exception { - logger.debug("Loading gpki certificate : targetServerId="+ certId); + log.debug("Loading gpki certificate : targetServerId="+ certId); X509Certificate cert = targetServerCertMap.get(certId); if (cert != null) { @@ -107,7 +107,7 @@ public class NewGpkiUtil { if(certFilePath != null){ cert = Disk.readCert(certFilePath + File.separator + certId + ".cer"); }else{ - logger.debug("not certFilePath"); + log.debug("not certFilePath"); } } @@ -117,13 +117,13 @@ public class NewGpkiUtil { private gpkiapi_jni getGPKI(){ gpkiapi_jni gpki = new gpkiapi_jni(); if(gpki.API_Init(gpkiLicPath) != 0){ - logger.error(gpki.sDetailErrorString); + log.error(gpki.sDetailErrorString); } return gpki; } private void finish(gpkiapi_jni gpki){ if(gpki.API_Finish() != 0){ - logger.error(gpki.sDetailErrorString); + log.error(gpki.sDetailErrorString); } } @@ -243,44 +243,44 @@ public class NewGpkiUtil { public void testGpki(gpkiapi_jni gpki) throws Exception{ //gpki test eng - logger.info("======================================================="); - logger.info("================ TEST GPKI START ======================"); - logger.info("======================================================="); + log.info("======================================================="); + log.info("================ TEST GPKI START ======================"); + log.info("======================================================="); String original_Eng = "abc"; - logger.info("=== TEST ENG STRING: "+ original_Eng); + log.info("=== TEST ENG STRING: "+ original_Eng); try { byte[] encrypted = encrypt(original_Eng.getBytes(), myServerId); - logger.info("=== TEST ENG ENCRYPT STRING: "+ encode(encrypted)); + log.info("=== TEST ENG ENCRYPT STRING: "+ encode(encrypted)); String decrypted = new String(decrypt(encrypted)); - logger.info("=== TEST ENG DECRYPT STRING: "+decrypted); + log.info("=== TEST ENG DECRYPT STRING: "+decrypted); if (!original_Eng.equals(decrypted)) { throw new Exception("GpkiUtil not initialized properly(english)"); } - logger.info("=== TEST ENG: OK"); + log.info("=== TEST ENG: OK"); } catch (Exception e) { - logger.warn("Gpki Test error(english)", e); + log.warn("Gpki Test error(english)", e); throw e; } //gpki test kor String original = "한글테스트"; - logger.info("=== TEST KOR STRING: "+ original); + log.info("=== TEST KOR STRING: "+ original); try { byte[] encrypted = encrypt(original.getBytes(), myServerId); - logger.info("=== TEST KOR ENCRYPT STRING: "+ encode(encrypted)); + log.info("=== TEST KOR ENCRYPT STRING: "+ encode(encrypted)); String decrypted = new String(decrypt(encrypted)); - logger.info("=== TEST KOR DECRYPT STRING: "+decrypted); + log.info("=== TEST KOR DECRYPT STRING: "+decrypted); if (!original.equals(decrypted)) { throw new Exception("GpkiUtil not initialized properly(korean)"); } - logger.info("=== TEST KOR: OK"); + log.info("=== TEST KOR: OK"); } catch (Exception e) { - logger.warn("Gpki Test error(korean)", e); + log.warn("Gpki Test error(korean)", e); throw e; }finally{ - logger.info("======================================================="); - logger.info("================ TEST GPKI END ========================"); - logger.info("======================================================="); + log.info("======================================================="); + log.info("================ TEST GPKI END ========================"); + log.info("======================================================="); } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index ffc2a64..d496d2f 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,6 +1,22 @@ server: port: 8080 +# 로그 설정 - 개발(DEV) 환경 +logging: + config: classpath:logback-spring.xml + file: + path: d:/data/VMIS-interface/logs + name: vmis-interface + logback: + rollingpolicy: + max-file-size: 10MB + max-history: 30 + level: + root: INFO + com.vmis.interfaceapp: DEBUG + org.springframework: INFO + org.springframework.web: DEBUG + # 인터페이스 및 연계 설정 - 개발(DEV) 환경 vmis: system: diff --git a/src/main/resources/application-prd.yml b/src/main/resources/application-prd.yml index f068437..e5983b5 100644 --- a/src/main/resources/application-prd.yml +++ b/src/main/resources/application-prd.yml @@ -1,6 +1,22 @@ server: port: 8080 +# 로그 설정 - 운영(PRD) 환경 +logging: + config: classpath:logback-spring.xml + file: + path: d:/data/VMIS-interface/logs + name: vmis-interface + logback: + rollingpolicy: + max-file-size: 10MB + max-history: 90 + level: + root: WARN + com.vmis.interfaceapp: INFO + org.springframework: WARN + org.springframework.web: INFO + # 인터페이스 및 연계 설정 - 운영(PRD) 환경 # 주의: 실제 운영 키/호스트는 배포 환경 변수나 외부 설정(Secret)로 주입 권장 vmis: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 260e017..caac1db 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,48 +8,16 @@ spring: server: port: 8080 -# 인터페이스 및 연계 설정 (공통 기본값) -vmis: - system: - infoSysId: "41-345" # INFO_SYS_ID - infoSysIp: "" # INFO_SYS_IP (예: 105.19.10.135) - # 예시: 경기도 용인시 수지구 장애인복지과 - regionCode: "" # 시군구코드 (SIGUNGU_CODE, 예: 41460) - departmentCode: "" # 행정부서코드 필요 시 입력 - # 담당자 기본값(미입력 시 빈 값) - chargerId: "" - chargerIp: "" - chargerNm: "" - gpki: - enabled: "Y" # Y 또는 N (환경별 yml에서 재정의 가능) - useSign: true - charset: "UTF-8" - certServerId: "SVR5640020001" # 이용기관 인증서 ID (ENV/SIG 공통 서버 ID) - targetServerId: "SVR1611000006" # 보유기관 인증서 ID(교통안전공단) - # 아래는 네이티브 GPKI 유틸(NewGpkiUtil) 설정값 (필요 시 사용) - ldap: true # LDAP 사용 여부 (true: LDAP에서 대상서버 인증서 조회) - gpkiLicPath: "C:/gpki2/gpkisecureweb/conf" - certFilePath: "C:/gpki2/gpkisecureweb/certs" # LDAP 미사용 시 대상서버 인증서 파일 폴더 - envCertFilePathName: "C:/gpki2/gpkisecureweb/certs/SVRxxxx_env.cer" - envPrivateKeyFilePathName: "C:/gpki2/gpkisecureweb/certs/SVRxxxx_env.key" - envPrivateKeyPasswd: "change-me" - sigCertFilePathName: "C:/gpki2/gpkisecureweb/certs/SVRxxxx_sig.cer" - sigPrivateKeyFilePathName: "C:/gpki2/gpkisecureweb/certs/SVRxxxx_sig.key" - sigPrivateKeyPasswd: "change-me" - gov: - scheme: "http" - host: "localhost:18080" # 환경별 yml에서 재정의 - basePath: "/piss/api/molit" - connectTimeoutMillis: 5000 - readTimeoutMillis: 10000 - services: - basic: # 시군구연계 자동차기본사항조회 - path: "/SignguCarBassMatterInqireService" - cntcInfoCode: "AC1_FD11_01" - apiKey: "change-me" - cvmisApikey: "change-me" - ledger: # 시군구연계 자동차등록원부(갑) - path: "/SignguCarLedgerFrmbkService" - cntcInfoCode: "AC1_FD11_02" - apiKey: "change-me" - cvmisApikey: "change-me" +# 로그 설정 +logging: + config: classpath:logback-spring.xml + file: + path: ./logs + name: vmis-interface + logback: + rollingpolicy: + max-file-size: 10MB + max-history: 30 + level: + root: INFO + com.vmis.interfaceapp: DEBUG \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..9a137bc --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + ${LOG_PATTERN} + ${LOG_CHARSET} + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) [%thread] %cyan(%logger{36}) - %msg%n + ${LOG_CHARSET} + + + + + + ${LOG_PATH}/${LOG_FILE}.log + + ${LOG_PATTERN} + ${LOG_CHARSET} + + + + ${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.%i.log + + ${MAX_FILE_SIZE} + + ${MAX_HISTORY} + true + + 3GB + + + + + + ${LOG_PATH}/${LOG_FILE}-error.log + + ERROR + ACCEPT + DENY + + + ${LOG_PATTERN} + ${LOG_CHARSET} + + + ${LOG_PATH}/${LOG_FILE}-error.%d{yyyy-MM-dd}.%i.log + + ${MAX_FILE_SIZE} + 90 + true + + + + + + + 512 + 0 + false + false + + + + + + 256 + 0 + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +