레거시 현대화 · Legacy Modernization

레거시 URL의 언어 규칙을 Spring Locale로 연결하기

브라우저 설정이 아니라 URL과 법인 환경으로 언어를 정하던 시스템에서, 기존 호출 규칙을 유지하면서 요청 처리 전에 로케일을 결정했습니다.

Spring MVCMessageSourceLocaleBackward Compatibility

URL과 법인 설정이 언어를 결정했습니다

이 시스템의 언어는 브라우저가 보내는 Accept-Language만으로 결정되지 않았습니다. URL 경로와 법인 설정이 언어 선택 규칙으로 쓰였고, 기존 업무 시스템과 메일 링크도 그 규칙에 의존했습니다.

내부 코드를 Spring Boot로 전환하면서 URL 규칙을 바꾸면 호출 시스템과 과거 링크까지 깨질 수 있었습니다. 따라서 로케일을 언제 결정하고, 레거시 화면의 내부 이동과 컨트롤러·서비스·예외 처리·검증 메시지가 그 값을 어떻게 공유할지 함께 설계해야 했습니다.

그대로 유지한 URL·법인 규칙

공개 예시에서는 실제 언어 경로와 클래스명을 바꿨지만, 판단 순서는 그대로 두었습니다.

  • 특정 해외법인 환경은 URL보다 법인 언어 정책을 우선합니다.
  • 본사 환경은 레거시 URL의 정확한 경로 세그먼트로 언어를 구분합니다.
  • 정의되지 않은 경로는 안전한 기본 언어를 사용합니다.
  • 레거시 화면 요청을 내부 컨트롤러로 포워드하기 전에 로케일을 결정합니다.

포워드 뒤에는 원래 URL의 언어 정보가 사라졌습니다

포워드 뒤에는 원래 URL의 언어 정보가 사라졌습니다 데이터 표
대안맞지 않았던 이유
Accept-Language 사용같은 브라우저에서도 URL과 법인에 따라 언어가 달라짐
Session·Cookie 저장세션 없이 직접 진입하는 링크의 언어를 보장하지 못함
URL을 신규 규칙으로 변경기존 시스템과 과거 메일 링크를 함께 수정해야 함
컨트롤러에서 매번 판정서비스·예외 처리·검증보다 늦고 중복됨

포워드된 URI만 보고 언어를 결정하면 원래 요청 경로의 의미를 잃을 수 있었습니다. 따라서 로케일은 컨트롤러보다 앞선 요청 처리 초기에 결정해야 했습니다.

포워드 전에 로케일을 정했습니다

아래 코드는 핵심 동작만 보여 주도록 실제 클래스·테이블·설정 이름을 바꾼 예시입니다.

1. 요청 식별자 설정
2. 요청값 보안 처리
3. 원 URL과 법인 정책으로 Locale 확정
4. 레거시 화면 요청을 내부 Controller로 Forward
5. 이미 확정된 Locale로 업무 처리

이 로직은 번역문을 직접 읽는 대신 URL·법인 규칙을 Spring이 이해할 수 있는 요청 로케일로 변환합니다.

Locale selected = tenantPolicy.forceEnglish()
    ? Locale.ENGLISH
    : localePathPolicy.resolve(request.getRequestURI());

requestLocaleStore.set(selected);
LocaleContextHolder.setLocale(selected);
filterChain.doFilter(request, response);

DB 메시지와 Bean Validation이 같은 로케일을 사용하게 했습니다

기존 업무 시스템의 DB 기반 메시지 체계를 유지하고, Controller·Service·공통 예외 처리와 Bean Validation이 같은 요청 Locale을 사용하게 했습니다. 실제 Bean 이름, 메시지 코드와 캐시 설정 키는 공개하지 않습니다.

원 요청 URL·법인 정책
  → 요청 Locale 확정
  → Spring Locale Context
  → DB MessageSource
  → Validation / Controller / Service / 오류 응답

운영에서는 메시지를 미리 적재하고 개발 환경에서는 요청된 메시지를 필요할 때 읽도록 환경별 캐시 정책을 분리했습니다. 실제 모드 이름과 설정 키는 일반화했습니다.

검증은 이렇게 진행했습니다

로케일 처리는 다운로드 시스템 전체 기능테스트에서 다음 조건으로 확인했습니다.

  • 기존 한국어·영어 계열 URL이 변경 없이 동작하는지
  • 레거시 화면 Forward 뒤에도 원 요청 언어가 유지되는지
  • 해외법인 정책이 URL보다 우선하는지
  • Controller 성공 메시지와 Service·예외 메시지의 언어가 일치하는지
  • Bean Validation이 같은 DB 메시지 체계와 Locale을 사용하는지
  • 메시지 캐시 갱신 경로가 동작하는지

이 로케일 변경은 DNA2 전체 기능 테스트 20개 시나리오·557개 케이스 안에서 URL·파일·DB 접근·오류 응답과 함께 확인했습니다. 처음 실패한 9건을 고친 뒤 557건이 모두 통과했고, 본사·유럽법인 통합 테스트도 별도로 진행했습니다.

정리

레거시 시스템의 URL에는 경로 이상의 의미가 숨어 있을 수 있습니다. 이 시스템에서는 원래 요청의 URL과 법인 정책으로 로케일을 먼저 정한 뒤 Spring 컨텍스트에 전달했습니다. 덕분에 포워드 이후에도 컨트롤러·서비스·검증·오류 응답이 같은 언어 기준을 사용할 수 있었습니다.

TECHNICAL SERIES

DNA2 레거시 현대화

DB 연결 생명주기부터 기존 요청 형식, 다국어 처리, 입력 검증과 런타임 충돌까지 이어지는 현대화 기록입니다.

시리즈 전체 보기

현재 3/6

  1. 1요청마다 Connection Pool과 SessionFactory를 만들면 생기는 문제
  2. 2DB Link 제거 후 복수 DataSource를 한 트랜잭션으로 관리하기
  3. 3레거시 URL의 언어 규칙을 Spring Locale로 연결하기
  4. 4축약 파라미터는 유지하고 DTO 필드명은 명확하게 바꾸기
  5. 5같은 DTO에서 API마다 다른 필수값을 검증하기
  6. 6JVM 클래스 로딩 로그로 추적한 Oracle JDBC 드라이버 충돌