Skip to main content

Mac k3s에서 서울 자전거 모델 검증하기: MLflow·Feast·Kubeflow·KServe

· 44 min read
Jinwoong Kim
Technologist and Cloud Consultant

이 글은 개인 학습 기록이며 현재 재직 중인 회사와 관계가 없다.

참고 자료: 최성욱 님의 ML Platform Engineering Part 2 핸즈온(확인한 커밋 162b2f7, 2026-11-02)과 Machine Learning Platform Engineering 4~6장. 참고 저장소의 도메인은 성인 소득 분류다. 이 글은 서울 공공자전거 시간별 수요 모델로 별도 실험한 결과이며, 참고 저장소의 실행 수치를 내 결과로 옮기지 않았다.

직접 실행한 범위: 2026년 11월 5일 Mac M3 Pro의 Rancher Desktop k3s에서 MLflow·Feast·BentoML·KServe 사이의 계약을 검사하는 Kubernetes Job을 실행했다. 같은 클러스터에 Kubeflow Notebook 컨트롤러와 자전거 노트북을 띄워 데이터 점검 셀도 실행했다. 기존 KFP는 standalone 설치이며, 이번 검증 Job은 KFP를 사용하지 않았다. Kubeflow 전체 배포판과 GitOps PR 프리뷰를 설치한 결과도 아니다.

시리즈 순서: 발행된 4~5장 (모델·피처·배치 추론) → 6장(BentoML 서빙·Evidently 배치 드리프트) → 7장(KFP 데이터 준비) → 이 글, Part 2 후속 검증(Notebook·KServe).

앞선 4~5장 서울 자전거 실험에서는 데이터를 모아 시차 피처를 만들고, MLflow에 모델을 등록하고, Feast로 피처를 조회하고, KFP로 미래 구간을 평가했다. 6장 실험에서는 등록된 모델을 BentoML API로 내놓았다. 7장에서는 같은 UCI 원본의 데이터 준비를 별도의 KFP 파이프라인으로 실행했다. 이 글에는 이번 검증 Job에 필요한 선행 환경을 만드는 파일과 실행 명령을 본문에 실었다. 다른 글이나 코드 저장소를 열지 않아도 이 글의 실험용 파일을 구성할 수 있다. 여기까지 오면 모든 구성요소가 따로는 정상처럼 보인다. 그러나 한 가지 질문은 남는다.

지금 API가 내놓는 숫자는 어떤 원본 데이터로 훈련한 모델이 어느 시각의 피처를 받아 계산한 값인가?

7장 글과 이 글의 범위는 다르다. 7장에서는 다운로드·검증·피처 생성·시간 분할·QA를 KFP의 서로 다른 Pod에서 실행하고, 단계별 Dataset 아티팩트가 SeaweedFS를 거쳐 전달되는지 확인했다. 이 글의 4.0절에 넣은 collect → features → train → infer → online은 Notebook·KServe 검증의 선행 환경을 만드는 일반 Kubernetes Job이다. 7장의 KFP 데이터 준비 결과를 MLflow·Feast 학습 입력으로 자동 승격시키는 연결은 아직 만들지 않았다. 따라서 이 글만으로 7장의 KFP 실험까지 재현했다고 볼 수는 없다.

참고 저장소의 Part 2에서 가장 배울 만한 점은 이 질문을 시스템 경계마다 확인한다는 것이다. MLflow의 모델 별칭에서 출처 Run과 데이터 기록까지 거슬러 올라가고, Feast의 오프라인·온라인 값을 대조하고, 서빙 API 결과를 직접 추론값과 비교한다. 참고 저장소에는 KServe가 Ready인데도 학습과 서빙의 라이브러리 차이로 예측값이 달라진 사례가 있다. 이 글에서는 같은 입력에 대해 직접 추론·BentoML·KServe가 같은 값을 내는지 Kubernetes Job으로 확인하고, Kubeflow Notebook에서 그 입력 데이터의 시간 규칙도 다시 검사했다.

7장: 서울 자전거 데이터를 KFP v2 아티팩트로 준비하고 검증하기

· 14 min read
Jinwoong Kim
Technologist and Cloud Consultant

이 글은 개인 학습 기록이며 현재 재직 중인 회사와 관계가 없다.

