9. Model Registry — 이름으로 모델 집어 오기
이 장에서 처음 나오는 말4개
registered model등록 모델- 이름이 붙은 모델 묶음. 그 아래에 버전들이 쌓인다.
model version모델 버전- 등록할 때마다 1씩 늘어나는 번호. 내용은 바뀌지 않는다.
alias별칭- 특정 버전을 가리키는 이름표.
@champion처럼 쓰고 다른 버전으로 옮길 수 있다. stage단계Staging·Production같은 예전 방식의 고정 단계. alias로 대체됐다.
run_id를 코드에 박으면 생기는 일
섹션 제목: “run_id를 코드에 박으면 생기는 일”8장에서 모델을 기록하고 나면 models:/m-a1b2c3… 같은 URI가 생긴다. 실거래 코드가
이걸 직접 들고 있으면 문제가 세 가지다.
- 모델을 새로 학습할 때마다 코드를 고쳐 배포해야 한다.
- 그 32자 문자열이 어떤 조건의 모델인지 코드만 봐서는 모른다.
- 되돌리려면 예전 문자열을 어딘가에서 찾아와야 한다.
Model Registry는 이 사이에 한 겹을 넣는다. 모델에 이름을 주고, 그 이름 아래 버전을 쌓고, “지금 쓰는 것”을 별칭으로 가리킨다.
등록하는 두 가지 방법
섹션 제목: “등록하는 두 가지 방법”sqlite도 database backend이므로 지금 구성 그대로 Registry를 쓸 수 있다. file store였다면 못 썼을 기능이다.
-
기록과 동시에 등록한다. 가장 짧다.
mlflow.lightgbm.log_model(model,name="lgbm_o2n",signature=signature,registered_model_name="nxt_daily_o2n", # 없으면 만들고, 있으면 버전을 하나 늘린다) -
이미 기록된 모델을 나중에 등록한다. 연구 런을 한참 쌓아 두고 그중 하나를 고르는 흐름에 맞다.
import mlflowmv = mlflow.register_model(model_uri=f"models:/{model_id}", name="nxt_daily_o2n")print(mv.version) # 3 -
UI에서 버튼으로도 된다. 모델 화면의 등록 버튼을 누르면 새 이름을 만들지, 기존 이름에 버전을 더할지 묻는다.

두 번째 방식을 권한다. 연구 run은 대부분 기각된다. 학습할 때마다 자동 등록하면 Registry가 후보 목록이 되어 버리고, “등록됐다”는 사실이 아무 의미가 없어진다. 등록은 판단이 끝난 뒤의 행위여야 한다.
alias로 “지금 쓰는 것”을 가리킨다
섹션 제목: “alias로 “지금 쓰는 것”을 가리킨다”버전 번호는 늘기만 하고 바뀌지 않는다. 움직이는 건 alias다.
from mlflow import MlflowClient
client = MlflowClient("sqlite:///artifacts/mlflow.db")
# 검증을 통과한 버전을 champion으로 승격client.set_registered_model_alias("nxt_daily_o2n", "champion", version="3")
# 비교용으로 돌려 볼 후보client.set_registered_model_alias("nxt_daily_o2n", "challenger", version="4")
# 판단 근거를 버전에 붙여 둔다client.set_model_version_tag("nxt_daily_o2n", version="3", key="holdout_sharpe", value="0.91")client.set_model_version_tag("nxt_daily_o2n", version="3", key="dataset", value="chart-nxt_day_202608")소비자는 버전을 모른다.
model = mlflow.pyfunc.load_model("models:/nxt_daily_o2n@champion")되돌리기도 한 줄이다 — set_registered_model_alias(..., version="2")로 이름표만 옮기면 된다.
모델 파일은 그대로 있고 가리키는 곳만 바뀐다.
실거래가 이걸 쓰려면 무엇이 필요한가
섹션 제목: “실거래가 이걸 쓰려면 무엇이 필요한가”여기서 정직하게 짚을 게 있다. 지금 mlflow는 dev dependency다. python -m sshim_trader는
MLflow를 import하지 않고, 그게 0장에서 확인한 경계다. Registry를 실거래에
쓰려면 이 경계를 어떻게든 건드려야 한다.
| 방식 | 하는 일 | 대가 |
|---|---|---|
| A. 실거래에서 직접 로드 | 실거래가 mlflow를 런타임 의존성으로 갖고 models:/…@champion을 읽는다 | 매매 봇이 MLflow와 sqlite 파일에 의존하게 된다. MLflow가 깨지면 매매가 멈춘다 |
| B. 연구 쪽에서 내보내기 | 승격 시 champion 모델을 artifacts/live/model.pkl 같은 고정 경로로 복사한다 | 실거래는 파일 하나만 안다. 대신 복사 단계를 사람이나 스크립트가 챙겨야 한다 |
B를 권한다. 0장의 “MLflow는 부가 기능” 계약이 실거래에서 특히 중요하기 때문이다. Registry는 어느 모델이 champion인가를 결정하고 기록하는 자리로 쓰고, 실행 시점에 매매 봇이 참조하는 건 내보낸 파일로 둔다.
# 승격 스크립트: alias가 가리키는 버전을 실거래가 읽는 경로로 내보낸다mv = client.get_model_version_by_alias("nxt_daily_o2n", "champion")local = mlflow.artifacts.download_artifacts(mv.source, dst_path="artifacts/live")print(f"champion = version {mv.version} → {local}")이러면 판단의 이력은 Registry에, 실행의 의존성은 파일 하나에 남는다. 나중에 A로 옮기고 싶어져도
get_model_version_by_alias 한 줄을 실거래 쪽으로 옮기면 되니 되돌릴 수 없는 선택이 아니다.
지금 당장 할 일은 아니다
섹션 제목: “지금 당장 할 일은 아니다”전략이 아직 채택 전이라면 Registry는 비어 있는 게 정상이다. 이 장은 8장의 모델 기록을 시작하는 순간 함께 정해야 할 이름 규칙을 미리 정리해 둔 것이다. 실제로 필요한 건 셋뿐이다.
- 등록 모델 이름은 target별로 하나 —
nxt_daily_o2n,nxt_daily_o2c - alias는
champion하나로 시작하고, 비교 실험을 시작할 때challenger를 더한다 - 버전마다
holdout_sharpe·dataset·git_committag를 붙여 근거를 남긴다