지난주 모델이 더 좋았는데 아무도 못 찾는다 · 지금 서비스 중인 것은 어느 파일인가 · 이론
버전은 사실, 별칭은 역할
한 줄 요약
레지스트리는 모델 파일을 모아 두는 창고가 아니라, 버전과 별칭으로 "지금 무엇이
서비스 중인가" 를 한 곳에서 답하게 만드는 장치다.
왜 이게 필요했나
실험이 잘 정리되고 나면 다음 질문이 온다. "그래서 지금 운영에서 돌고 있는 게
어느 거죠?" 놀랍게도 이 질문이 가장 자주 막힌다. 모델 파일은 S3 어딘가에model_final_v3_really.pkl 로 놓여 있고, 서빙 설정에는 그 경로가 문자열로 적혀
있으며, 그 파일이 어느 실행에서 나왔는지는 만든 사람 머릿속에 있다. 그 사람이
휴가를 가면 조직이 자기 모델을 설명하지 못한다.
되돌리기도 같은 이유로 어려워진다. 배포가 '경로 문자열을 바꾸는 일' 이면 되돌리기도
'경로 문자열을 되돌리는 일' 이라서, 급할 때 누가 어느 파일로 되돌렸는지가 남지
않는다. 사고 후에 타임라인을 그리려고 하면 채팅 기록을 뒤지게 된다.
어떻게 동작하나
MLflow 모델 레지스트리 문서는 이 문제를 네 가지 개념으로 정리한다
([MLflow Model Registry](https://mlflow.org/docs/latest/ml/model-registry/)).
| 개념 | 내용 |
| --- | --- |
| Registered Model | 이름을 가진 모델 하나. 버전·별칭·태그를 담는다 |
| Model Version | 같은 이름에 등록될 때마다 번호가 1씩 올라간다. 처음 등록하면 1 |
| Model Alias | 특정 버전을 가리키는 바뀔 수 있는 이름. champion 같은 것 |
| Tag | 키-값 꼬리표. 버전에도 붙는다(예: validation_status: approved) |
핵심은 버전과 별칭을 나눈 데 있다. 버전은 한 번 만들어지면 변하지 않는 사실이고,
별칭은 "지금 이 역할을 맡은 것" 을 가리키는 손잡이다. 운영이 models:/MyModel@champion
을 바라보게 해 두면, 배포는 별칭이 가리키는 버전을 바꾸는 일이 된다. 문서는 이
방식을 두고 운영 트래픽을 받을 버전에 별칭을 주고 그 별칭을 대상으로 삼으면,
다른 버전으로 별칭을 다시 지정하는 것만으로 서빙 대상을 바꿀 수 있다고 설명한다.
여기에 계보(lineage)가 붙는다. 등록된 각 버전은 그것을 만든 실행이나 로그된 모델과
연결되어 있어서, 어떤 데이터와 파라미터로 학습했는지를 거슬러 올라갈 수 있다.
앞 모듈에서 실행을 꼼꼼히 적어 둔 이유가 여기서 회수된다 — 레지스트리는 추적 위에
서고, 추적이 비어 있으면 레지스트리도 파일 목록 이상이 되지 못한다.
registry.json 버전 1, 2, 3 … (변하지 않는 사실)aliases.json champion → 2 (지금 누가 그 역할인가)audit.jsonl champion 1→2, 2→1 … (어떻게 여기까지 왔는가)별칭을 옮기는 일에는 한 가지 규율이 따라붙는다. 옮긴 사실을 어딘가에 적어야
한다는 것이다. 별칭 파일만 보면 "지금 champion 은 2번" 이라는 현재 상태만 알 수
있고, 어제까지 1번이었다는 사실은 남지 않는다. 그래서 별칭 옆에는 변경 이력이
따라다닌다. 바뀌기 전 값과 바뀐 값, 누가 왜 옮겼는지를 한 줄씩 쌓아 두면, 그
기록을 처음부터 재생했을 때 지금 상태가 그대로 나와야 한다. 나오지 않으면 누군가
기록 없이 손을 댄 것이다.
태그는 별칭보다 가벼운 표시다. 검증을 기다리는 버전에 validation_status: pending,
통과한 버전에 approved 를 붙이는 식으로 상태를 나타낸다. 별칭은 하나의 역할에
하나만 붙지만 태그는 여러 개가 붙을 수 있어서, 자동화가 읽는 조건으로 쓰기 좋다.
현장에서 만나는 모습
별칭 없이 버전 번호를 서빙 설정에 직접 박아 둔 팀은 되돌릴 때 배포 파이프라인을
다시 돌려야 한다. 급할수록 그 파이프라인이 오래 걸린다. 별칭을 쓰는 팀은 같은
상황에서 가리키는 곳만 바꾸고, 그 변경이 이력에 한 줄로 남는다.
반대 방향의 실수도 있다. 별칭을 너무 많이 만드는 것이다. champion, stable,prod, prod-real, prod-new 가 동시에 있으면 그중 무엇이 진짜인지 아무도
모르게 된다. 별칭은 역할의 수만큼만 둔다. 대개는 운영 하나와 도전자 하나로 충분하다.
세 번째는 버전을 지우는 습관이다. 실패한 버전을 레지스트리에서 삭제하면 목록은
깨끗해지지만, 그 버전이 왜 실패했는지도 함께 사라진다. 다음 분기에 비슷한 접근을
다시 시도하는 사람이 같은 벽에 부딪힌다.
네 번째는 레지스트리와 아티팩트 저장소를 같은 것으로 여기는 오해다. 모델 파일의
바이트가 어디에 놓이는지는 저장소의 일이고, 레지스트리가 답하는 것은 "그 바이트가
몇 번 버전이고 지금 어떤 역할을 맡고 있으며 어디서 왔는가" 다. 둘을 섞으면 파일을
옮길 때마다 배포가 깨지고, 반대로 파일은 그대로인데 역할이 바뀐 사실은 아무 데도
남지 않는다. 실습에서 registry.json 과 모델 파일을 따로 두는 이유가 이것이다.
다음 퀴즈에서 확인할 것
버전과 별칭이 각각 무엇을 책임지는지, 새 모델을 같은 이름으로 등록하면 번호가
어떻게 되는지, 되돌리기가 왜 별칭을 옮기는 일이어야 하는지를 확인한다.