읽은 자료: Machine Learning Platform Engineering 7장. 직접 실행: 2026년 11월 5일 Mac M3 Pro, Rancher Desktop Kubernetes의 KFP standalone에서 아래 파이프라인을 실행했다. 이 KFP 실행 당시 Kubeflow Notebook 컨트롤러와 MinIO 서비스는 없었다. 노트북 UI 구성은 책의 내용으로 설명하고, 실행 결과는 실제로 설치된 KFP와 SeaweedFS 아티팩트 저장소 기준으로 적었다. 같은 날 뒤이어 진행한 Part 2 후속 실험에서 Notebook v1 컨트롤러를 추가했다.

시리즈 순서: 발행된 4~5장 (모델·피처·배치 추론) → 6장(BentoML 서빙·Evidently 배치 드리프트) → 이 글, 7장(KFP 데이터 준비) → Part 2 후속 실험(Notebook·KServe 정합성 검사).

4~5장의 서울 자전거 모델 실습은 원본 데이터를 Job으로 내려받고, Feast 피처와 MLflow 모델을 만든 뒤 KFP로 배치 추론했다. 이번에는 훈련보다 앞 단계인 데이터 준비를 KFP의 작업 단위로 옮겼다. 다운로드, 원본 검증, 시차 피처 생성, 시간 순서 분할, QA가 각각 다른 Pod에서 실행된다. 어느 단계에서 어떤 파일이 만들어졌는지를 KFP Dataset 아티팩트로 확인하는 것이 이번 실험의 목표다.

6장에서는 이미 등록된 모델을 API로 서빙하고 입력 분포를 배치로 검사했다. 여기서는 그 API를 다시 배포하지 않고 상류 데이터 준비를 별도의 KFP 실행으로 재구성한다. 같은 원본 데이터와 시간 분할 규칙을 사용하지만, 새 아티팩트가 기존 모델이나 온라인 피처를 자동으로 갱신하지는 않는다.

데이터 준비를 따로 떼어낸 이유는 간단하다. 소득 분류처럼 행을 섞어 나누면 자전거 수요의 미래 평가가 과거와 섞인다. lag_168을 만들기 전에 첫 168시간을 버리지 않으면 결측이 모델 입력에 들어간다. 두 규칙을 노트북의 기억에 맡기는 대신 파이프라인 코드와 QA 단언으로 고정해 봤다.

6장: 서울 자전거 모델을 BentoML로 서빙하고 Evidently 드리프트를 검증하기

· 20 min read
Jinwoong Kim
Technologist and Cloud Consultant

이 글은 개인 학습 기록이며 현재 재직 중인 회사와 관계가 없다.

읽은 자료: Machine Learning Platform Engineering 6장. 직접 실행: 2026년 11월 5일 Mac M3 Pro의 Rancher Desktop Kubernetes에서 BentoML API와 KFP 배치 드리프트 작업을 실행했다. Yatai, Evidently UI, 실제 시간별 새 데이터가 들어오는 온라인 드리프트 서비스는 설치·실행하지 않았다. 책의 소득 분류 수치를 서울 자전거 실험 결과로 옮기지 않았다.

시리즈 순서: 발행된 4~5장 (모델·피처·배치 추론) → 이 글, 6장(서빙·드리프트) → 7장(KFP 데이터 준비) → Part 2 후속 실험(Notebook·KServe 정합성 검사).

4~5장 서울 자전거 실험에서 MLflow 레지스트리에 seoul-bike-hourly 버전 1을 등록하고 champion 별칭을 붙였다. Feast에는 시간별 시차 피처를 올렸고, 미래 2,184시간을 따로 평가해 MAE 90.8443대를 확인했다. 6장의 질문은 두 가지다. 등록된 모델을 호출 가능한 API로 만들 수 있는가? 그 API가 받는 데이터가 훈련 때와 달라지면 알아챌 수 있는가?

발행된 4~5장 수치 정정: 그 글의 “원본에서 Functioning Day=No인 시간 247시간”은 미래 테스트 구간의 집계다. UCI 원본 8,760시간 전체에서는 295시간, 미래 테스트 구간에서는 247시간이다. 원본 ZIP·CSV의 SHA-256을 확인한 뒤 두 구간을 다시 집계했다.

책은 BentoML·Yatai로 배포를, Evidently로 배치·실시간 드리프트 감시를 설명한다. 그대로 따라 적기 전에 기존 실험의 제약을 확인했다. Feast Redis 온라인 스토어에는 city_id=seoul의 마지막 한 시각만 적재돼 있다. 따라서 임의의 예측 시각을 받으면서 같은 온라인 피처로 예측하거나, 같은 행을 50번 호출해 실시간 드리프트를 측정하면 잘못된 결과가 나온다. 이번 실험에서는 API가 실제로 적재된 시각만 받게 하고, Evidently는 시각이 다른 과거 행들의 배치로 검증했다.

