레거시 현대화

본사·해외법인 파일 다운로드 플랫폼(DNA2) 레거시 현대화 및 통합

본사·유럽법인의 결과 파일을 제공하는 다운로드 플랫폼(DNA2)을 Spring Boot 기반 단일 프로젝트로 통합하고, DB 연결·DB Link·배포 구조와 결과 다운로드 기준을 개선했습니다.

기간
2025.03 — 2025.08
상태
운영 반영
역량
레거시 분석 · 호환성 설계
요청별 → 공용DB 연결 관리
16 → 2성공·실패 화면
557기능테스트 케이스
전환 범위
본사 Model2·유럽법인 Model1의 결과 다운로드 기능과 배포 구조
유지해야 한 호출 방식
기존 URL·축약 파라미터·파일명·압축 구성·예외 응답
완료 기준
20개 기능테스트 시나리오·557개 테스트 케이스, DB 연결 방식 개선, 단계별 운영 안정화

CASE STUDY

한눈에 보는 변화

본사와 유럽법인에서 따로 운영하던 다운로드 기능을 Spring Boot 기반 단일 프로젝트로 합쳤습니다. 이 과정에서 다른 시스템과 고객이 사용하던 URL·파라미터·파일 구성은 유지하고, 요청마다 생성되던 DB 객체는 애플리케이션이 공용으로 관리하도록 바꿨습니다.

본사와 유럽법인에 비슷한 다운로드 기능이 서로 다른 방식으로 중복 구현되어 있었습니다. 요청마다 Connection Pool과 SessionFactory가 생성됐고, DB Link와 법인별 배포 방식에도 크게 의존했습니다. 이를 개선하면서 고객이 사용하던 URL·파라미터·파일명·압축 구성은 그대로 유지해야 했습니다.

직접 담당한 범위

  • 본사 Model2와 유럽법인 Model1 구조의 AS-IS/TO-BE 및 Gap Analysis 작성
  • 공통 구조 설계와 핵심 다운로드·검증·예외 처리 개발
  • 기능테스트와 본사·유럽법인 별도 통합테스트, 단계별 배포와 운영 안정화 주도
프로젝트 변경 전후 비교
구분변경 전변경 후확인된 변화
DB 객체 생명주기요청마다 Connection Pool을 만들고 쿼리 경로에서 SqlSessionFactory를 반복 생성DB별 DataSource와 SqlSessionFactory를 애플리케이션 공용 객체로 관리요청마다 생성되던 Connection Pool 제거
DB 접근 경로구형·신형 LIMS 접근과 DB Link가 코드 안에서 혼재용도별 DataSource를 분리하고 필요한 구간은 직접 DB 접근으로 전환접근 대상과 Pool 소유 관계 명확화
법인별 코드·배포본사 Model2와 유럽법인 Model1에 유사 기능이 중복애플리케이션 코드는 통합하고 Build Profile·설정·배포 흐름은 분리본사·유럽법인 단일 프로젝트
성공·실패 처리기능과 법인에 따라 성공·실패 화면 16개가 분산메시지와 예외 전달 규칙을 정리해 공통 화면 2개로 통합16개 → 2개
요청 호환·다국어레거시 URL·법인별 언어 규칙과 하드코딩 메시지가 혼재원 URL·법인 Profile로 Locale을 먼저 확정하고 DB MessageSource와 내부 Forward에 연결기존 호출 URL을 유지한 Spring 요청 생명주기
입력·접근 검증Service마다 필수값·경로 검증이 반복되고 호출별 차이가 코드에 분산Validation Group을 메서드별로 조합하고 경로·주문 고객 검증은 별도 책임으로 분리호출별 Validation Group을 선언적으로 구성

EVIDENCE CHAIN

