# VMIS-interface → VIPS 통합 프로젝트 분석 문서 **작성일**: 2025-11-06 **작업 방식**: 방법 2 - 직접 통합 (Spring Boot 2.7 다운그레이드) --- ## 목차 1. [프로젝트 개요](#1-프로젝트-개요) 2. [VIPS 프로젝트 구조](#2-vips-프로젝트-구조) 3. [VMIS-interface 프로젝트 구조](#3-vmis-interface-프로젝트-구조) 4. [기술 스택 비교](#4-기술-스택-비교) 5. [통합 방식 선택 이유](#5-통합-방식-선택-이유) 6. [주요 차이점 및 해결 방안](#6-주요-차이점-및-해결-방안) --- ## 1. 프로젝트 개요 ### VIPS (차량 점검 페널티 시스템) - **위치**: D:\workspace\git\VIPS - **목적**: 자동차 점검 페널티 관리 업무 시스템 - **형태**: 단일 모듈 Spring Boot 웹 애플리케이션 ### VMIS-interface (차량 정보 조회 API) - **위치**: D:\workspace\git\VMIS-interface - **목적**: 도로교통공단 Open API 연동하여 차량 정보 조회 - **형태**: REST API 서버 ### 통합 목표 VMIS-interface의 모든 설정, 로직, 데이터베이스를 VIPS 내부로 이식하여 외부 API 호출 없이 내부 모듈로 작동 --- ## 2. VIPS 프로젝트 구조 ### 2.1 기본 정보 ``` 프로젝트명: VIPS Spring Boot: 2.7.18 Java: 1.8 빌드: Gradle 패키징: WAR 데이터베이스: MariaDB ORM: MyBatis ``` ### 2.2 디렉토리 구조 ``` D:\workspace\git\VIPS\ ├── src/main/java/ │ ├── egovframework/ (전자정부 프레임워크) │ │ ├── config/ (설정 클래스) │ │ │ ├── RestTemplateConfig.java │ │ │ ├── DataSourceProxyConfig.java │ │ │ ├── EgovConfigCommon.java │ │ │ ├── EgovConfigWeb.java │ │ │ ├── SqlLoggingInterceptor.java │ │ │ └── SwaggerConfig.java │ │ ├── configProperties/ │ │ │ └── RestTemplateProperties.java │ │ ├── filter/ │ │ │ └── XssFilterConfig.java │ │ └── util/ │ │ ├── ApiResponseEntity.java │ │ └── ApiResponseUtil.java │ │ │ └── go/kr/project/ │ ├── externalApi/ (외부 API 통합 모듈) ★ │ │ ├── service/ │ │ │ └── ExternalVehicleApiService.java │ │ └── vo/ │ │ ├── Envelope.java │ │ ├── VehicleApiResponseVO.java │ │ ├── VehicleBasicInfoVO.java │ │ ├── VehicleBasicRequestVO.java │ │ ├── VehicleLedgerRequestVO.java │ │ └── VehicleLedgerVO.java │ ├── carInspectionPenalty/ │ ├── common/ │ ├── login/ │ ├── main/ │ ├── mypage/ │ └── system/ │ ├── src/main/resources/ │ ├── application.yml │ ├── application-local.yml │ ├── application-dev.yml │ ├── application-prd.yml │ ├── logback-spring.xml │ └── mybatis/ │ ├── mybatis-config.xml │ └── mapper/ │ └── build.gradle ``` ### 2.3 주요 설정 (application.yml) ```yaml server: port: 8080 mybatis: config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/**/*_${Globals.DbType}.xml rest-template: timeout: connect-timeout-millis: 10000 read-timeout-millis: 12000 connection-pool: max-total: 100 max-per-route: 20 rate-limit: permits-per-second: 5.0 ``` ### 2.4 기존 외부 API 통합 구조 **ExternalVehicleApiService.java**: - VMIS-interface를 REST API로 호출 (http://localhost:8081) - 배치 처리 지원 - 에러 처리 및 로깅 **RestTemplateConfig.java**: - Apache HttpClient 4 기반 - 연결 풀 관리 (PoolingHttpClientConnectionManager) - Rate Limiting (Guava RateLimiter) ### 2.5 주요 의존성 ```gradle dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:2.7.18' implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.3.1' implementation 'org.mariadb.jdbc:mariadb-java-client' implementation 'org.apache.httpcomponents:httpclient' implementation 'com.google.guava:guava:32.1.3-jre' implementation 'org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.3.0' implementation 'org.egovframe.rte:org.egovframe.rte.ptl.mvc:4.3.0' } ``` --- ## 3. VMIS-interface 프로젝트 구조 ### 3.1 기본 정보 ``` 프로젝트명: VMIS-interface Spring Boot: 3.3.4 Java: 17 빌드: Gradle 패키징: JAR 데이터베이스: MariaDB ORM: MyBatis ``` ### 3.2 디렉토리 구조 ``` D:\workspace\git\VMIS-interface\ ├── src/main/java/com/vmis/interfaceapp/ │ ├── InterfaceApplication.java (메인 클래스) │ │ │ ├── config/ (설정 계층) │ │ ├── MyBatisConfig.java │ │ ├── OpenApiConfig.java │ │ └── VmisProperties.java (핵심 설정) │ │ │ ├── controller/ (API 진입점) │ │ └── VehicleInterfaceController.java │ │ │ ├── service/ (비즈니스 로직) │ │ ├── CarBassMatterInqireService.java (기본사항 조회) │ │ ├── CarLedgerFrmbkService.java (등록원부 조회) │ │ ├── CarBassMatterInqireLogService.java (로그) │ │ └── CarLedgerFrmbkLogService.java (로그) │ │ │ ├── client/ (외부 API 호출) │ │ └── GovernmentApiClient.java (도로교통공단 API) │ │ │ ├── enricher/ (데이터 보강) │ │ └── RequestEnricher.java │ │ │ ├── model/ (도메인 모델) │ │ ├── entity/ (DB 엔티티 - 7개) │ │ ├── vo/ (VO - 6개) │ │ └── dto/ (DTO - 2개) │ │ │ ├── mapper/ (MyBatis Mapper) │ │ ├── CarBassMatterInqireLogMapper.java │ │ └── CarLedgerFrmbkLogMapper.java │ │ │ └── util/ (유틸리티) │ ├── EncryptionUtil.java (GPKI 암호화) │ └── TransactionIdGenerator.java │ ├── src/main/resources/ │ ├── application.yml │ ├── application-dev.yml │ ├── application-prd.yml │ ├── logback-spring.xml │ └── mybatis/ │ ├── mybatis-config.xml │ └── mapper/ │ ├── CarBassMatterInqireLogMapper.xml │ └── CarLedgerFrmbkLogMapper.xml │ ├── lib/ │ └── libgpkiapi_jni_1.5.jar (GPKI 라이브러리) │ ├── ddl/vips/ (데이터베이스 스키마) │ ├── tb_car_bass_matter_inqire.sql │ ├── seq_car_bass_matter_inqire.sql │ ├── tb_car_ledger_frmbk.sql │ ├── seq_car_ledger_frmbk.sql │ ├── tb_car_ledger_frmbk_dtl.sql │ └── seq_car_ledger_frmbk_dtl.sql │ └── build.gradle ``` ### 3.3 핵심 파일 목록 (34개 Java 파일) #### 설정 (3개) 1. `MyBatisConfig.java` 2. `OpenApiConfig.java` 3. `VmisProperties.java` ⭐ (핵심 설정) #### 컨트롤러 (1개) 4. `VehicleInterfaceController.java` #### 서비스 (4개) 5. `CarBassMatterInqireService.java` 6. `CarLedgerFrmbkService.java` 7. `CarBassMatterInqireLogService.java` 8. `CarLedgerFrmbkLogService.java` #### 클라이언트 (1개) 9. `GovernmentApiClient.java` ⭐ (가장 복잡) #### 데이터 보강 (1개) 10. `RequestEnricher.java` #### 엔티티 (7개) 11. `CarBassMatterInqire.java` 12. `CarBassMatterInqireLog.java` 13. `CarLedgerFrmbk.java` 14. `CarLedgerFrmbkDtl.java` 15. `CarLedgerFrmbkLog.java` 16. `VehicleBasicInfo.java` 17. `VehicleLedger.java` #### VO (6개) 18. `CarBassMatterInqireRequestVO.java` 19. `CarLedgerFrmbkRequestVO.java` 20. `Envelope.java` 21. `GovApiBasicRequest.java` 22. `GovApiBasicResponse.java` 23. `GovApiLedgerRequest.java` 24. `GovApiLedgerResponse.java` #### DTO (2개) 25. `VehicleBasicInfoDTO.java` 26. `VehicleLedgerDTO.java` #### Mapper (2개) 27. `CarBassMatterInqireLogMapper.java` 28. `CarLedgerFrmbkLogMapper.java` #### 유틸리티 (2개) 29. `EncryptionUtil.java` 30. `TransactionIdGenerator.java` #### 메인 클래스 (1개) 31. `InterfaceApplication.java` **총 31개 핵심 파일 + 3개 추가 클래스** ### 3.4 VmisProperties 구조 (핵심) ```java @ConfigurationProperties(prefix = "vmis") public class VmisProperties { private SystemProps system; // 시스템 정보 private GpkiProps gpki; // GPKI 암호화 설정 private GovProps government; // 정부 API 설정 public static class SystemProps { private String infoSysId; // 정보시스템 ID private String infoSysIp; // 시스템 IP private String managerId; // 담당자 ID private String managerName; // 담당자명 private String managerTel; // 담당자 전화번호 } public static class GpkiProps { private boolean enabled; // 암호화 사용 여부 private String certPath; // 인증서 경로 private String privateKeyPath; // 개인키 경로 private String privateKeyPassword; // 개인키 비밀번호 } public static class GovProps { private String host; // API 호스트 private String basePath; // 기본 경로 private int connectTimeout; // 연결 타임아웃 private int readTimeout; // 읽기 타임아웃 private Services services; // 서비스별 설정 public static class Services { private ServiceConfig basic; // 기본사항 API private ServiceConfig ledger; // 등록원부 API public static class ServiceConfig { private String path; // API 경로 private String apiKey; // API 키 } } } } ``` ### 3.5 application.yml 설정 ```yaml vmis: system: info-sys-id: "VMIS001" info-sys-ip: "192.168.1.100" manager-id: "admin" manager-name: "관리자" manager-tel: "02-1234-5678" gpki: enabled: false # 개발환경에서는 false cert-path: "/path/to/cert.der" private-key-path: "/path/to/private.key" private-key-password: "${GPKI_PASSWORD}" government: host: "https://www.vemanet.com" base-path: "/openapi" connect-timeout: 10000 read-timeout: 15000 services: basic: path: "/carBassMatterInqire" api-key: "${GOV_API_KEY_BASIC}" ledger: path: "/carLedgerFrmbk" api-key: "${GOV_API_KEY_LEDGER}" ``` ### 3.6 API 엔드포인트 #### 1. 자동차 기본사항 조회 ``` POST /api/v1/vehicles/basic Content-Type: application/json Request: { "vhrno": "12가3456" } Response: { "data": [ { "vhrno": "12가3456", "success": true, "message": "조회 성공", "basicInfo": { "vhrno": "12가3456", "vhcleNm": "소나타", ... } } ] } ``` #### 2. 자동차 등록원부 조회 ``` POST /api/v1/vehicles/ledger Content-Type: application/json Request: { "vhrno": "12가3456" } Response: { "data": [ { "vhrno": "12가3456", "success": true, "message": "조회 성공", "ledgerInfo": { "master": {...}, "details": [...] } } ] } ``` ### 3.7 데이터베이스 테이블 (6개) 1. **tb_car_bass_matter_inqire** (기본사항 로그) - seq_car_bass_matter_inqire (시퀀스) 2. **tb_car_ledger_frmbk** (등록원부 마스터) - seq_car_ledger_frmbk (시퀀스) 3. **tb_car_ledger_frmbk_dtl** (등록원부 상세) - seq_car_ledger_frmbk_dtl (시퀀스) ### 3.8 주요 의존성 ```gradle dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.3.4' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3' implementation 'org.mariadb.jdbc:mariadb-java-client:3.3.3' implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.3' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0' implementation 'org.projectlombok:lombok:1.18.34' implementation files('lib/libgpkiapi_jni_1.5.jar') } ``` --- ## 4. 기술 스택 비교 | 항목 | VIPS | VMIS-interface | 비고 | |------|------|----------------|------| | **Spring Boot** | 2.7.18 | 3.3.4 | 메이저 버전 차이 | | **Java** | 1.8 | 17 | 9개 버전 차이 | | **패키지** | javax.* | jakarta.* | 네임스페이스 변경 | | **HttpClient** | Apache 4 | Apache 5 | API 변경 | | **MyBatis** | 2.3.1 | 3.0.3 | 호환 가능 | | **MariaDB** | 기본 | 3.3.3 | 호환 가능 | | **Swagger** | springdoc 1.7.0 | springdoc 2.6.0 | 버전 차이 | | **Lombok** | 기본 | 1.18.34 | 호환 가능 | ### 4.1 주요 호환성 이슈 #### Spring Boot 2.x → 3.x 주요 변경사항 1. **패키지 변경**: `javax.*` → `jakarta.*` 2. **최소 Java 버전**: Java 8 → Java 17 3. **Spring Security**: 아키텍처 변경 4. **Configuration Properties**: 일부 속성명 변경 #### HttpClient 4 → 5 주요 변경사항 1. **패키지명**: `org.apache.http.*` → `org.apache.hc.client5.*` 2. **API 재설계**: 빌더 패턴 강화 3. **클래스명 변경**: `HttpClientBuilder` → `HttpClients` --- ## 5. 통합 방식 선택 이유 ### 방법 2: 직접 통합 (Spring Boot 2.7 다운그레이드) #### 선택 이유 1. **내부 시스템 자체 완결**: 외부 API 호출 없이 내부 메서드 호출로 처리 2. **트랜잭션 일관성**: 단일 애플리케이션 내 DB 트랜잭션 관리 3. **배포 단순화**: 하나의 WAR 파일로 배포 4. **성능 최적화**: 네트워크 오버헤드 제거 #### 트레이드오프 - Spring Boot 3 → 2 다운그레이드 필요 - Java 17 → Java 8 호환성 작업 필요 - 최신 기술 스택 사용 불가 --- ## 6. 주요 차이점 및 해결 방안 ### 6.1 Spring Boot 버전 차이 #### 문제 - Spring Boot 3.3.4 → 2.7.18 다운그레이드 #### 해결 방안 ```gradle // VMIS-interface build.gradle 수정 plugins { id 'org.springframework.boot' version '2.7.18' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } sourceCompatibility = '1.8' targetCompatibility = '1.8' ``` ### 6.2 패키지 네임스페이스 변경 #### 문제 - `jakarta.*` → `javax.*` 전체 변경 필요 #### 영향 범위 ``` jakarta.servlet.* → javax.servlet.* jakarta.validation.* → javax.validation.* jakarta.persistence.* → javax.persistence.* jakarta.annotation.* → javax.annotation.* ``` #### 해결 방안 - 전체 파일에서 `jakarta` → `javax` 일괄 교체 - IDE의 Find & Replace 기능 활용 ### 6.3 HttpClient 버전 차이 #### 문제 - Apache HttpClient 5 → 4 다운그레이드 #### GovernmentApiClient.java 수정 필요 ```java // Before (HttpClient 5) import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; // After (HttpClient 4) import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; ``` ### 6.4 Java 17 → Java 8 호환성 #### 주요 체크 포인트 1. **Text Blocks**: Java 15+ 기능 사용 시 일반 문자열로 변경 2. **Records**: Java 14+ 기능 사용 시 일반 클래스로 변경 3. **Switch Expressions**: Java 14+ 기능 사용 시 전통적 switch로 변경 4. **var 키워드**: Java 10+ 기능 (사용 가능하나 명시적 타입 권장) #### 현재 VMIS-interface 코드 검토 필요 - 대부분 전통적 Java 문법 사용 예상 - Lombok 적극 활용 중 (호환 가능) ### 6.5 MyBatis 설정 차이 #### VMIS-interface mybatis-config.xml ```xml ``` #### VIPS 설정과 통합 - VIPS의 기존 mybatis-config.xml에 설정 병합 - mapper 위치 추가: `mybatis/mapper/vmis/**/*_maria.xml` ### 6.6 패키지 구조 변경 #### Before (VMIS-interface) ``` com.vmis.interfaceapp.* ``` #### After (VIPS 통합) ``` go.kr.project.vmis.* ``` #### 변경 계획 ``` com.vmis.interfaceapp.config → go.kr.project.vmis.config com.vmis.interfaceapp.controller → go.kr.project.vmis.controller com.vmis.interfaceapp.service → go.kr.project.vmis.service com.vmis.interfaceapp.client → go.kr.project.vmis.client com.vmis.interfaceapp.model → go.kr.project.vmis.model com.vmis.interfaceapp.mapper → go.kr.project.vmis.mapper com.vmis.interfaceapp.util → go.kr.project.vmis.util ``` ### 6.7 설정 파일 통합 #### VmisProperties 통합 방안 **Option 1**: VIPS의 application.yml에 vmis 섹션 추가 ```yaml # VIPS application.yml vmis: system: info-sys-id: "VMIS001" ... government: ... ``` **Option 2**: application-vmis.yml 별도 파일 생성 ```yaml # application-vmis.yml vmis: ... ``` **권장**: Option 1 (단일 설정 파일 유지) ### 6.8 GPKI 라이브러리 통합 #### 파일 위치 ``` D:\workspace\git\VMIS-interface\lib\libgpkiapi_jni_1.5.jar ↓ D:\workspace\git\VIPS\lib\libgpkiapi_jni_1.5.jar ``` #### build.gradle 수정 ```gradle dependencies { implementation files('lib/libgpkiapi_jni_1.5.jar') } ``` --- ## 7. 마이그레이션 체크리스트 ### Phase 1: 환경 준비 - [ ] 현재 브랜치 상태 확인 (이미 생성됨) - [ ] VIPS 프로젝트 백업 (선택사항) - [ ] GPKI 라이브러리 복사 ### Phase 2: 코드 이식 - [ ] VmisProperties 이식 및 패키지 변경 - [ ] 설정 클래스 이식 (MyBatisConfig, OpenApiConfig) - [ ] GovernmentApiClient 이식 (HttpClient 4 변경) - [ ] 모델 클래스 이식 (entity, vo, dto) - [ ] 서비스 클래스 이식 - [ ] 컨트롤러 이식 - [ ] Mapper 인터페이스 및 XML 이식 - [ ] 유틸리티 클래스 이식 ### Phase 3: 설정 통합 - [ ] application.yml 설정 통합 - [ ] mybatis-config.xml 설정 병합 - [ ] logback-spring.xml 로그 설정 추가 - [ ] build.gradle 의존성 추가 ### Phase 4: 패키지 변경 - [ ] jakarta → javax 일괄 변경 - [ ] com.vmis.interfaceapp → go.kr.project.vmis 변경 - [ ] import 문 정리 ### Phase 5: 데이터베이스 - [ ] 데이터베이스 연결 테스트 (테이블은 이미 존재) ### Phase 6: 빌드 및 테스트 - [ ] Gradle 빌드 성공 확인 - [ ] 애플리케이션 구동 확인 - [ ] API 엔드포인트 테스트 - [ ] 정부 API 연동 테스트 - [ ] 로그 저장 확인 ### Phase 7: 전략 패턴 구현 (내부/외부 통신 분기) - [ ] VehicleInfoService 인터페이스 생성 - [ ] Internal/External 모드 구현체 작성 - [ ] VmisIntegrationConfig 설정 클래스 - [ ] application.yml 설정 추가 (vmis.integration.mode) - [ ] 기존 클라이언트 코드 인터페이스 의존으로 변경 ### Phase 8: 기존 코드 정리 - [ ] ExternalVehicleApiService 코드 리팩토링 - [ ] 불필요한 REST 호출 로직 제거 - [ ] 내부 메서드 호출로 변경 ### Phase 9: 문서화 및 배포 - [ ] API 문서 업데이트 - [ ] 운영 가이드 작성 - [ ] 코드 리뷰 - [ ] main 브랜치 머지 --- ## 8. 주요 파일 절대 경로 ### VIPS ``` D:\workspace\git\VIPS\src\main\java\egovframework\config\RestTemplateConfig.java D:\workspace\git\VIPS\src\main\java\go\kr\project\externalApi\service\ExternalVehicleApiService.java D:\workspace\git\VIPS\src\main\resources\application.yml D:\workspace\git\VIPS\build.gradle ``` ### VMIS-interface ``` D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\config\VmisProperties.java D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\client\GovernmentApiClient.java D:\workspace\git\VMIS-interface\src\main\resources\application.yml D:\workspace\git\VMIS-interface\lib\libgpkiapi_jni_1.5.jar D:\workspace\git\VMIS-interface\ddl\vips\*.sql ``` --- ## 9. 위험 요소 및 대응 방안 ### 9.1 Spring Boot 다운그레이드 실패 **위험**: 일부 Spring Boot 3 전용 기능 사용 시 빌드 실패 **대응**: 코드 리뷰 후 대체 코드 작성 ### 9.2 GPKI 암호화 라이브러리 호환성 **위험**: GPKI JNI 라이브러리가 특정 Java 버전에서만 작동 **대응**: 개발환경(gpki.enabled=false)에서 먼저 테스트 ### 9.3 HttpClient 버전 차이 **위험**: API 차이로 인한 런타임 에러 **대응**: GovernmentApiClient 전면 재작성 고려 ### 9.4 데이터베이스 트랜잭션 **위험**: 기존 VIPS와 새로운 VMIS 로직의 트랜잭션 충돌 **대응**: @Transactional 범위 명확히 설정 --- ## 10. 예상 작업 시간 | 단계 | 예상 시간 | 비고 | |------|----------|------| | Phase 1: 환경 준비 | 20분 | 디렉토리 생성, 라이브러리 복사 | | Phase 2: 코드 이식 | 3시간 | 34개 파일 이식 | | Phase 3: 설정 통합 | 1시간 | YAML, XML 병합 | | Phase 4: 패키지 변경 | 1시간 | 일괄 변경 | | Phase 5: 데이터베이스 | 10분 | 연결 테스트 (테이블 기존재) | | Phase 6: 빌드/테스트 | 2시간 | 디버깅 포함 | | Phase 7: 전략 패턴 구현 | 1.5시간 | 내부/외부 통신 분기 처리 | | Phase 8: 기존 코드 정리 | 1시간 | 리팩토링 | | Phase 9: 문서화 | 1시간 | 문서 작성 | | **총 예상 시간** | **10시간 50분** | 순수 작업 시간 | --- ## 11. 다음 단계 상세한 마이그레이션 계획은 `VMIS_INTERFACE_MIGRATION_PLAN.md` 파일을 참조하세요. **작업 진행 방법**: 브랜치는 이미 생성되어 있으므로, `VMIS_INTERFACE_MIGRATION_PLAN.md`의 Phase 1부터 시작하세요. ```bash cd D:\workspace\git\VIPS git status # 현재 브랜치 확인 ``` --- **문서 버전**: 1.2 **최종 수정**: 2025-11-06 **주요 변경사항**: - 브랜치 생성 관련 내용 제거 (이미 생성됨) - 데이터베이스 테이블 생성 제거 (이미 존재) - Phase 7 추가: 전략 패턴 구현 (내부/외부 통신 분기)