레거시 현대화 · Legacy Modernization

레거시 요청 계약을 유지한 DTO 파라미터 매핑 구조

기존 URL과 연계 시스템의 축약형 파라미터 규격은 유지하면서, Spring MVC 확장으로 내부 DTO에 의미가 명확한 필드명을 적용한 과정입니다.

Spring MVCHandlerMethodArgumentResolverBackward CompatibilityCustom Annotation

배경과 문제

기존 다운로드·결과 조회 기능은 의미를 파악하기 어려운 축약형 요청 파라미터를 사용하고 있었다. 이 값은 현재 화면뿐 아니라 기존 시스템이 생성한 URL, 메일 링크와 다른 업무 시스템의 호출 계약에 연결돼 있었다.

파라미터명을 일괄 변경하면 기존 링크와 호출 시스템을 함께 수정해야 했다. 반대로 레거시 이름을 신규 DTO 필드명으로 그대로 사용하면 업무 의미가 드러나지 않고 과거 명명 규칙이 새 코드까지 전파된다.

설계 판단

외부 파라미터 규격은 유지하되 애플리케이션 내부에서는 업무 의미가 명확한 이름을 사용하도록 요청과 DTO 사이에 매핑 계층을 뒀다. 실제 커스텀 Annotation, Resolver, DTO와 레거시 파라미터명은 공개하지 않고 일반적인 가명으로 바꿨다.

아래 코드는 문제 해결 구조를 설명하기 위한 pseudocode이며 실제 클래스·테이블·설정 이름과는 무관합니다.

public class DownloadRequest {

    @LegacyAlias("legacyUserKey")
    private String userKey;

    @LegacyAlias("legacyOrderKey")
    private String orderKey;

    @LegacyAlias("legacyItemKey")
    private Integer itemSequence;
}

외부 계약과 내부 모델의 분리

기존 요청 형식은 변경하지 않는다. 매핑 계층이 레거시 별칭을 의미가 명확한 DTO 필드로 변환하므로 Controller와 Service는 과거 명명 규칙을 알 필요가 없다.

아래 코드는 문제 해결 구조를 설명하기 위한 pseudocode이며 실제 클래스·테이블·설정 이름과는 무관합니다.

// 공개용 예시 요청
// /download?legacyUserKey=user&legacyOrderKey=order&legacyItemKey=1

public FileResult download(DownloadRequest request) {
    return downloadService.findFile(
        request.getUserKey(),
        request.getOrderKey(),
        request.getItemSequence()
    );
}

매핑 계층의 책임

  • DTO 필드에 레거시 요청 별칭을 선언한다.
  • 한 필드가 여러 과거 별칭을 수용할 수 있게 한다.
  • 선언된 별칭을 우선순위에 따라 탐색한다.
  • 별칭이 없으면 DTO 필드명과 같은 요청 값을 확인한다.
  • Spring의 표준 변환 기능으로 문자열을 대상 자료형으로 바꾼다.
  • 단일 값과 배열 값을 구분한다.

Spring MVC의 Argument Resolver 확장 지점을 사용해 Controller마다 파라미터 조회와 변환 코드를 반복하지 않게 했다.

검증

  • 기존 요청 URL과 메일 링크가 그대로 동작하는지 확인했다.
  • 복수 별칭 중 우선순위가 의도대로 적용되는지 확인했다.
  • 숫자·문자열·배열 변환 실패가 명시적 오류로 전달되는지 확인했다.
  • 매핑 후 Controller와 Service에 레거시 이름이 전파되지 않는지 확인했다.
  • 기존 파일명·압축 결과·오류 응답 계약이 유지되는지 전체 회귀 범위에서 확인했다.

미확정 수치 처리

기존 글의 DTO 개수와 파라미터 매핑 개수는 소스에서 집계한 값이었지만 최신 경력 마스터에 근거와 산출 기준이 없다. 이번 작업에서는 신규 경력 사실로 확정하지 않고 정성 표현으로 바꿨다.

적용 개수와 집계 기준은 추가 확인이 필요하다. 공개 글에는 “여러 레거시 DTO와 요청 별칭에 공통 매핑을 적용했다”는 확인 가능한 구조만 남긴다.

적용 결과

  • 기존 URL과 연계 시스템의 요청 규격을 바꾸지 않고 신규 코드의 가독성을 개선했다.
  • 레거시 파라미터명이 Service와 업무 코드까지 전파되는 문제를 줄였다.
  • Controller마다 반복되던 요청 조회·변환 로직을 공통 계층으로 모았다.
  • 변경하기 어려운 외부 계약과 개선 가능한 내부 객체 모델을 분리했다.

정리

이 개선은 파라미터명을 단순히 바꾼 작업이 아니다. 운영 중인 외부 호출 계약을 보호하면서 내부 모델을 점진적으로 개선한 사례다. 레거시 현대화에서는 바꾸기 어려운 계약과 바꿀 수 있는 내부 경계를 먼저 분리해야 한다.

TECHNICAL SERIES

DNA2 레거시 현대화

연결 생명주기와 DB 경계부터 요청 계약, 다국어 처리, 검증과 런타임 충돌까지 이어지는 현대화 과정입니다.

시리즈 전체 보기

현재 4/6

  1. 1요청마다 Connection Pool과 SessionFactory를 만들면 생기는 문제
  2. 2DB Link를 제거한 뒤 남은 문제: 복수 DataSource의 트랜잭션 경계
  3. 3레거시 URL이 언어를 결정할 때: 기존 계약을 유지하며 Spring Locale 처리로 전환하기
  4. 4레거시 요청 계약을 유지한 DTO 파라미터 매핑 구조
  5. 5같은 DTO인데 API마다 필수값이 달랐다: Validation Group을 호출별로 조합한 이유
  6. 6JVM Class Loading 로그로 추적한 Oracle JDBC Driver 충돌