문제를 좁힌 과정

  1. 01 · 현행 비교

    Connection을 소유한 Pool의 생성 횟수까지 추적했습니다

    DNA2에서 DB Connection 232개가 유지되는 상태를 확인하고, 본사 Model2·유럽법인 Model1의 DB 접근과 요청 처리를 기능별로 비교했습니다. 개별 쿼리 종료 여부만으로는 이 현상을 설명할 수 없었습니다.

    판단Connection 한 개의 close 누락과 Connection을 소유하는 Pool 자체의 반복 생성을 분리해 확인해야 했습니다.

  2. 02 · 호출 경로 추적

    요청과 쿼리 코드가 인프라 객체까지 만들고 있었습니다

    요청 진입점부터 설정 로드, DataSource 생성, MyBatis 설정, SqlSessionFactory 생성과 쿼리 실행까지 역추적했습니다. 요청마다 Pool이 만들어지고 쿼리 경로에서 SqlSessionFactory가 다시 생성되는 것을 확인했습니다.

    판단SqlSession을 닫아도 Connection은 새로 만든 Pool로 돌아갈 뿐이므로, Pool의 생명주기를 애플리케이션 단위로 올려야 했습니다.

  3. 03 · 변경 제약 수집

    기존 호출 방식을 회귀 테스트 기준으로 만들었습니다

    LIMS·COMS와 메일 링크가 사용하던 URL, 축약 파라미터, 파일명, 경로, 압축 구성과 예외 응답을 기능별로 목록화했습니다. 내부 명칭을 정리하더라도 외부에서 보내는 요청 형식은 그대로 유지해야 했습니다.

    판단내부 구현이 바뀌어도 같은 요청에 같은 결과를 돌려주는지를 성공 기준으로 삼았습니다.

  4. 04 · 기능 검증

    최초 548건 성공에서 멈추지 않고 차이가 난 9건을 분리했습니다

    20개 기능테스트 시나리오, 557개 테스트 케이스를 실행해 최초 548건 성공과 9건 실패를 확인했습니다. 실패 항목을 기능별 결함으로 분리해 수정한 뒤 전체 557건을 다시 검증했습니다. 본사·유럽법인 통합테스트는 별도 시나리오로 수행했습니다.

    판단기능테스트 557개 수치와 별도 통합테스트를 구분하고, 두 검증 범위를 모두 통과해야 전환을 완료할 수 있었습니다.

  5. 05 · 운영 안정화

    배포 뒤 나타난 세 가지 문제를 따로 재현했습니다

    대용량 ZIP 처리, 동일 파일명 충돌, 구형 JDBC Driver 선로딩이 차례로 나타났습니다. 압축 로직·파일 구성·JVM Class Loading을 각각 확인해 원인을 분리했습니다.

    판단코드 전환을 마친 뒤에도 실제 실행 환경을 확인하고 운영 문제를 안정화해야 했습니다.

DECISION LOG

검토한 대안과 선택 근거

제외

Connection close 경로만 보완

개별 세션이 반환돼도 요청마다 새 Pool이 만들어지는 생명주기 문제는 남기 때문입니다.

제외

기존 DB Link 중심 접근 유지

실제로 어느 DB에 접근하는지 코드에서 알아보기 어렵고 법인별 의존성도 계속 남기 때문입니다.

제외

법인별 Branch 분리

법인별 최적화는 쉽지만 공통 기능 Merge 충돌과 법인 추가 시 Branch 증가가 예상됐고, 현행 분석에서 본사·유럽 기능의 공통성이 더 높았기 때문입니다.

선택

단일 소스 + Active Profile·Build Profile

공통 코드는 한 곳에서 유지하고 법인별 분기는 Active Profile로, 접속정보와 배포 산출물은 Build Profile로 분리할 수 있었습니다.

선택

단일 코드 + 명시적 복수 DataSource

공통 로직을 한 곳에서 관리하면서 구형·신형 LIMS의 접근 대상과 인프라 객체 소유 관계를 명확히 할 수 있었습니다.

IMPLEMENTATION

설계와 구현

DB 인프라 생명주기

  • 구형·신형 LIMS의 XA DataSource와 MyBatis 접근 계층을 각각 분리
  • 조건에 따라 다른 Mapper를 사용하는 Service가 같은 @Transactional 선언을 쓰도록 Atomikos JTA 구성
  • DB Link 의존 구간을 직접 DataSource 접근으로 전환하고 유럽 Profile에서는 미사용 LIMS 2.0 구성을 비활성화

URL·요청 호환 계층

  • 레거시 화면 요청을 내부 Controller로 Forward하고 정적 리소스 경로를 신규 위치에 매핑
  • HandlerMethodArgumentResolver가 레거시 축약 파라미터를 의미가 드러나는 DTO 필드로 변환
  • 기존 파일명·압축 구성·다운로드 결과와 오류 응답을 회귀 기준으로 고정

Locale·메시지 생명주기

  • 원 요청 URL과 법인 Profile로 Locale을 먼저 확정해 내부 Forward 전 언어 정보 보존
  • LocaleContextHolder와 DB MessageSource를 Controller·Service·예외 처리·Bean Validation에 연결
  • 운영은 메시지 사전 적재, 개발·로컬은 지연 적재를 적용하고 요청 종료 시 커스텀 ThreadLocal 제거

호출 맥락별 검증

  • 동일 DTO의 필드 제약에 의미 단위 Validation Group을 부여하고 호출 메서드별로 조합
  • Spring AOP가 Controller 인자에서 대상 DTO를 찾아 표준 Validator를 Group 순서대로 실행
  • 파일 경로의 '..' 검사와 요청 고객·실제 주문 고객 일치 검증은 구조·필수값 검증과 분리

