31 KiB
VMIS-interface → VIPS 통합 마이그레이션 실행 계획
작성일: 2025-11-06 방법: 직접 통합 (Spring Boot 2.7 다운그레이드) 예상 소요 시간: 10시간
목차
Phase 1: 사전 준비
참고: 브랜치는 이미 생성되어 진행 중입니다.
1.1 현재 상태 확인
cd D:\workspace\git\VIPS
# 현재 브랜치 및 상태 확인
git status
git branch
1.2 디렉토리 구조 준비
# VIPS 프로젝트에 새 패키지 생성 (Windows PowerShell)
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\config"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\controller"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\service"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\client"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\model\entity"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\model\vo"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\model\dto"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\mapper"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\util"
New-Item -ItemType Directory -Force -Path "src\main\java\go\kr\project\vmis\enricher"
# MyBatis 매퍼 디렉토리
New-Item -ItemType Directory -Force -Path "src\main\resources\mybatis\mapper\vmis"
# GPKI 라이브러리 디렉토리 (이미 존재하면 스킵)
New-Item -ItemType Directory -Force -Path "lib"
1.3 GPKI 라이브러리 복사
# Windows CMD
copy "D:\workspace\git\VMIS-interface\lib\libgpkiapi_jni_1.5.jar" "D:\workspace\git\VIPS\lib\"
Phase 2: 패키지 구조 설계
2.1 최종 패키지 구조
go.kr.project.vmis/
├── config/ (설정)
│ ├── VmisProperties.java (설정 속성)
│ ├── MyBatisConfig.java (MyBatis 설정)
│ └── OpenApiConfig.java (Open API 설정)
│
├── controller/ (컨트롤러)
│ └── VehicleInterfaceController.java
│
├── service/ (서비스)
│ ├── CarBassMatterInqireService.java
│ ├── CarLedgerFrmbkService.java
│ ├── CarBassMatterInqireLogService.java
│ └── CarLedgerFrmbkLogService.java
│
├── client/ (외부 API 클라이언트)
│ └── GovernmentApiClient.java
│
├── enricher/ (데이터 보강)
│ └── RequestEnricher.java
│
├── model/ (모델)
│ ├── entity/ (DB 엔티티)
│ │ ├── CarBassMatterInqire.java
│ │ ├── CarBassMatterInqireLog.java
│ │ ├── CarLedgerFrmbk.java
│ │ ├── CarLedgerFrmbkDtl.java
│ │ ├── CarLedgerFrmbkLog.java
│ │ ├── VehicleBasicInfo.java
│ │ └── VehicleLedger.java
│ ├── vo/ (VO)
│ │ ├── CarBassMatterInqireRequestVO.java
│ │ ├── CarLedgerFrmbkRequestVO.java
│ │ ├── Envelope.java
│ │ ├── GovApiBasicRequest.java
│ │ ├── GovApiBasicResponse.java
│ │ ├── GovApiLedgerRequest.java
│ │ └── GovApiLedgerResponse.java
│ └── dto/ (DTO)
│ ├── VehicleBasicInfoDTO.java
│ └── VehicleLedgerDTO.java
│
├── mapper/ (MyBatis Mapper)
│ ├── CarBassMatterInqireLogMapper.java
│ └── CarLedgerFrmbkLogMapper.java
│
└── util/ (유틸리티)
├── EncryptionUtil.java
└── TransactionIdGenerator.java
Phase 3: 코드 이식 순서
3.1 이식 우선순위 (의존성 순서)
1. util (의존성 없음)
└── TransactionIdGenerator.java
└── EncryptionUtil.java
2. model (util에만 의존)
└── entity/ (7개)
└── vo/ (7개)
└── dto/ (2개)
3. config (model에 의존)
└── VmisProperties.java (가장 먼저)
└── MyBatisConfig.java
└── OpenApiConfig.java
4. mapper (model에 의존)
└── CarBassMatterInqireLogMapper.java
└── CarLedgerFrmbkLogMapper.java
5. enricher (config, util에 의존)
└── RequestEnricher.java
6. client (config, model, util, enricher에 의존)
└── GovernmentApiClient.java
7. service (모든 계층에 의존)
└── CarBassMatterInqireLogService.java
└── CarLedgerFrmbkLogService.java
└── CarBassMatterInqireService.java
└── CarLedgerFrmbkService.java
8. controller (service에 의존)
└── VehicleInterfaceController.java
Phase 4: 단계별 상세 가이드
Step 1: build.gradle 의존성 추가
파일: D:\workspace\git\VIPS\build.gradle
dependencies {
// 기존 의존성...
// VMIS-interface 관련 추가 의존성
implementation 'org.apache.httpcomponents:httpclient:4.5.14' // Apache HttpClient 4
implementation 'com.fasterxml.jackson.core:jackson-databind' // JSON 처리 (이미 있을 가능성 높음)
// GPKI 라이브러리
implementation files('lib/libgpkiapi_jni_1.5.jar')
}
주의:
- Spring Boot 2.7.18에는 기본적으로 HttpClient 4가 포함되어 있으므로 충돌 확인 필요
- Jackson은 Spring Boot Starter에 포함되어 있음
Step 2: VmisProperties 이식 및 수정
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\config\VmisProperties.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\config\VmisProperties.java
변경 사항:
// Before
package com.vmis.interfaceapp.config;
// After
package go.kr.project.vmis.config;
전체 코드 예시:
package go.kr.project.vmis.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "vmis")
public class VmisProperties {
private SystemProps system = new SystemProps();
private GpkiProps gpki = new GpkiProps();
private GovProps government = new GovProps();
@Getter
@Setter
public static class SystemProps {
private String infoSysId;
private String infoSysIp;
private String managerId;
private String managerName;
private String managerTel;
}
@Getter
@Setter
public static class GpkiProps {
private boolean enabled;
private String certPath;
private String privateKeyPath;
private String privateKeyPassword;
}
@Getter
@Setter
public static class GovProps {
private String host;
private String basePath;
private int connectTimeout;
private int readTimeout;
private Services services = new Services();
@Getter
@Setter
public static class Services {
private ServiceConfig basic = new ServiceConfig();
private ServiceConfig ledger = new ServiceConfig();
@Getter
@Setter
public static class ServiceConfig {
private String path;
private String apiKey;
}
}
}
}
Step 3: application.yml 설정 통합
파일: D:\workspace\git\VIPS\src\main\resources\application.yml
추가할 내용:
# VMIS 정부 API 연동 설정
vmis:
system:
info-sys-id: "VMIS001"
info-sys-ip: "${SERVER_IP:192.168.1.100}"
manager-id: "admin"
manager-name: "관리자"
manager-tel: "02-1234-5678"
gpki:
enabled: false # 개발환경에서는 false, 운영환경에서는 true
cert-path: "${GPKI_CERT_PATH:/path/to/cert.der}"
private-key-path: "${GPKI_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:your-api-key-basic}"
ledger:
path: "/carLedgerFrmbk"
api-key: "${GOV_API_KEY_LEDGER:your-api-key-ledger}"
# MyBatis 설정 업데이트 (기존 설정에 추가)
mybatis:
mapper-locations:
- classpath:mybatis/mapper/**/*_${Globals.DbType}.xml
- classpath:mybatis/mapper/vmis/**/*_maria.xml # VMIS 매퍼 추가
환경별 설정 (application-local.yml, application-dev.yml, application-prd.yml):
# application-prd.yml (운영환경)
vmis:
gpki:
enabled: true # 운영환경에서는 암호화 활성화
Step 4: 유틸리티 클래스 이식
4.1 TransactionIdGenerator.java
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\util\TransactionIdGenerator.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\util\TransactionIdGenerator.java
변경 사항:
// Before
package com.vmis.interfaceapp.util;
// After
package go.kr.project.vmis.util;
// import 문 변경 없음 (Java 표준 라이브러리만 사용)
4.2 EncryptionUtil.java
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\util\EncryptionUtil.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\util\EncryptionUtil.java
주요 변경 사항:
// Before
package com.vmis.interfaceapp.util;
import com.vmis.interfaceapp.config.VmisProperties;
// After
package go.kr.project.vmis.util;
import go.kr.project.vmis.config.VmisProperties;
Step 5: 모델 클래스 이식
5.1 Entity 클래스 (7개)
패키지 변경:
// Before
package com.vmis.interfaceapp.model.entity;
// After
package go.kr.project.vmis.model.entity;
파일 목록:
- CarBassMatterInqire.java
- CarBassMatterInqireLog.java
- CarLedgerFrmbk.java
- CarLedgerFrmbkDtl.java
- CarLedgerFrmbkLog.java
- VehicleBasicInfo.java
- VehicleLedger.java
주의사항:
- Lombok 어노테이션 유지 (
@Getter,@Setter,@Builder등) java.time.*클래스 사용 가능 (Java 8+)jakarta.validation.*→javax.validation.*변경
5.2 VO 클래스 (7개)
변경 예시:
// Before
package com.vmis.interfaceapp.model.vo;
import jakarta.validation.constraints.NotBlank;
// After
package go.kr.project.vmis.model.vo;
import javax.validation.constraints.NotBlank;
파일 목록:
- CarBassMatterInqireRequestVO.java
- CarLedgerFrmbkRequestVO.java
- Envelope.java
- GovApiBasicRequest.java
- GovApiBasicResponse.java
- GovApiLedgerRequest.java
- GovApiLedgerResponse.java
5.3 DTO 클래스 (2개)
패키지 변경:
// Before
package com.vmis.interfaceapp.model.dto;
// After
package go.kr.project.vmis.model.dto;
파일 목록:
- VehicleBasicInfoDTO.java
- VehicleLedgerDTO.java
Step 6: Config 클래스 이식
6.1 MyBatisConfig.java
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\config\MyBatisConfig.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\config\VmisMyBatisConfig.java (이름 변경)
변경 사항:
// Before
package com.vmis.interfaceapp.config;
import org.mybatis.spring.annotation.MapperScan;
@Configuration
@MapperScan("com.vmis.interfaceapp.mapper")
public class MyBatisConfig {
// ...
}
// After
package go.kr.project.vmis.config;
import org.mybatis.spring.annotation.MapperScan;
@Configuration
@MapperScan("go.kr.project.vmis.mapper")
public class VmisMyBatisConfig {
// ...
}
주의: VIPS에 이미 MyBatis 설정이 있으므로 클래스명을 변경하여 충돌 방지
6.2 OpenApiConfig.java
변경 사항:
// Before
package com.vmis.interfaceapp.config;
// After
package go.kr.project.vmis.config;
// import 패키지 변경
import go.kr.project.vmis.model.vo.*;
Step 7: Mapper 이식
7.1 Mapper 인터페이스
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\mapper\
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\mapper\
변경 사항:
// Before
package com.vmis.interfaceapp.mapper;
import com.vmis.interfaceapp.model.entity.CarBassMatterInqireLog;
// After
package go.kr.project.vmis.mapper;
import go.kr.project.vmis.model.entity.CarBassMatterInqireLog;
파일 목록:
- CarBassMatterInqireLogMapper.java
- CarLedgerFrmbkLogMapper.java
7.2 Mapper XML
소스: D:\workspace\git\VMIS-interface\src\main\resources\mybatis\mapper\
대상: D:\workspace\git\VIPS\src\main\resources\mybatis\mapper\vmis\
CarBassMatterInqireLogMapper_maria.xml 변경 예시:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- Before -->
<mapper namespace="com.vmis.interfaceapp.mapper.CarBassMatterInqireLogMapper">
<resultMap id="CarBassMatterInqireLogResultMap"
type="com.vmis.interfaceapp.model.entity.CarBassMatterInqireLog">
<!-- After -->
<mapper namespace="go.kr.project.vmis.mapper.CarBassMatterInqireLogMapper">
<resultMap id="CarBassMatterInqireLogResultMap"
type="go.kr.project.vmis.model.entity.CarBassMatterInqireLog">
파일 목록:
- CarBassMatterInqireLogMapper_maria.xml
- CarLedgerFrmbkLogMapper_maria.xml
Step 8: Enricher 이식
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\enricher\RequestEnricher.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\enricher\RequestEnricher.java
변경 사항:
// Before
package com.vmis.interfaceapp.enricher;
import com.vmis.interfaceapp.config.VmisProperties;
import com.vmis.interfaceapp.util.TransactionIdGenerator;
// After
package go.kr.project.vmis.enricher;
import go.kr.project.vmis.config.VmisProperties;
import go.kr.project.vmis.util.TransactionIdGenerator;
Step 9: GovernmentApiClient 이식 (가장 복잡)
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\client\GovernmentApiClient.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\client\GovernmentApiClient.java
HttpClient 5 → 4 변경:
// Before (HttpClient 5)
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.ContentType;
// After (HttpClient 4)
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.ContentType;
주요 API 변경:
// Before (HttpClient 5)
StringEntity entity = new StringEntity(jsonBody, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
String responseBody = EntityUtils.toString(response.getEntity());
}
// After (HttpClient 4)
StringEntity entity = new StringEntity(jsonBody, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
String responseBody = EntityUtils.toString(response.getEntity());
} finally {
if (response != null) {
response.close();
}
}
전체 변경 템플릿:
package go.kr.project.vmis.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import go.kr.project.vmis.config.VmisProperties;
import go.kr.project.vmis.enricher.RequestEnricher;
import go.kr.project.vmis.model.vo.*;
import go.kr.project.vmis.util.EncryptionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
@Slf4j
@Component
@RequiredArgsConstructor
public class GovernmentApiClient {
private final VmisProperties vmisProperties;
private final RequestEnricher requestEnricher;
private final EncryptionUtil encryptionUtil;
private final ObjectMapper objectMapper;
public GovApiBasicResponse callBasicInfoApi(String vhrno) {
// 기존 로직 유지, HttpClient 4 API로 변경
// ...
}
public GovApiLedgerResponse callLedgerInfoApi(String vhrno) {
// 기존 로직 유지, HttpClient 4 API로 변경
// ...
}
private CloseableHttpClient createHttpClient() {
return HttpClientBuilder.create()
.setConnectionTimeToLive(vmisProperties.getGovernment().getConnectTimeout(),
java.util.concurrent.TimeUnit.MILLISECONDS)
.build();
}
}
Step 10: Service 계층 이식
패키지 변경:
// Before
package com.vmis.interfaceapp.service;
import com.vmis.interfaceapp.client.GovernmentApiClient;
import com.vmis.interfaceapp.mapper.*;
import com.vmis.interfaceapp.model.*;
// After
package go.kr.project.vmis.service;
import go.kr.project.vmis.client.GovernmentApiClient;
import go.kr.project.vmis.mapper.*;
import go.kr.project.vmis.model.*;
파일 목록:
- CarBassMatterInqireLogService.java
- CarLedgerFrmbkLogService.java
- CarBassMatterInqireService.java
- CarLedgerFrmbkService.java
주의사항:
@Service어노테이션 유지@Transactional설정 확인
Step 11: Controller 이식
소스: D:\workspace\git\VMIS-interface\src\main\java\com\vmis\interfaceapp\controller\VehicleInterfaceController.java
대상: D:\workspace\git\VIPS\src\main\java\go\kr\project\vmis\controller\VehicleInterfaceController.java
주요 변경 사항:
// Before
package com.vmis.interfaceapp.controller;
import com.vmis.interfaceapp.service.*;
import com.vmis.interfaceapp.model.vo.*;
import jakarta.validation.Valid;
@RestController
@RequestMapping("/api/v1/vehicles")
// After
package go.kr.project.vmis.controller;
import go.kr.project.vmis.service.*;
import go.kr.project.vmis.model.vo.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/vmis/api/v1/vehicles") // 경로 변경 고려
API 경로 충돌 방지:
- 기존 VIPS:
/api/v1/vehicles(ExternalVehicleApiService가 사용) - 새로운 VMIS:
/vmis/api/v1/vehicles또는/internal/vehicles
Step 12: 데이터베이스 확인
데이터베이스 테이블은 이미 존재합니다 (VIPS와 VMIS-interface가 동일한 DB 사용)
테이블 존재 확인:
-- 1. 테이블 존재 확인
SHOW TABLES LIKE 'tb_car_bass_matter_inqire%';
SHOW TABLES LIKE 'tb_car_ledger_frmbk%';
-- 2. 시퀀스 존재 확인
SHOW TABLES LIKE 'seq_car_%';
-- 예상 결과: 6개 항목
-- tb_car_bass_matter_inqire_log
-- seq_car_bass_matter_inqire
-- tb_car_ledger_frmbk
-- seq_car_ledger_frmbk
-- tb_car_ledger_frmbk_dtl
-- seq_car_ledger_frmbk_dtl
테이블 구조 확인 (선택사항):
DESC tb_car_bass_matter_inqire_log;
DESC tb_car_ledger_frmbk;
DESC tb_car_ledger_frmbk_dtl;
Phase 5: 빌드 및 테스트
5.1 Gradle 빌드
cd D:\workspace\git\VIPS
# Clean 빌드
gradlew clean build
# 빌드 성공 확인
# BUILD SUCCESSFUL 메시지 확인
5.2 애플리케이션 구동
# Spring Boot 실행
gradlew bootRun
# 또는
java -jar build/libs/VIPS-BOOT.war
5.3 로그 확인
로그 파일 위치 확인 (logback-spring.xml 참조)
- 구동 시 에러 로그 확인
- Bean 생성 확인 (VmisProperties, GovernmentApiClient 등)
5.4 API 테스트
Swagger UI 접속
http://localhost:8080/swagger-ui/index.html
직접 API 호출 (PowerShell)
# 기본사항 조회 테스트
Invoke-RestMethod -Uri "http://localhost:8080/vmis/api/v1/vehicles/basic" `
-Method POST `
-ContentType "application/json" `
-Body '{"vhrno":"12가3456"}' | ConvertTo-Json -Depth 10
# 등록원부 조회 테스트
Invoke-RestMethod -Uri "http://localhost:8080/vmis/api/v1/vehicles/ledger" `
-Method POST `
-ContentType "application/json" `
-Body '{"vhrno":"12가3456"}' | ConvertTo-Json -Depth 10
cURL (Git Bash)
# 기본사항 조회
curl -X POST http://localhost:8080/vmis/api/v1/vehicles/basic \
-H "Content-Type: application/json" \
-d '{"vhrno":"12가3456"}'
# 등록원부 조회
curl -X POST http://localhost:8080/vmis/api/v1/vehicles/ledger \
-H "Content-Type: application/json" \
-d '{"vhrno":"12가3456"}'
5.5 데이터베이스 확인
-- 로그 테이블 확인
SELECT * FROM tb_car_bass_matter_inqire_log ORDER BY reg_dt DESC LIMIT 10;
SELECT * FROM tb_car_ledger_frmbk_log ORDER BY reg_dt DESC LIMIT 10;
-- 데이터 저장 확인
SELECT * FROM tb_car_ledger_frmbk ORDER BY reg_dt DESC LIMIT 10;
SELECT * FROM tb_car_ledger_frmbk_dtl ORDER BY reg_dt DESC LIMIT 10;
Phase 6: 트러블슈팅
6.1 빌드 오류
오류 1: Package jakarta.* does not exist
원인: jakarta 패키지 미변경
해결: 전체 프로젝트에서 jakarta → javax 일괄 변경
# IntelliJ IDEA
Ctrl+Shift+R → "jakarta." → "javax."
오류 2: Cannot resolve symbol 'HttpClients'
원인: HttpClient 5 import 문 사용
해결: org.apache.hc.client5.* → org.apache.http.* 변경
오류 3: Bean creation error - VmisProperties
원인: @ConfigurationProperties 스캔 누락
해결: @Component 어노테이션 추가 또는
@EnableConfigurationProperties(VmisProperties.class) 추가
6.2 런타임 오류
오류 1: Mapper not found
원인: MyBatis mapper-locations 설정 누락
해결: application.yml에 vmis 매퍼 경로 추가
mybatis:
mapper-locations:
- classpath:mybatis/mapper/**/*_maria.xml
- classpath:mybatis/mapper/vmis/**/*_maria.xml
오류 2: GPKI 라이브러리 로드 실패
원인: libgpkiapi_jni_1.5.jar 경로 문제
해결:
1. lib 디렉토리 확인
2. build.gradle에 files('lib/...') 추가 확인
3. 개발환경에서는 vmis.gpki.enabled=false 설정
오류 3: API 호출 타임아웃
원인: 정부 API 호스트 연결 불가
해결:
1. 네트워크 연결 확인
2. 방화벽 설정 확인
3. API 키 유효성 확인
4. vmis.government.connect-timeout 값 증가
6.3 데이터베이스 오류
오류 1: Table doesn't exist
원인: DDL 미실행
해결: ddl/vips/*.sql 파일 실행
오류 2: Sequence not found
원인: 시퀀스 미생성
해결: seq_*.sql 파일 먼저 실행
6.4 API 응답 오류
오류 1: 401 Unauthorized
원인: API 키 오류
해결: application.yml의 GOV_API_KEY_* 환경변수 확인
오류 2: 500 Internal Server Error
원인: 암호화 실패
해결:
1. 개발환경에서는 vmis.gpki.enabled=false 설정
2. 운영환경에서는 인증서 경로 확인
Phase 7: 기존 코드 리팩토링
7.1 ExternalVehicleApiService 수정
파일: D:\workspace\git\VIPS\src\main\java\go\kr\project\externalApi\service\ExternalVehicleApiService.java
변경 전 (REST API 호출):
@Service
public class ExternalVehicleApiService {
private final RestTemplate restTemplate;
private final String VMIS_API_URL = "http://localhost:8081/api/v1/vehicles";
public VehicleApiResponseVO getBasicInfo(String vhrno) {
String url = VMIS_API_URL + "/basic";
// RestTemplate으로 HTTP 호출...
}
}
변경 후 (내부 메서드 호출):
@Service
@RequiredArgsConstructor
public class ExternalVehicleApiService {
private final CarBassMatterInqireService carBassMatterInqireService;
private final CarLedgerFrmbkService carLedgerFrmbkService;
public VehicleApiResponseVO getBasicInfo(String vhrno) {
// 내부 서비스 직접 호출
CarBassMatterInqireRequestVO request = new CarBassMatterInqireRequestVO();
request.setVhrno(vhrno);
Envelope<VehicleBasicInfoDTO> response =
carBassMatterInqireService.getBasicInfo(request);
// DTO → VO 변환 로직...
return convertToApiResponse(response);
}
public VehicleApiResponseVO getLedgerInfo(String vhrno) {
CarLedgerFrmbkRequestVO request = new CarLedgerFrmbkRequestVO();
request.setVhrno(vhrno);
Envelope<VehicleLedgerDTO> response =
carLedgerFrmbkService.getLedgerInfo(request);
return convertToApiResponse(response);
}
private VehicleApiResponseVO convertToApiResponse(Envelope<?> envelope) {
// 변환 로직...
}
}
7.2 RestTemplate 설정 정리
옵션 1: RestTemplate 설정 유지 (향후 다른 외부 API 사용 가능) 옵션 2: 미사용 시 주석 처리
// RestTemplateConfig.java
// @Configuration // 주석 처리
public class RestTemplateConfig {
// ...
}
Phase 8: 문서화 및 배포
8.1 API 문서 업데이트
Swagger 어노테이션 추가 (VehicleInterfaceController.java):
@RestController
@RequestMapping("/vmis/api/v1/vehicles")
@Tag(name = "VMIS 차량 정보 조회", description = "도로교통공단 API 연동")
public class VehicleInterfaceController {
@PostMapping("/basic")
@Operation(summary = "자동차 기본사항 조회",
description = "차량번호로 기본사항 조회")
public ResponseEntity<Envelope<VehicleBasicInfoDTO>> getBasicInfo(
@Valid @RequestBody CarBassMatterInqireRequestVO request) {
// ...
}
}
8.2 환경변수 설정 가이드
application-prd.yml 예시:
vmis:
system:
info-sys-id: "${VMIS_SYSTEM_ID}"
info-sys-ip: "${SERVER_IP}"
manager-id: "${VMIS_MANAGER_ID}"
manager-name: "${VMIS_MANAGER_NAME}"
manager-tel: "${VMIS_MANAGER_TEL}"
gpki:
enabled: true
cert-path: "${GPKI_CERT_PATH}"
private-key-path: "${GPKI_PRIVATE_KEY_PATH}"
private-key-password: "${GPKI_PASSWORD}"
government:
services:
basic:
api-key: "${GOV_API_KEY_BASIC}"
ledger:
api-key: "${GOV_API_KEY_LEDGER}"
환경변수 설정 스크립트 (setenv.bat):
@echo off
REM VMIS 환경변수 설정
SET VMIS_SYSTEM_ID=VMIS001
SET SERVER_IP=192.168.1.100
SET VMIS_MANAGER_ID=admin
SET VMIS_MANAGER_NAME=관리자
SET VMIS_MANAGER_TEL=02-1234-5678
SET GPKI_CERT_PATH=C:\gpki\cert.der
SET GPKI_PRIVATE_KEY_PATH=C:\gpki\private.key
SET GPKI_PASSWORD=your-password
SET GOV_API_KEY_BASIC=your-api-key-basic
SET GOV_API_KEY_LEDGER=your-api-key-ledger
echo VMIS 환경변수 설정 완료
8.3 Git Commit
# 모든 변경사항 스테이징
git add .
# 커밋
git commit -m "VMIS-interface 통합: 도로교통공단 API 연동 모듈 내재화
- VMIS-interface 전체 코드 이식 (34개 파일)
- Spring Boot 3 → 2.7 다운그레이드
- jakarta → javax 패키지 변경
- HttpClient 5 → 4 변경
- 패키지 구조: go.kr.project.vmis.*
- 데이터베이스 테이블 추가 (6개)
- ExternalVehicleApiService 내부 호출로 리팩토링
Co-Authored-By: Claude <noreply@anthropic.com>"
# 푸시
git push origin feature/vmis-integration
8.4 Pull Request 생성
# GitHub CLI 사용
gh pr create --title "VMIS-interface 통합" \
--body "## 개요
도로교통공단 API 연동 모듈(VMIS-interface)을 VIPS 내부로 통합
## 주요 변경사항
- Spring Boot 2.7 호환 코드로 변경
- 34개 Java 파일 이식
- 6개 데이터베이스 테이블 추가
- 내부 메서드 호출로 성능 개선
## 테스트
- [x] 빌드 성공
- [x] API 호출 테스트
- [x] 데이터베이스 저장 확인
## 체크리스트
- [x] 코드 리뷰 완료
- [x] 테스트 통과
- [x] 문서 업데이트
"
체크리스트
Phase 1: 사전 준비
- 현재 브랜치 상태 확인 (이미 생성됨)
- 디렉토리 구조 생성
- GPKI 라이브러리 복사
Phase 2: 설정
- build.gradle 의존성 추가
- application.yml 설정 통합
- VmisProperties 이식
Phase 3: 유틸리티 및 모델
- TransactionIdGenerator 이식
- EncryptionUtil 이식
- Entity 클래스 이식 (7개)
- VO 클래스 이식 (7개)
- DTO 클래스 이식 (2개)
Phase 4: 핵심 로직
- Config 클래스 이식 (2개)
- Mapper 인터페이스 이식 (2개)
- Mapper XML 이식 (2개)
- RequestEnricher 이식
- GovernmentApiClient 이식 (HttpClient 4 변경)
- Service 클래스 이식 (4개)
- Controller 이식
Phase 5: 데이터베이스
- 테이블 존재 확인 (6개 테이블/시퀀스 - 이미 존재)
Phase 6: 빌드 및 테스트
- Gradle 빌드 성공
- 애플리케이션 구동 확인
- Swagger UI 확인
- API 호출 테스트 (/basic)
- API 호출 테스트 (/ledger)
- 데이터베이스 저장 확인
Phase 7: 리팩토링
- ExternalVehicleApiService 수정
- 불필요한 코드 제거
Phase 8: 마무리
- API 문서 업데이트
- 환경변수 가이드 작성
- Git 커밋
- Pull Request 생성
참고 자료
- Spring Boot 2.7 문서: https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/
- MyBatis Spring Boot: https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
- Apache HttpClient 4: https://hc.apache.org/httpcomponents-client-4.5.x/
작업 진행 방법: 브랜치는 이미 생성되어 있으므로, Phase 1의 디렉토리 구조 준비부터 시작하세요.
cd D:\workspace\git\VIPS
git status # 현재 브랜치 확인
문서 버전: 1.1 최종 수정: 2025-11-06