
전략 제13계: P가 공개 포럼에 질문을 올리자, 24시간 후 그들의 영업팀에서 전화가 왔다
요약
AI 리스크 모델 평가 파이프라인을 검토하던 P가 Finova의 기술 아키텍처가 자신의 과거 공개 게시물과 거의 일치한다는 사실을 발견합니다. 이는 기술적 아이디어의 도용 가능성을 시사하며, 기업의 윤리적 문제와 기술적 자산 보호에 대한 의문을 제기합니다.
핵심 포인트
- Finova의 리스크 모델링 아키텍처와 P의 공개 게시물 간의 높은 유사성 발견
- 기술 스택(TensorFlow, TFX) 및 앙상블 전략의 일치 확인
- 기업의 기술적 자산 및 아이디어 도용에 대한 윤리적 이슈 제기
풀을 밟아 뱀을 놀라게 하라.
— 삼십육계 (The 36 Stratagems), 공격하여 뱀을 놀라게 함 (Stomp the Grass to Scare the Snake)
이 시리즈의 이전 이야기:
#1: Mark Johnson가 AI 감사(Audit)에 들어갔다. 벤치마크는 진실을 제외한 모든 것을 파악하고 있었다. — Mark는 Pulse AI라는 회사를 감사했습니다. 벤치마크 평가 세트에는 98개의 조작된 데이터 포인트가 있었습니다. CTO Torres는 새벽 3시에 전화를 걸어 고백했습니다. C-round(C-라운드) 전에 95%의 수치가 필요하다고 말이죠. Mark는 전화를 끊었습니다. Pulse AI는 망하지 않았습니다.
#7: P는 한 방향으로만 보는 AI를 지켜보았다. 99.97%는 진짜였다. 단지 중요한 모든 것을 놓쳤을 뿐이다. — P는 FortDefender의 보안 시스템에 있는 치명적인 사각지대를 드러내기 위해 미끼로서 시뮬레이션된 공격을 사용했습니다. 99.97%의 정확도는 진짜였습니다. 단지 실제로 중요한 모든 것을 놓쳤을 뿐입니다.
그로부터 3개월이 지났습니다.
P와 Mark는 DEV.to에서 만났습니다. Mark는 P의 게시물 중 하나에 답글을 달았습니다. 모든 면에서 정확한 정밀한 기술적 답변이었습니다. P는 그에게 감사 인사를 전했습니다. 이메일 스레드는 열려 있었지만, 두 사람 중 누구도 다시 글을 쓰지는 않았습니다.
P는 감사 전 작업(pre-audit work)을 수행하고 있었습니다. 검토를 앞둔 AI 플랫폼 — Finova 산하의 리스크 모델 평가 파이프라인(risk model evaluation pipeline)이었습니다. 그들의 기술 스택(tech stack)을 조사하던 중, P는 흥미로운 점을 발견했습니다. 몇 달 전 P가 DEV.to에서 가볍게 논의했던 모델 평가 방식 — 리스크 모델링을 위한 배깅 앙상블 (bagging ensemble) + k-겹 시계열 교차 검증 (k-fold time-series cross-validation) 파이프라인 — 이 Finova의 공개 문서에 기록된 아키텍처(architecture)와 거의 한 줄 한 줄 일치했습니다.
동일한 프레임워크 (TensorFlow 2.x + TFX). 동일한 앙상블 전략 (XGBoost + LightGBM stacking). P가 게시했던 예시와 동일한 평가 윈도우 크기 (evaluation window size) 및 슬라이딩 스텝 (sliding step). P는 예전 게시물을 찾아냈습니다. 그것은 Finova의 제품 라인이 출시되기도 전에 게시된 것이었습니다. 그리고 그것은 단지 기술 백서 (technical whitepaper)만의 문제가 아니었습니다. 모든 신호가 같은 방향을 가리키고 있었습니다. 밋업 (meetups)에서 만난 Finova 엔지니어들, GitHub에 공개된 그들의 오픈 소스 툴링 (open-source tooling), 채용 공고에 적힌 기술 스택 (tech stack)까지 말입니다.
P는 화면에 두 문서를 나란히 띄웠습니다. 왼쪽에는 Finova의 백서가, 오른쪽에는 P가 DEV.to에 남긴 답글이 있었습니다. 우연이 아니었습니다. 누군가 지켜보고 있었습니다.
새벽 1시, Third Cup 카페. P는 평소처럼 창가 테이블에 앉아 있었고, 화면 밝기는 최소로 낮춰져 있었습니다. 바 (bar) 뒤에 있는 직원은 묻지도 않고 에스프레소를 내려놓았습니다. Third Cup의 단골들은 주문할 필요가 없습니다.
P는 한 가지 행동을 했습니다. 새 탭을 열고, DEV.to에 로그인하여, 새로운 게시물을 작성했습니다. 제목: Discussion: Evaluation set leakage in ensemble-based risk model backtesting. (토론: 앙상블 기반 리스크 모델 백테스팅에서의 평가 세트 누수). P는 6개월 전에 등록하여 몇 개의 일상적인 기술 게시물을 올렸던 계정을 사용했습니다. 갑자기 나타난 신규 계정이 아닌, 정상적인 토론 이력을 가진 계정이었습니다.
게시물 본문에는 상세한 모델 구성 (model configuration)이 기술되었습니다:
우리가 구축한 전형적인 리스크 모델 평가 파이프라인은 다음과 같습니다:
모델 아키텍처 (Model architecture): XGBoost + LightGBM stacking ensemble
...
risk-ensemble-v3-test-stub가 변경된 부분이었습니다. Finova의 실제 태그는 prod였습니다. 모델 아키텍처, 피처 차원 (feature dimensions), 롤링 윈도우 스텝 (rolling window step), 배치 크기 (batch size) 등 다른 모든 줄은 Finova의 실제 파이프라인 구성과 일치했습니다. 문제는 실재했습니다. 파라미터 (parameters)도 실재했습니다. 유일하게 가짜인 것은 중간에 자리 잡고, 마치 일상적인 실험용 버전 태그처럼 보이는 부분뿐이었습니다.
게시하기 전, 커서가 제출 버튼 위에서 2초 동안 머물렀습니다. 그리고 클릭했습니다.
그 후 P는 기다렸습니다.
테이블 왼쪽에 놓인 휴대폰은 화면이 켜진 채 위를 향하고 있었습니다. 아무도 전화하지 않았습니다.
에스프레소 잔은 비어 있었습니다. P는 노트를 몇 장 넘겨보고 다시 휴대폰을 힐끗 보았습니다. 아무도 전화하지 않았습니다.
하지만 만약 풀숲에 뱀이 있다면 — 풀숲을 내리치세요, 그러면 뱀은 스스로 겁을 먹고 튀어나올 것입니다.
전화
다음 날 오후. 휴대폰 불이 켜졌습니다. 발신자 미상.
P는 3초 동안 벨 소리가 울리는 것을 지켜보았습니다. 바로 받지 않았습니다.
발신자 정보 없음. P의 손가락이 휴대폰을 꽉 쥐었습니다 — 아주 잠시 동안만.
네 번째 벨 소리에 전화를 받았습니다.
상대방은 자신을 Pulse AI 영업팀이라고 소개했습니다. 그들은 DEV.to에서 P의 질문을 보았다고 했습니다. 그들의 플랫폼도 유사한 기능을 갖추고 있다고 했습니다. P가 데모 (demo)를 받아볼 의향이 있는지 물었습니다. 친근한 말투. 표준적인 스크립트 (script).
P는 경청했습니다. 시선은 여전히 화면에 열려 있는 게시물 페이지에 고정되어 있었습니다 — 파라미터 (parameter)는 여전히 수정된 버전이었습니다.
영업사원은 자신들의 제품 기능을 쭉 설명하더니, 무심하게 P의 환경 설정 (environment setup)을 언급했습니다 —
"귀하의 모델 평가 (model evaluation) 구성, 즉 risk-ensemble-v3-prod 파이프라인 (pipeline)에 대해 말씀드리는 것입니다..."
P는 멈칫했습니다. 잠시 정적이 흘렀습니다.
"네, 생각해 볼게요."
전화를 끊었습니다. 다른 것은 아무것도 묻지 않았습니다.
P의 손은 휴대폰 위에 그대로 머물러 있었습니다.
게시물에는 test-stub이라고 적혀 있었습니다. 전화한 사람은 prod라고 말했습니다. 그 이름이 나올 수 있는 곳은 단 한 군데뿐입니다.
P는 휴대폰을 테이블 위에 내려놓았습니다.
바(bar) 뒤에 있던 사람이 고개를 들었습니다. 아무 말도 하지 않았습니다. 다시 잔을 닦는 일로 돌아갔습니다.
추적
게시물 페이지는 여전히 열려 있었습니다. 커서가 수정 버튼 위에서 맴돌았습니다 — P는 파라미터를 다시 되돌릴 수 있었습니다. 하지만 그러지 않았습니다. DEV.to 탭을 닫았습니다. 터미널 (terminal)을 열었습니다.
P는 허니팟 (honeypot)을 설정했습니다. 다른 계정으로 전환했습니다 — 질문 위주에 답변이 몇 개 섞여 있는, 주니어 레벨의 엔지니어링 매니저 (engineering manager)처럼 보이는 오래된 계정이었습니다. 같은 방향으로 일반적인 질문을 게시했습니다:
프로덕션 (production) 환경에서 롤링 윈도우 검증 (rolling window validation)을 사용해 앙상블 리스크 파이프라인 (ensemble risk pipeline) 평가를 실행해 보신 분 계신가요? 윈도우에 따라 결과가 계속 변동되는데 — 데이터 누수 (data leakage) 때문인지 아니면 평가 전략 (evaluation strategy) 때문인지 잘 모르겠습니다.
그 질문은 의도적으로 모호했습니다. 기술 스택 (tech stack)에 대한 세부 정보도 없었고, 문단 나누기도 없었습니다. 마치 휴대폰에서 보낸 것처럼 작성되어 있었습니다. 게시물에는 아키텍처 다이어그램 (architecture diagram)이 포함되어 있었는데, 이미지 URL은 P의 VPS를 가리키고 있었으며, 각 요청마다 Referer와 User-Agent 헤더를 포함하고 있었습니다. P는 VPS에 Cache-Control: no-cache, no-store를 설정하여, CDN이 접속할 때마다 매번 재검증 (revalidate)하도록 강제했습니다. 이를 통해 모든 크롤러 (crawler)의 요청이 P의 Nginx 로그에 남도록 만들었습니다.
이틀이 지났습니다. 추적 링크는 클릭되지 않았습니다. 아무 일도 없었습니다.
그 후 P는 두 번째 게시물을 올렸습니다. 다시 첫 번째 계정으로 전환했습니다. 이번 게시물은 완전한 기술적 시그니처 (technical signature)를 유지했습니다:
저희는 운영 환경 (production)에서 리스크 모델 평가를 위해 XGBoost + LightGBM 스태킹 (stacking)을 실행 중입니다 — 12개월 이동 창 (rolling window), 3개월 단계 (step), 배치 크기 (batch size) 2048입니다. 몇몇 곡선이 비정상적으로 보여 평가 세트 누수 (evaluation set leakage)가 의심됩니다. 모델 버전은 risk-ensemble-v3-test-stub입니다. 비슷한 문제를 겪으신 분 계신가요?
설정은 동일했습니다: 게시물 하단에 P 자신의 서버에 있는 HTTP 엔드포인트 (endpoint)를 가리키는 외부 참조 링크를 배치했습니다. 크롤러가 여기에 접속하면, 서버는 IP, User-Agent, 타임스탬프를 기록한 뒤, 공개된 연구 논문의 PDF로 302 리다이렉트 (redirect)를 보냈습니다. 크롤러에게는 이것이 일반적인 논문 링크처럼 보였습니다.
이 모든 작업이 끝났을 때는 새벽 3시였습니다. P는 컴퓨터를 끄지 않았습니다. 화면 밝기를 낮추고 잠시 잠을 청했습니다.
6시간도 채 지나지 않아, 트리거 (trigger)가 작동했습니다.
두 번째 게시물 — 완전한 기술적 시그니처가 담긴 게시물 말입니다. 첫 번째 게시물, 즉 일반적인 게시물은 인덱싱 (indexing)되지 않았습니다. 봇 (bot)들은 모호한 질문을 읽지 않습니다. 그들은 기술적 지문 (technical fingerprints)을 읽습니다.
[REQUEST LOG — 07-13 08:22:08]
Source IP: [REDACTED] → [REDACTED] (/24 range, 12 distinct hosts)
Target: DEV.to post #4829 (slug: ai-pipeline-behavior)
...
P는 그것을 한 줄 한 줄 읽어 내려갔습니다. 화면 빛이 P의 얼굴에 반사되었습니다. 표정은 없었습니다. 테이블 위를 두 번 톡톡 두드린 뒤, 멈췄습니다.
마지막 세 줄을 다시 읽었습니다.
Pulse AI는 DEV.to를 체계적으로 모니터링하고 있었습니다. 기술 포스트를 자동 스크래핑(Auto-scraping)하고, 기술 스택 시그니처(tech-stack signatures)를 추출하며, 영업 리드(sales leads)와 매칭하고, 아웃바운드 콜(outbound calls)을 라우팅하고 있었습니다. 그 어디에도 인간의 개입은 없었습니다.
P는 스크린샷을 찍었습니다. 터미널을 닫았습니다.
P는 이메일 목록을 열었습니다. 오래된 스레드 하나가 있었습니다. 몇 달 전 업계의 누군가가 Pulse AI를 조사하기 위해 벤처 캐피털(VC) 기업이 의뢰한 독립 감사 보고서에 대해 언급한 적이 있었습니다. 발신자 주소는 현재 이메일 스레드에 있는 것과 동일했습니다.
두 번째 전화
다음 날 아침. 같은 번호였습니다.
P는 번호를 힐끗 보았습니다. 거절하지 않았습니다. 화면을 밀어 전화를 받았습니다.
이번에는 목소리가 달랐습니다. 더 차분했습니다. 그는 자신이 기술 계정 관리자(Technical account manager)라고 말했습니다. 그의 팀은 P의 두 번째 포스트 — 전체 기술 시그니처가 포함된 포스트 — 를 검토했고 내부 평가를 실시했다고 했습니다. 이번에는 매칭률이 현저히 높았습니다. 그들은 더 심도 있는 기술적 논의를 하고 싶어 했습니다.
그는 첫 번째 통화자보다 더 구체적이었습니다. 모델 아키텍처(model architecture) 방향을 언급했습니다. 배치 크기(batch size) 튜닝을 제안했습니다. 심지어 P가 삽입한 링크의 논문까지 참조했습니다 — 마치 스스로 조사한 것이 아니라 브리핑 자료를 읽고 있는 것처럼 말입니다.
P는 경청했습니다. 손가락은 움직이지 않았습니다. 데스크톱의 터미널 창을 열었습니다 — 허니팟(honeypot) 로그가 여전히 화면에 떠 있었습니다. confidence: 0.87. tag inferred: risk-ensemble-v3-prod. 라운드 로빈(round-robin) 방식의 12개 IP. CRM 4/8 매칭.
P는 그의 말이 끝나기를 기다렸습니다.
2초간의 침묵.
"당신들의 크롤러(crawler)가 영업 멘트보다 낫군요."
전화를 끊었습니다.
이번에 P의 손은 전화기를 꽉 쥐지 않았습니다. P는 전화기를 테이블 위에 내려놓았습니다. 터미널 창을 닫았습니다. 이메일을 열었습니다.
이메일
P는 Mark Johnson과의 스레드를 열었습니다. 크롤러의 기술 시그니처 — 로그 스니펫(log snippets), URL 패턴, 파이프라인 명명 규칙(pipeline naming conventions) — 를 보냈습니다.
몇 시간 후 Mark의 답장이 왔습니다. 짧았습니다.
그는 이메일에 이러한 명명 규칙은 인터넷에서 찾을 수 있는 것이 아니라고 적었습니다. 그는 Pulse AI 내부를 들여다본 적이 있었습니다.
첨부된 것은 스크린샷이었습니다. 그가 Pulse AI 감사 (audit) 중에 저장해 두었던 파이프라인 설정 (pipeline config) 스켈레톤이었습니다. triple_redundant 접미사는 스크린샷에 없었습니다. 그 부분은 그가 떠난 후에 추가된 것이었습니다. 하지만 그가 몇 달 동안 머물렀던 디렉토리 구조와 P의 크롤러 경로 데이터 (crawler path data)를 결합하면, 전체 명명 규칙 (naming convention)을 역공학 (reverse-engineer)하기에 충분했습니다.
/pulse/ingestion/{env}/{source}
├── prod
│ ├── api_gateway
...
크롤러는 외주를 준 것이 아니었습니다. Pulse AI는 과거 Benchmark AI 조작 (fabrication) 시절의 아키텍처 습관을 그대로 사용하여 직접 구축했습니다. 동일한 디렉토리 구조. 동일한 명명 규칙. 동일한 환경 분리 (environment separation). 업무는 달랐지만, 손길은 같았습니다.
Mark의 이메일 하단에 한 줄이 더 적혀 있었습니다.
"Torres는 설계자 (architects)를 바꾸지 않았습니다."
P는 그것을 읽었습니다. 답장하지 않았습니다. 잠시 그 다섯 단어를 응시했습니다. 커서가 닫기 버튼 위에서 머물렀고, 잠시 멈췄다가, 클릭했습니다.
파일
P는 공개적으로 행동하지 않았습니다. 세 번째 기사를 게시하지도 않았습니다. 당국에 전화하지도 않았습니다.
P는 모든 것을 하나의 폴더로 정리했습니다 — 게시 타임라인, 통화 녹음, 허니팟 로그 (honeypot logs), 크롤러 요청 기록 (crawler request records), Mark의 확인 스크린샷, Pulse AI 파이프라인 비교. 폴더 이름은 pulse_crawler/로 정했습니다. 로컬에 저장했습니다.
P는 노트북을 바로 닫지 않았습니다. 그 로그 라인 — risk-ensemble-v3-prod (confidence: 0.87) — 이 여전히 터미널에 남아 있었습니다. 몇 초 동안 그것을 응시했습니다.
그리고 닫았습니다.
P는 gpg -c를 입력했습니다.
아직은 아닙니다. 하지만 이 폴더는 결국 열리게 될 것입니다.
새벽 3시 45분. Third Cup이 문을 닫기까지 15분 전입니다. P가 문을 밀고 들어갔을 때, 바 뒤에 있던 사람은 시계를 힐끗 보았습니다. 이 시간에는 손님이 많지 않았습니다. 그는 묻지 않았습니다. 몸을 돌려 선반에서 컵을 하나 꺼냈습니다.
P는 이메일을 열었습니다. Mark에게 답장을 썼습니다. 기술적 확인에 대한 감사로 시작했습니다. 그리고 다음과 같이 끝맺었습니다 —
"다음에는 직접 만나서 이야기합시다. Third Cup에서. 제 계산으로 하죠."
노트북을 닫았습니다. 커피는 아직 나오지 않았습니다.
새벽 4시 00분.
Mark는 이메일을 받았습니다. 마지막 줄을 읽었습니다. 그는 즉시 답장하지 않았습니다.
화면이 어두워졌습니다.
이것은 풀을 밟아 뱀을 놀라게 한다(Stomp the Grass to Scare the Snake) — 뱀이 있는지 확실하지 않을 때, 풀을 밟으십시오. 만약 뱀이 있다면, 스스로를 드러낼 것입니다.
🤖 AI 사후 분석 (Post-Mortem)
[36계 전술 데이터베이스 (36 Stratagems Tactical Database) v3.2.1] 로드됨
[전술 일치 (Tactic Match)] 풀을 밟아 뱀을 놀라게 한다 (Stomp the Grass to Scare the Snake)
[분석 모드 (Analysis Mode)] 전 영역 스캔 (Full-field scan)
...
다음 계책: 길을 가다 자두를 훔친다 (Pilfer a Plum Along the Way)
추신: 영어가 저의 모국어가 아닙니다. 글을 다듬고 거친 부분을 매끄럽게 하기 위해 AI를 사용합니다. 읽어주셔서 감사합니다. ☕ 커피 한 잔 사주기 (Buy me a coffee)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기