[기초] Part 9. 모델은 파이프라인 위에서만 삽니다: 데이터 엔지니어링과 도구
좋은 모델도 배관이 없으면 종이 위의 아이디어입니다. 피처의 상당수가 만들어지는 SQL, 누출이 가장 자주 생기는 시점정합 조인, 학습과 서빙이 어긋나는 문제, 그리고 재현성과 데이터 품질까지. 신용 모델을 실제로 굴러가게 하는 일을 실무의 언어로 정리했습니다.
Part 8까지 아홉 편에 걸쳐 신용 데이터 사이언스가 왜 다른지를 다뤘습니다. 선택편향과 시간, 비대칭 비용, 인과, 검증과 거버넌스, 해석가능성과 공정성. 전부 개념의 이야기였습니다.
그런데 개념은 저절로 굴러가지 않습니다. 모델은 파이프라인 위에서만 살아 있습니다. 데이터를 모으고, 피처를 만들고, 학습하고, 점수를 내보내는 배관이 없으면 아무리 좋은 모델도 종이 위의 아이디어로 남습니다.
이번 편은 그 배관 이야기입니다. 화려하지 않은데 실무 시간의 상당 부분이 여기로 들어갑니다. 그리고 이 분야에서는 성능보다 정합성과 재현성이 먼저입니다.
가장 오래 붙잡고 있는 도구는 SQL입니다
모델링을 배우고 들어오면 파이썬을 주로 쓸 거라 생각하기 쉽습니다. 실제로는 SQL을 더 오래 씁니다.
피처의 상당수가 SQL에서 만들어지기 때문입니다. 최근 3개월 평균 사용액, 6개월 연체 횟수, 잔액의 추세와 변동성 같은 것들은 전부 시간 윈도우 집계입니다. 수천만 건짜리 거래 테이블에서 이걸 뽑아내는 일은 BigQuery 같은 대규모 데이터웨어하우스에서 벌어지고, 윈도우 함수가 주력 도구가 됩니다.
여기서 쿼리를 잘 쓴다는 건 결과를 맞히는 것만 뜻하지 않습니다. 파티셔닝과 클러스터링을 어떻게 잡느냐에 따라 같은 결과를 내는 쿼리의 비용이 몇십 배 차이 납니다. 피처 하나를 추가하는 일이 월 비용 문제가 되기도 합니다.
누출은 대개 조인에서 생깁니다
그런데 SQL에서 진짜 중요한 건 성능이 아닙니다. 데이터 누출을 막는 최전선이 쿼리 설계라는 점입니다.
Part 0에서 시간은 한 방향으로 흐른다고 했고, Part 3에서 그래서 OOT 검증을 쓴다고 했습니다. 그 원칙이 코드로 내려오면 이렇게 됩니다. 모든 조인과 집계가 의사결정 시점 기준으로만 이뤄져야 합니다. 이걸 시점정합 조인이라고 부릅니다.
말은 당연한데 실제로는 자주 깨집니다. 가장 흔한 사고는 현재 상태 테이블을 그냥 붙이는 것입니다. 고객 마스터에서 한도를 가져왔는데 그게 신청 시점의 한도가 아니라 지금 한도인 경우입니다. 연체 이력을 붙였는데 신청 이후에 생긴 연체까지 섞여 들어간 경우도 같습니다.
이 사고가 무서운 이유는 검증에서 안 잡히기 때문입니다. 누출된 피처는 학습에서도 검증에서도 똑같이 잘 맞습니다. OOT로 나눠도 양쪽이 다 오염돼 있으면 소용이 없습니다. 그래서 성적이 유난히 좋게 나오면 기뻐하기 전에 조인을 다시 들여다보는 게 맞습니다. 현장에서 AUC가 0.95를 넘으면 대개 축하할 일이 아니라 의심할 일입니다.
파이썬은 그다음입니다
데이터가 테이블로 나온 뒤부터가 파이썬 구간입니다.
처리에는 pandas를 쓰고, 데이터가 커지면 polars로 넘어가기도 합니다. 모델은 scikit-learn과 LightGBM, XGBoost가 주력이고, 통계적인 설명이 필요하면 statsmodels를 씁니다.
신용 쪽에는 이 분야 전용 도구가 따로 있습니다. Part 4에서 본 WOE 변환과 구간화, 스코어카드 스케일링은 매번 직접 짜기보다 optbinning이나 scorecardpy 같은 라이브러리를 쓰는 편이 빠르고 안전합니다. Part 6의 인과추론에는 DoWhy와 EconML, CausalML이 있고, Part 8의 해석에는 SHAP이 사실상 표준입니다.
도구 목록 자체는 금방 바뀝니다. 중요한 건 어떤 문제에 어떤 종류의 도구가 필요한지를 아는 쪽입니다.
학습 때와 서빙 때가 어긋나면
모델을 다 만들고 나면 점수를 실제로 내보내야 합니다. 그런데 여기서 조용한 사고가 자주 납니다.
학습할 때는 배치 SQL로 피처를 만들었는데, 서빙할 때는 실시간 API가 같은 이름의 피처를 조금 다르게 계산하는 경우입니다. 최근 3개월을 90일로 잡았느냐 직전 3개 달로 잡았느냐, 결측을 0으로 채웠느냐 평균으로 채웠느냐 같은 사소한 차이입니다. 이름은 같은데 값이 다릅니다.
이걸 학습과 서빙의 어긋남이라고 부릅니다. 검증 성적은 멀쩡한데 운영에서 점수가 이상하게 나오고, 원인을 찾는 데 몇 주가 걸리기도 합니다. Part 7에서 배포 후에 PSI로 모니터링한다고 했는데, PSI가 튀는 원인이 고객 변화가 아니라 이 어긋남인 경우도 적지 않습니다.
해법은 정의를 한 곳에 두는 것입니다. 피처스토어는 피처의 계산 규칙을 하나로 등록해 두고 학습과 서빙이 같은 정의를 가져다 쓰게 합니다. 거창한 시스템을 들이지 않더라도, 최소한 피처 정의를 코드 한 군데에 모아 두고 양쪽이 그걸 호출하게 만드는 것만으로도 상당 부분 막힙니다.
재현성은 검증의 전제입니다
Part 7에서 재현되지 않는 모델은 검증할 수도 감사받을 수도 없다고 했습니다. 그 재현성이 실제로는 이런 도구들로 만들어집니다.
코드는 당연히 Git으로 관리하고, 라이브러리 버전을 고정해 환경을 재현할 수 있게 합니다. 어떤 실험에서 어떤 설정으로 어떤 성적이 나왔는지는 MLflow 같은 실험 추적 도구에 남깁니다. 그리고 금융에서 특히 중요한 것이 데이터와 모델의 버전 관리입니다. 반년 전에 승인받은 모델이 어떤 데이터로 학습됐는지를 나중에 되짚을 수 있어야 하니까요.
모델 레지스트리에 어떤 버전이 언제 승인돼 운영에 올라갔는지를 기록해 두면, Part 7에서 말한 감사 추적이 자연스럽게 따라옵니다. 거버넌스 문서와 엔지니어링이 같은 것을 가리키게 되는 셈입니다.
데이터 품질이 곧 모델 품질입니다
마지막은 데이터 품질입니다.
결측과 이상치, 중복은 기본이고, 실무에서 더 무서운 건 정의가 조용히 바뀌는 경우입니다. 업스트림에서 코드 체계를 바꿨는데 아무도 알려주지 않아서, 어느 날부터 특정 피처의 분포가 통째로 달라지는 식입니다. 모델은 그걸 모른 채 계속 점수를 냅니다.
그래서 스키마와 값의 범위를 명시해 두는 데이터 계약을 걸고, 데이터가 제때 들어왔는지 신선도를 확인합니다. 신용에는 여기에 하나가 더 붙습니다. 신용정보기관에서 오는 정보에는 보고 지연이 있습니다. 어제 생긴 연체가 오늘 데이터에는 없을 수 있다는 뜻입니다. 이 지연을 모르고 피처를 만들면, 학습 때 보이던 정보와 실제 심사 때 보이는 정보가 또 달라집니다.
그래서, 성능보다 정합성입니다
이번 편은 개념보다 배관에 가까운 이야기였습니다. 그런데 이 배관이 앞의 아홉 편을 떠받칩니다. 시점정합이 깨지면 Part 3의 검증이 의미를 잃고, 학습과 서빙이 어긋나면 Part 7의 모니터링이 엉뚱한 곳을 가리키며, 재현이 안 되면 Part 7의 독립 검증 자체가 불가능해집니다.
그래서 이 분야에서는 모델 성능을 0.01 끌어올리는 것보다, 조인이 시점정합인지 확인하고 피처 정의를 한 곳에 모으는 쪽이 대개 더 큰 이득입니다.
이제 한 편 남았습니다. 아무리 잘 만들고 잘 굴려도, 모델은 누군가의 결정으로 바뀌지 않으면 아무 일도 일어나지 않습니다. 마지막 편에서는 점수를 결정으로 바꾸는 일, 그리고 그 결과를 다른 사람에게 전달하는 일로 마무리하겠습니다.