서울 공공자전거 데이터로 진행한 Feast·MLflow·KFP 실험

· 44 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

읽은 자료: Machine Learning Platform Engineering 4~5장과 스터디 자료. 실습 데이터: UCI Seoul Bike Sharing Demand의 서울 시간별 공공자전거 대여량. 검증 환경: 2026년 10월 31일 Mac M3 Pro의 Rancher Desktop Kubernetes. 이 글의 Job·KFP 상태와 지표는 그날 실행해 남긴 기록을 바탕으로 한다.

책의 소득 분류 데이터를 그대로 따라가는 대신, 서울 공공자전거의 다음 한 시간 대여량을 예측하는 실험으로 4~5장을 다시 읽었다. 이 데이터에는 매 시간의 관측 시각이 있다. 덕분에 Feast가 예측 시각에 맞는 피처 행을 돌려주는지, MLflow에 등록한 모델을 KFP가 다시 찾는지, 무작위 평가 점수가 미래 구간에서도 유지되는지를 한 흐름에서 확인할 수 있다.

본론에 들어가기 전에, 이 글에서 묶는 세 도구를 한 줄로 정리한다. 모두 쿠버네티스 위에서 머신러닝 플랫폼을 이루는 오픈소스 구성요소이고, 각자 맡는 역할이 다르다.

도구한 줄 정의이 실험에서 맡은 일
Feast피처 스토어. 모델이 쓸 입력값(피처)을 한 번 정의해 저장하고, 과거 시점용(오프라인)과 실시간용(온라인)으로 같은 값을 제공한다예측 시각 기준으로 "그때 알 수 있던" 대여량·날씨 피처를 조회
MLflow실험 추적·모델 레지스트리. 어떤 데이터·설정으로 학습한 모델인지 기록하고, 버전을 붙여 등록·배포한다후보 모델의 지표·데이터 해시를 남기고 최종 모델을 버전 1로 등록
KFP(Kubeflow Pipelines)파이프라인 오케스트레이터. 여러 단계(컴포넌트)를 DAG로 묶어 순서대로 실행하고 상태를 관리한다등록된 모델을 재학습 없이 불러와 배치 추론 DAG로 실행

세 도구는 각각 하나의 질문에 대응한다. Feast: 예측 시각에 맞춰 만든 대여량·날씨 피처를 조회할 수 있는가? MLflow: 어떤 데이터와 피처로 선택한 모델인지 다시 찾을 수 있는가? KFP: 등록된 모델을 재학습하지 않고 배치 추론에 다시 쓸 수 있는가? 마지막에는 전체 소스와 제출 코드를 파일별로 본문에 실었다.

쿠버네티스 위에 ML 플랫폼 토대 쌓기 - Docker부터 GitOps·모니터링까지

· 11 min read
Jinwoong Kim
Technologist and Cloud Consultant

해당 포스팅은 현재 재직 중인 회사와 관련이 없고, 개인 역량 개발을 위한 스터디 자료로 활용할 예정입니다.

읽은 자료: Machine Learning Platform Engineering(Manning, 2026) 3장 실습 환경: Rancher Desktop의 k3s(v1.36.2+k3s1, arm64), Docker 29.5.3, Helm v4. 모든 명령과 출력은 2026년 10월 25일 로컬에서 직접 확인했다.

지난 글에서 1~2장을 읽으며 "모델보다 비즈니스 문제가 먼저"이고, 머신러닝의 가치는 폐쇄 루프 안에서 나온다는 개념 뼈대를 정리했다. 3장은 그 이론을 실제로 돌릴 수 있는 토대로 옮긴다. 저자들의 표현대로, 여기서 다루는 Docker·쿠버네티스·CI/CD·모니터링은 머신러닝 전용 기술이 아니라 대규모로 신뢰할 수 있는 머신러닝 시스템을 떠받치는 인프라다.

이 글은 책의 흐름을 따라 하나의 데모 앱을 Docker 이미지로 만들고, 쿠버네티스에 올리고, Helm으로 패키징하고, Argo CD로 GitOps 배포를 하고, Prometheus·Grafana로 관측하는 과정을 직접 실행한 기록이다. 앱은 요청 수를 세어 /metrics로 노출하는 작은 Go HTTP 서버다. 모니터링 단계에서 이 커스텀 지표가 Prometheus까지 흘러가는 것을 눈으로 확인하기 위해 골랐다.