레거시 통행료 시스템 역설계 연동 소개 영상
문제
이 기관은 통행료 미납 차량에 안내를 발송하기 전, 미납 내역을 조회하고 가상계좌를 매핑해 발송 자료를 만드는 업무를 사람이 손으로 처리해 왔습니다. 담당자가 인트라넷의 정산 센터 시스템에 로그인해 미납 목록을 조회하고 별도의 가상계좌 시스템에서 계좌를 등록·매핑한 뒤, 두 결과를 차량번호 기준으로 맞춰 알림 발송용 자료로 정리했습니다. 대상 건수가 늘어날수록 이 반복 작업은 실수와 지연의 온상이 됐습니다.
문제는 자동화의 통상적인 방법이 전부 막혀 있었다는 점입니다. 대상 시스템은 오래된 사내 프로그램이라 공개된 API 문서가 없고 보안 정책상 원격 접속도 불가능했습니다. 화면을 녹화하거나 클릭을 흉내 내는 UI 자동화도 현실적이지 않았습니다. 정산 센터는 Nexacro라는 옛 UI 프레임워크로 만들어져 있었습니다. 로그인 자격증명은 브라우저 안에서 한 번 암호화된 뒤 서버로 전송되는 구조였습니다. 겉으로 드러나는 화면만 봐서는 무엇을 어떻게 주고받는지 알 수 없었습니다.
게다가 실행 환경은 인트라넷 PC와 인터넷 PC가 물리적으로 분리된 망분리 구조였습니다. 미납 조회와 발송 자료 생성은 인트라넷에서만 가능하고 알림톡 발송은 외부 인터넷에서만 가능했습니다. 두 세계를 잇는 다리 없이, 각 망에서 도는 프로그램을 따로 만들고 그 사이를 파일로 안전하게 넘기는 설계가 필요했습니다. 요약하면 문서도 화면 자동화도 원격 접속도 쓸 수 없는 상태에서, 오래된 시스템이 실제로 주고받는 언어를 직접 해석해 붙여야 하는 일이었습니다.
접근
기능
통신 캡처로 레거시 프로토콜을 역설계
원격 접속이 막혀 있어 현장에서 실제 로그인과 조회를 한 번 수행하며 네트워크 통신을 그대로 캡처했습니다. 그 기록을 분석해 정산 센터가 Nexacro XML 데이터셋 프로토콜을 쓰고 동작마다 별도의 서버 주소를 호출하며 표준 세션 쿠키로 인증한다는 것을 확인했습니다. 화면을 흉내 내는 대신 서버가 실제로 이해하는 요청을 그대로 재현하는 방향을 잡았습니다.
가장 큰 관문은 로그인이었습니다. 아이디와 비밀번호가 평문이 아니라 클라이언트 안에서 한 번 암호화된 값으로 전송되고 있었습니다. 캡처된 요청값과 원래 입력값을 대조하며 이 암호화가 특정 방식의 대칭키 암호화라는 것을 확인했고 패딩과 인코딩 규칙까지 맞춰 같은 입력이 같은 결과를 만들어 내는지 검증했습니다. 검증된 키와 초기값은 코드에 박아 두지 않고 설정으로 주입해 자격증명이 소스에 노출되지 않도록 했습니다.
기능
클라이언트 측 로그인 암호화 해석
로그인 시 자격증명은 대칭키 암호화를 거쳐 전송됩니다. 캡처된 실제 값을 기준으로 암호화 방식과 패딩·인코딩 규칙을 재현해 서버가 받아들이는 로그인 요청을 프로그램이 스스로 만들 수 있게 했습니다. 키와 초기값은 하드코딩하지 않고 외부 설정으로 주입합니다.
로그인이 뚫려도 끝이 아니었습니다. 발송 처리 요청이 서버에서 계속 거부됐습니다. 원인은 요청 XML의 미세한 형식 차이였습니다. 서버는 특정 화면이 보내는 전체 컬럼 스키마를 그대로 기대하는데, 일반적인 XML 생성기로 만든 요청은 컬럼 수와 순서, 공백과 줄바꿈까지 조금씩 달랐습니다. 그래서 성공했던 캡처 요청을 바이트 단위로 대조해 컬럼 정의부터 셀 직렬화 규칙, 빈 값 처리까지 캡처와 정확히 일치하는 전용 직렬화기를 만들었습니다. 이 지점이 이 프로젝트에서 가장 오래 붙든 문제였습니다.
기능
바이트 단위 요청 재현으로 발송 오류 해결
발송 요청이 반복적으로 거부되던 원인은 서버가 기대하는 전체 컬럼 스키마와 직렬화 형식이었습니다. 성공 캡처를 바이트 단위로 대조해 컬럼 수·순서·공백·빈 값 처리까지 캡처와 일치하는 전용 직렬화기를 만들어 해소했습니다.
두 시스템을 붙이는 일도 만만치 않았습니다. 정산 센터는 앞서 말한 Nexacro XML을 쓰고 가상계좌 시스템은 전혀 다른 방식의 일반 웹 로그인과 요청을 씁니다. 두 시스템을 각각 별도의 세션과 요청 규칙으로 다루되, 세션이 만료되면 서버가 오류 대신 로그인 페이지를 되돌려 주는 특성까지 감지해 자동으로 한 번 다시 로그인한 뒤 재시도하도록 했습니다. 마지막으로 두 시스템에서 모은 데이터를 차량번호를 키로 병합해 발송 자료 파일 하나로 만들고 이 파일을 인터넷 PC의 발송 프로그램이 받아 알림을 보냅니다.
기능
망분리 환경을 위한 2프로그램 구조
인트라넷 프로그램은 브라우저와 엑셀 없이 서버 API만 호출해 미납 조회·가상계좌 매핑·발송 자료 생성을 수행하고 인터넷 프로그램은 그 자료 파일을 받아 알림을 발송합니다. 두 세계는 검증된 포맷의 파일 하나로만 연결되며 각 프로그램은 담당 PC에서 스케줄대로 무인 실행됩니다.
전체 구조는 다음과 같습니다.
글로도 요약하면 이렇습니다. 인트라넷 프로그램은 정산 센터와 가상계좌 시스템을 각각의 프로토콜로 로그인하고 조회한 뒤, 차량번호를 키로 데이터를 병합해 발송 자료 파일을 만듭니다. 이 파일은 정해진 포맷으로 인터넷 PC에 넘어가고 인터넷 프로그램이 파일을 읽어 알림을 발송한 뒤 성공·실패 결과를 리포트로 남깁니다. 두 프로그램 모두 브라우저 없이 서버와 직접 통신하며 담당 PC의 스케줄러로 무인 실행됩니다.
결과
사람이 여러 화면을 오가며 조회하고 옮겨 적던 발송 준비 작업이 프로그램 한 번 실행으로 대체됐습니다. 미납 조회부터 가상계좌 매핑, 발송 자료 생성까지 브라우저나 엑셀을 열지 않고 서버 API 호출만으로 끝나고 담당 PC에서 스케줄대로 무인 실행됩니다. 원격 접속과 화면 자동화가 막힌 조건에서도, 시스템이 실제로 주고받는 통신을 해석해 붙였기 때문에 UI 변화에 취약한 클릭 자동화보다 견고합니다.
무엇보다 이 프로젝트는 "문서도 접근도 없는 오래된 시스템도 연동할 수 있다"는 것을 보여 준 사례입니다. 화면이 아니라 프로토콜을 상대로 했기 때문에 무엇이 실패하면 어디서 왜 실패했는지 단계별로 드러나고 쓰기 동작에는 안전 가드를, 로그에는 개인정보 마스킹을 두어 실데이터를 다루는 업무에도 조심스럽게 적용할 수 있게 했습니다.
이 프로젝트에서 다룬 기술적 판단들은 아래 글에서 더 자세히 풀었습니다.
- Nexacro 레거시 프로토콜 역설계: 통신 캡처로 옛 시스템의 통신 규칙을 읽는 법
- 클라이언트 측 로그인 암호화 해석: 브라우저 안에서 암호화되는 자격증명을 재현하기
- 바이트 단위 요청 재현으로 오류 잡기: 형식 하나가 어긋나 거부되는 요청을 맞추는 과정
- 레거시 세션 유지와 만료 복구: 오류 대신 로그인 페이지를 주는 서버 다루기
- 망분리 환경의 2프로그램 자동화: 물리적으로 분리된 두 망을 파일로 잇기
- 레거시 연동 외주 전 체크리스트: 발주 전에 확인해야 할 것들
자주 묻는 질문
문서도 없고 접근도 안 되는 오래된 시스템을 어떻게 연동하나요?
시스템이 화면 뒤에서 실제로 주고받는 통신을 기준으로 삼습니다. 이 프로젝트는 원격 접속이 막혀 있어 현장에서 실제 로그인과 조회를 한 번 수행하며 네트워크 통신을 캡처하고 그 기록을 분석해 서버가 이해하는 요청을 그대로 재현했습니다. 화면을 흉내 내는 방식이 아니라 서버와 직접 통신하는 방식이라 오히려 견고합니다.
로그인 자격증명이 암호화되어 있어도 연동이 되나요?
가능합니다. 이 시스템은 아이디와 비밀번호가 클라이언트 안에서 한 번 암호화된 뒤 전송되는 구조였는데, 캡처된 실제 값과 원래 입력값을 대조해 암호화 방식과 패딩·인코딩 규칙을 재현했습니다. 이렇게 하면 프로그램이 서버가 받아들이는 로그인 요청을 스스로 만들 수 있습니다. 키와 초기값은 소스에 하드코딩하지 않고 설정으로 주입합니다.
화면 클릭 자동화와 무엇이 다른가요?
화면 클릭 자동화는 UI가 조금만 바뀌어도 멈추고 느리며 무인 운영에 취약합니다. 이 프로젝트는 브라우저 없이 서버 API를 직접 호출하므로 훨씬 빠르고 안정적이며 실패 시 어느 단계에서 왜 실패했는지 명확히 드러납니다. 다만 시스템의 통신 구조가 크게 바뀌면 재대응이 필요하며 이는 유지보수 범위로 다룹니다.
개인정보가 포함된 업무인데 안전한가요?
발송 대상 데이터에는 차량번호와 연락처 같은 개인정보가 포함되므로, 로그와 리포트에는 이런 값을 마스킹해 원본이 남지 않게 했습니다. 또한 실제로 데이터를 등록·발송하는 쓰기 동작에는 기본적으로 안전 가드를 두어 명시적으로 실행을 지정하기 전에는 실제 전송이 일어나지 않도록 설계했습니다.