3화: 사내 폐쇄망에 러스트 툴을 올릴 수 없다니요?
어제 길게 이어진 팀 회의와 고객사 원격 미팅 끝에 내 야심 찬 'Rust 기반 MSA 전면 재작성안'은 보수적인 비즈니스 핑계에 가로막혀 튕겨 나갔다. 예산, 롤백 위험, 이관 책임... 개발 외적인 변수들을 들이밀며 고개를 저어대던 박정수 팀장님과 임동현 PM의 얼굴이 여전히 눈앞에 선했다.
하지만 나는 이대로 손을 놓고 있을 생각이 전혀 없었다.
'말만 해서는 저 사람들의 보수적인 벽을 깰 수 없어. 개발자가 자신의 주장을 증명하는 가장 확실한 방법은 수치화된 객관적 데이터뿐이다.'
출근 직후 사내 노트북을 켜고 팀 파이프라인이 구축된 사내 젠킨스(Jenkins) CI 서버에 접속했다. 우리 새벽기술 팀이 관리하는 한빛상사 레거시 ERP 빌드 잡은 전형적인 프리스타일(Freestyle) 구조로 묶여 있었다. SVN 저장소에서 소스코드를 내려받아 Maven으로 14개 서브모듈을 순차적으로 컴파일하고, 온갖 레거시 XML과 클래스들을 묶어 최종 WAR 패키지를 만들어내는 방식이었다.
매번 클린 빌드(Clean Build)를 돌릴 때마다 무려 20분 가깝게 소요되는 답답한 파이프라인. 게다가 모듈 간 의존성 구조가 엉망으로 꼬여 있어서 어떤 모듈을 수정할 때 어디까지 영향이 미치는지 시각적으로 파악하기조차 불가능했다.
'좋아. 내가 개인 프로젝트로 만들어둔 Rust 정적 분석 도구를 이 젠킨스 빌드 잡의 후속 단계(Post-build)에 얹는 거야.'
내가 만든 도구는 AST(추상 구문 트리) 파싱과 심볼 추적을 통해 모듈 간 상호 의존성과 복잡도를 컴파일 타임급 정밀도로 추출하고, HTML 형태의 직관적인 정적 분석 리포트를 생성해 주는 도구였다. 자바의 기존 린터나 단순 텍스트 기반 검증 도구와는 차원이 다른 깊이 있는 구조 그래프를 뽑아낼 수 있었다.
이 리포트만 파이프라인 끝단에 붙여서 매 빌드마다 자동 생성되게 만든다면, 팀장님도 레거시 아키텍처가 얼마나 심각하게 꼬여 있는지 눈으로 직접 확인하게 될 것이었다.
나는 즉시 사내 젠킨스 잡 설정 페이지로 들어갔다. 쉘 스크립트 실행 단계를 추가하고, 내 분석 도구를 젠킨스 슬레이브 노드에서 즉석으로 빌드하거나 실행할 수 있도록 툴체인 명령을 작성하기 시작했다.
그런데 '저장' 버튼을 누르고 테스트 빌드를 돌린 직후, 콘솔 로그 창에 붉은색 에러 메시지가 쏟아져 내렸다.
`[ERROR] Cargo failed to fetch dependencies: Could not resolve host: crates.io`
`[ERROR] Connection timed out: 10.192.0.45:8081/repository/crates-mirror`
"어...?"
나는 당황해서 젠킨스 노드의 네트워크 설정을 훑어보았다.
사내 넥서스(Nexus) 아티팩트 저장소 주소가 등록되어 있긴 했지만, 그곳에는 오직 자바용 Central Repository 미러만 뚫려 있을 뿐이었다. Rust의 패키지 관리자인 Cargo가 사용하는 crates.io registry 미러는 전혀 구축되어 있지 않았다. 아니, 그 이전에 이 개발망 젠킨스 노드 자체에서 외부 인터넷망으로 나가는 모든 80/443 포트가 방화벽에 의해 철저하게 차단된 완전 폐쇄망 상태였다.
"외부 패키지 다운로드가 통째로 막혀 있다고...?"
당연한 일이었다. 보안이 극도로 엄격한 금융/SI 고객사 환경에서는 외부 GitHub이나 open registry에서 직접 소스를 받아오거나 바이너리를 내려받는 행위가 엄격히 금지된다. 모든 외부 OSS 의존성은 사전 보안 검증을 거쳐 사내 넥서스 미러에 등록된 인가된 아티팩트만 주입받아 쓰도록 통제되어 있었다.
'그렇다면... 젠킨스 노드에서 빌드할 필요 없이, 내가 직접 작성한 Rust 정적 분석 바이너리 실행 파일과 최소한의 필수 툴체인 라이브러리를 사내 넥서스 공용 아티팩트 폴더에 업로드해 두고 끌어다 쓰면 되잖아?'
생각이 거기에 미치자 나는 곧바로 넥서스 관리 콘솔 페이지를 열고 사내 공용 아티팩트 업로드 창을 켰다. 내 개인 작업 디렉터리에 축적해 둔 최신 Rust 분석 바이너리 파일(.exe)을 Drag & Drop 영역으로 끌고 가려던 바로 그 순간이었다.
"강현호 씨, 지금 모니터 화면에 켜둔 게 뭡니까?"
뒤에서 나직하면서도 무게감 있는 목소리가 들려왔다. 언제 다가왔는지 박정수 팀장님이 내 자리 옆에 서서 넥서스 업로드 화면을 유심히 바라보고 계셨다.
"아, 팀장님. 어제 말씀드린 레거시 아키텍처의 의존성 꼬임 문제를 수치화해서 보여드리려고 합니다. 제가 만든 정적 분석 툴 바이너리를 사내 넥서스에 올려서 젠킨스 빌드 잡에 연동하려고..."
내 말이 끝나기도 전에 박 팀장님이 헛웃음을 픽 흘리며 손을 가볍게 내저었다.
"강현호 씨. 사내 넥서스 공용 아티팩트 저장소는 개인이나 팀이 검증되지 않은 외부 바이너리를 마음대로 올리라고 만든 공간이 아닙니다."
"네? 하지만 이건 단순한 내부 코드 분석용 도구일 뿐입니다. 시스템 실행 파일이나 운영 소스를 건드리는 게 아니라 리포트만 출력하는..."
"용도가 무엇이든 상관없습니다."
박 팀장님의 눈빛이 단호해졌다.
"우리 프로젝트는 한빛상사 보안 가이드라인과 새벽기술 인프라운영팀의 엄격한 규정을 적용받습니다. 사내 넥서스에 신규 바이너리나 외부 라이브러리를 반입하려면, 소스코드 보안성 검토와 라이선스 검증, 그리고 인프라팀의 정식 반입 승인 요청서를 거쳐야 합니다. 인프라팀 승인도 없이 임의로 툴을 올렸다가 보안 감사에 걸리면 팀 전체가 경위서를 써야 해요."
"승인 없이... 바이너리 하나도 올릴 수 없다는 말씀이십니까?"
"그렇습니다. 보안망 내부의 아티팩트 관리는 그렇게 허술하게 돌아가지 않아요. 개인 도구를 쓰고 싶어 하는 강현호 씨의 의욕은 알겠지만, 회사 절차와 규정을 무시하고 사내 망에 외부 바이너리를 집어넣는 건 절대 허용할 수 없습니다."
박 팀장님의 확고한 선언에 나는 입을 싹 다물 수밖에 없었다. 자바 생태계의 20분짜리 빌드 판을 러스트의 정밀함으로 쇄신하려던 계획이 사내 보안 규정이라는 단단한 빗장에 막혀버린 것이었다.
옆자리에서 조용히 키보드를 두드리던 한지훈 선배가 의자를 살짝 돌리며 무심한 어조로 한마디를 보탰다.
"강현호 씨, 젠킨스에서 꼭 외부 바이너리를 올려서 돌려야만 하는 거라면... 굳이 그렇게 거창한 툴을 안 써도 되지 않나요? 기존 젠킨스 잡의 쉘 스크립트 단계에서 자바 표준 린터나 MyBatis XML 정적 체크 스크립트 정도만 구동해도 기본적인 설정 에러나 쿼리 파일 누락은 충분히 걸러낼 수 있을 텐데요."
한 선배의 질문은 지극히 현실적이고 합리적인 제안처럼 들렸다. 하지만 내 내부의 오만함은 그 타협안을 순순히 받아들이지 못했다.
'단순한 자바 린터나 쉘 스크립트 텍스트 긁기 따위로 내가 만든 Rust 툴을 대체하라고? 문자열이나 겨우 긁어내는 수준으로는 AST 기반의 순환 의존성 그래프나 심볼 추적 성능을 절반도 따라오지 못해. 자바 생태계의 어설픈 도구들로 때우니까 매번 이런 20분짜리 기형적인 모노리스 빌드가 유지되는 거 아닌가.'
나는 내적 반발심을 누르며 한 선배와 박 팀장님을 향해 깍듯이 존댓말로 대답했다.
"선배님 말씀도 무슨 뜻인지 이해합니다. 하지만 기존 자바 텍스트 린터로는 모듈 간 깊은 순환 참조나 구조적 아키텍처 부채를 명확히 측정하는 데 한계가 있습니다. 저는 정확하고 수치화된 의존성 그래프로 팀장님과 고객사를 설득하고 싶습니다."
박 팀장님은 나를 가만히 바라보다가 가볍게 한숨을 쉬었다.
"정 그 도구를 써서 리포트를 내고 싶다면, 정식 절차를 밟으세요. 인프라운영팀 포털에 '외부 바이너리 사내 반입 및 넥서스 등록 신청서'를 작성해서 올리고 승인을 받으십시오. 물론 인프라팀 검토에 최소 일주일은 걸릴 거고, 외부 라이선스 검증과 보안 스캔까지 통과해야겠지만요."
"일주일이요...?"
"네. 절차를 거치지 않은 편법은 안 됩니다. 규정을 지키면서 증명해 보세요."
박 팀장님은 그 말을 남기고 자신의 자리로 돌아갔다.
나는 텅 빈 넥서스 업로드 화면을 노려보았다. 폐쇄망이라는 미로 속에서, 내가 자랑스럽게 여겼던 컴파일 타임의 강력함과 Rust의 우수성은 사내 보안 규정이라는 커다란 관료제 벽에 가로막혀 발조차 떼지 못하고 있었다.
'좋아... 정식 절차가 필요하다면 거쳐 주겠어. 일주일이 걸리든 보름이 걸리든 인프라팀 신청서를 올리고 보안 검토를 통과해서 내 도구가 맞다는 걸 이 사내망 위에서 똑똑히 증명해 보이고 말겠다.'
나는 오기를 품은 채 인프라운영팀 보안 반입 신청서 양식을 화면에 띄웠다. 자바 8과 폐쇄망이라는 굳건한 레거시의 벽을 향한 나의 고집스러운 도전은 이제 정식 보안 절차라는 새로운 전선으로 이어지고 있었다.
<4화에서 계속>
TL;DR