법인별 설정·배포

  • 본사와 유럽법인 애플리케이션 코드를 하나의 프로젝트로 통합
  • 법인별 설정, Build Profile과 Jenkins 배포 흐름은 독립적으로 유지
  • 각 법인의 DB 접근 경로와 환경 차이는 설정으로 분리

다운로드·운영 안정화

  • 파일명·압축 구성·시퀀스 길이 계산과 분석 결과 예외 기준 개선
  • 유럽법인 자동발송 결과 압축에 필요한 결과 파일이 포함되도록 보완
  • 대용량 압축 처리와 ZIP 내부 동일 파일명 충돌 보완
  • JVM Class Loading 로그로 애플리케이션 의존성과 실제 JDBC Driver 차이 확인
  • 본사 자동발송 모듈의 불필요한 구형 JDBC Driver 의존 제거

VERIFICATION

테스트 매트릭스

프로젝트 테스트와 완료 기준
검증 영역검증 방법완료 기준
기존 호출 방식기존 .jsp URL·축약 파라미터와 언어 경로를 동일하게 호출Forward 이후에도 본사·유럽법인별 다운로드·Locale·오류 결과 유지
입력·접근 검증API별 필수 Group, '..' 경로와 주문 고객 불일치 요청 확인호출별 선택 필드는 허용하고 비정상 경로·고객 불일치는 업무 처리 전 차단
파일 결과파일명·압축 구성·분석 결과 예외를 전후 비교기존 사용자가 받는 결과 형식 유지
DB 접근구형·신형 LIMS 직접 연결과 기존 조회 결과 대조조회 결과가 같고 요청을 반복해도 Pool이 추가로 생성되지 않음
기능테스트20개 시나리오·557개 테스트 케이스 수행최초 실패 9건 수정 후 557건 전체 통과
법인 통합 흐름본사·유럽법인 통합테스트를 별도 시나리오로 수행557개 기능테스트 수치와 분리해 연계·다운로드 흐름 확인
운영 안정화단계별 배포 후 연결 수·로그·대용량 다운로드 관찰요청마다 Pool을 만들지 않고 주요 다운로드 기능이 정상 동작
자동발송 모듈 후속 안정화필수 결과 파일 포함과 JDBC 패키징 변경 관련 검증자동발송 결과 구성 유지 및 불필요한 구형 JDBC Driver 의존 제거

OPERATION

운영 반영과 후속 안정화

운영 이슈

대용량 ZIP 처리 지연

분리한 원인
일반 다운로드와 달리 압축 시간에 영향을 받는 타임아웃 문제로 분리
대응
대용량 압축 시간을 고려하도록 처리 흐름 보완
운영 이슈

ZIP 내부 동일 파일명 충돌

분리한 원인
서로 다른 경로의 파일이 같은 이름으로 압축될 때 발생하는 충돌 재현
대응
압축 구성 단계의 파일명 충돌 처리 보완
운영 이슈

JDBC API 실행 불일치

분리한 원인
JVM Class Loading 로그로 JRE Extension 경로의 구형 Driver 선로딩 확인
대응
코드 결함과 운영 런타임 Driver 충돌을 분리해 대응
확인된 결과
  • 요청마다 만들던 Connection Pool과 SessionFactory를 애플리케이션 공용 객체로 전환
  • 성공·실패 화면 16개를 공통 화면 2개로 통합
  • 본사·유럽법인 유사 기능을 단일 프로젝트와 공통 코드로 재구성
  • 20개 기능테스트 시나리오, 총 557개 테스트 케이스 통과
  • 다운로드 시스템과 자동발송 모듈의 JDBC Driver 로딩·패키징 충돌 요인을 함께 제거

TAKEAWAYS

이 사례에서 드러난 역량

  • Connection 수가 많을 때 close()만 찾지 않고 Pool과 SessionFactory가 몇 번 생성되는지 확인해야 합니다.
  • 레거시 현대화에서는 내부 코드가 바뀐 뒤에도 기존 호출 방식과 결과가 유지되는지 확인해야 합니다.
  • 공통 코드는 통합하더라도 법인별 설정과 배포 책임까지 억지로 하나로 묶을 필요는 없습니다.
  • 운영 배포 뒤 나타난 문제는 전환 실패로 뭉뚱그리지 않고 압축·파일·런타임 문제로 나눠 확인해야 합니다.
레거시 분석호환성 설계다법인 통합운영 안정화

사용 기술

Java 8Spring Boot 2.7.5MavenMyBatisOracle/MySQLLog4j2ThymeleafJenkinsZIPAtomikos