MLflow 완전정복 다섯 번째 편. 지난 편에서 서버 띄우다 한참 헤맸는데, 그 답이 강의 자료 두 번째 슬라이드에 그냥 적혀 있었습니다.
이번 편은 기록을 남기기 전에 반드시 정해야 하는 두 가지 — Tracking URI와 Experiment 이야기예요.
📎 출처: 이 글은 인프런 강의 「실리콘밸리 엔지니어와 함께하는 MLflow」의 영문 강의 자료를 수강 후, 제가 공부하며 이해한 방향으로 한국어로 재구성한 것입니다.
🎯 1. 이번 편은 "기록하기 전" 이야기
이번 챕터에서 배우는 함수는 딱 네 개입니다. 그런데 넷 다 실제로 뭘 기록하는 함수는 아닙니다.
- set_tracking_uri() — 기록을 어디로 보낼지 정한다
- get_tracking_uri() — 지금 어디로 보내고 있는지 확인한다
- set_experiment() — 어느 서랍에 넣을지 정한다
- get_experiment() — 그 서랍 정보를 조회한다
강의 자료 첫 장은 이렇게 시작합니다.
"MLflow는 파라미터·메트릭·아티팩트·모델을 추적하는 로깅 함수들을 제공하며, 이는 MLflow Tracking API의 일부다."
즉 log_param(), log_metric() 같은 진짜 기록 함수는 다음 편이고,
이번 편은 그걸 쓰기 전에 자리를 잡아두는 내용이에요.
💡 내가 이해한 방향 — 종이에 글 쓰기 전에 "어느 노트에, 몇 번째 칸에" 쓸지 정하는 단계라고 이해했어요. 별거 아닌 것 같은데, 이걸 안 정하면 기록은 남는데 어디 남았는지 모르는 상태가 됩니다. 지난 편의 제가 그랬어요.
📍 2. Tracking URI — "어디에 쓸 건가"
강의 자료의 설명은 두 줄인데, 필요한 말은 다 들어 있습니다.
- MLflow 클라이언트를 특정 트래킹 서버에 연결할 때 필수적(essential)이다 — 로컬이든, 원격이든, 클라우드든
- 기본 동작 — 이 함수를 명시적으로 호출하지 않으면, MLflow는 현재 작업 디렉토리의 mlruns 폴더(로컬 파일 저장소)를 쓴다
제가 지난 편에서 한참 헤맸던 이유가 저 두 번째 줄에 있었습니다.
MLflow는 URI를 안 정해줘도 에러를 내지 않아요. 그냥 조용히 내 폴더에 쌓습니다. 그래서 이런 일이 벌어집니다.
- 서버는 멀쩡히 돌고 있고
- 스크립트도 에러 없이 잘 끝나고
- 그런데 웹 UI엔 아무것도 안 보이는
실패했는데 실패한 티가 안 나니까, 어디서부터 봐야 할지를 모릅니다. 자료가 알려주는 URI는 세 종류예요.
| 종류 | 형태 | 언제 |
| 로컬 파일 | file:/path/to/mlruns | 혼자 잠깐 돌려볼 때 (기본값) |
| 원격 서버 | http://<server-address>:5000 | 우리 케이스 (Docker로 띄운 서버) |
| 클라우드 | s3://<bucket-name>/mlruns | 팀·운영 환경 |
강의 코드는 URI를 환경변수에서 꺼내 읽는 방식으로 짜여 있습니다.
import os
import mlflow
# 환경변수에서 읽어온다. 값이 없으면 두 번째 인자인 ""(빈 문자열)
mlflow.set_tracking_uri(uri=os.getenv("MLFLOW_TRACKING_URI", ""))
# 지금 어디로 보내는 중인지 확인
print(f"Current Tracking URI: {mlflow.get_tracking_uri()}")
이 환경변수가 없으면 ""가 대신 쓰이고, 그 순간 로컬 폴더 행입니다. 그래서 실행할 때 이렇게 앞에 붙여줘야 해요.
MLFLOW_TRACKING_URI=http://localhost:5001 python3 logging_functions.py
그리고 get_tracking_uri()는 사실상 디버깅용입니다.
실행하자마자 이 줄이 먼저 찍히니까, 주소가 맞는지 여기서 바로 걸러낼 수 있어요.
💡 내가 이해한 방향 — 혼자 공부할 땐 로컬 폴더도 괜찮습니다. 문제는 팀이 되는 순간이에요. 내 맥의 mlruns 폴더는 아무도 못 봅니다. 동료 결과와 비교할 수도 없고요. 로컬 폴더에서 공용 서버로 갈아타는 스위치가 딱 이 한 줄이라서, 1편에서 재현성이니 협업이니 했던 이야기가 결국 이 한 줄이었구나 싶었어요.
🗂️ 3. Experiment — "어느 서랍에 넣을 건가"
자료의 정의는 한 줄입니다.
"Experiment는 런(run)의 논리적 묶음이다."
같은 프로젝트·유스케이스에 속한 런들을 한데 정리해주는 개념이에요.
왜 필요하냐면 — 런이 생각보다 훨씬 빨리 쌓이기 때문입니다. 하이퍼파라미터 하나 바꿔서 20번 돌리면 런이 20개예요.
서랍이 없으면 어제 돌린 이미지 분류 런과 오늘 돌린 추천 모델 런이 한 화면에 뒤섞입니다.
게다가 이름은 kindly-loon-220 같은 랜덤 작명이고요.
자료가 정리한 Experiment의 네 가지 특징입니다.
| 특징 | 설명 |
| Logical Grouping | 실험은 런을 담는 컨테이너. 하이퍼파라미터를 바꿔가며 돌린 런들을 한 실험에 묶는다 |
| Experiment Metadata | 고유 ID와 이름을 가지며, artifact location이 파일이 저장될 위치를 지정 |
| Runs | 각 실험은 여러 런을 담고, 런 1개 = ML 워크플로 1회 실행 |
| Lifecycle Stages | active / deleted 상태. active만 UI에 보이고, deleted는 명시적으로 조회해야 나온다 |
그리고 set_experiment()의 설명에서 제일 중요한 문장은 이거였어요.
- Sets or creates — 이미 있으면 그걸 쓰고, 없으면 새로 만든다
- Scope — 이 함수를 호출한 뒤에 시작되는 모든 런은 이 실험 아래에 기록된다
두 번째가 핵심입니다. set_experiment()은 한 번만 불러두면 됩니다. 그 뒤에 만드는 런들은 따로 지정하지 않아도 알아서 그 서랍으로 들어가요. get_experiment()는 바꾸지 않고 조회만 합니다. set_은 바꾸고 get_은 확인만 — Tracking URI 때랑 똑같아요.
💡 내가 이해한 방향 — Lifecycle의 deleted가 의외로 실용적이었어요. UI에서 실험을 지워도 DB에서 진짜 사라지는 게 아니라 딱지가 붙어 숨겨질 뿐이더라고요. 지난 편 README에서 봤던 mlflow runs list --view all의 그 all이, 바로 이 숨겨진 것까지 보겠다는 뜻이었어요. 지난 편엔 그냥 지나쳤는데, 이제야 왜 있는 옵션인지 알겠더라고요.
🧑💻 4. 코드 한 편으로 따라가기
강의 예제 logging_functions.py는 서랍 만들기 → 런 3개 넣기 → 나중에 하나 더 넣기 흐름입니다. 핵심만 추리면 이래요.
# ① 서랍 만들기 (없으면 생성, 있으면 그거 사용)
experiment = mlflow.set_experiment("new_experiment")
print(f"Experiment ID: {experiment.experiment_id}")
# ② 같은 서랍에 런 3개 넣기
for i in range(3):
with mlflow.start_run():
mlflow.log_param("iteration", i)
mlflow.log_metric("accuracy", 0.8 + i * 0.05)
with open("example.txt", "w") as f:
f.write("This is an example artifact.")
mlflow.log_artifact("example.txt") # 파일 첨부
# ③ 나중에 같은 서랍에 하나 더 (ID로 직접 지정)
with mlflow.start_run(experiment_id=experiment.experiment_id):
mlflow.log_param("new_param", 100)
mlflow.log_metric("new_metric", 0.95) # log_artifact 없음
실행하면 터미널에 이렇게 찍힙니다.
Current Tracking URI: http://localhost:5001
INFO mlflow.tracking.fluent: Experiment with name 'new_experiment'
does not exist. Creating a new experiment.
Experiment ID: 2
Experiment Name: new_experiment
Artifact Location: mlflow-artifacts:/2
Lifecycle Stage: active
Logged run under experiment 'new_experiment'
🏃 View run kindly-loon-220 at: http://localhost:5001/#/experiments/2/runs/830cfd...
🧪 View experiment at: http://localhost:5001/#/experiments/2
... (3번 반복) ...
Logged run under experiment ID 2
🏃 View run hilarious-croc-255 at: ...
여기서 처음에 헷갈렸던 게 출력 순서였어요.
내가 쓴 print가 먼저 나오고, 🏃 링크가 나중에 나옵니다.
MLflow는 with 블록을 빠져나가는 순간 "이 런 끝났습니다, 여기서 보세요"라며 링크를 찍어주기 때문이에요.
그리고 반복문은 3번인데 런은 4개가 됩니다.
③번 블록이 반복문 바깥에 있어서 그래요. start_run() 한 번 = 런 하나입니다. 서버에 실제로 들어간 결과를 보면 이렇습니다.
| 이름 | 파라미터 | 지표 | 첨부파일 |
| kindly-loon-220 | iteration 0 | accuracy 0.8 | example.txt |
| blushing-fish-498 | iteration 1 | accuracy 0.85 | example.txt |
| intrigued-colt-494 | iteration 2 | accuracy 0.9 | example.txt |
| hilarious-croc-255 | new_param 100 | new_metric 0.95 | — |
숫자가 0.8 → 0.85 → 0.9 → 0.95로 이어지는 것처럼 보이지만, 마지막은 이름이 다른 지표입니다.
반복문의 accuracy는 range(3)이라 0.9에서 끝나고, 0.95는 마지막 블록에 손으로 써넣은 new_metric이에요.
엑셀로 치면 아예 다른 열입니다.
💡 내가 이해한 방향 — 마지막 런에만 첨부파일이 없는 이유는 간단합니다. 그 블록에 log_artifact 줄이 없어서예요. 그런데 그 순간에도 example.txt는 폴더에 멀쩡히 있었어요. 파일이 폴더에 있는 것과, 그 파일이 런에 붙는 건 완전히 별개였어요. 택배도 상자만 싸놓으면 안 가잖아요. 접수를 해야 갑니다. MLflow도 내가 시킨 것만 기록해요. 안 시키면 에러도 경고도 없이 그냥 없습니다.
🔍 5. 내 출력이 강의 자료와 다른 이유
강의 자료의 예시 출력과 제 화면을 나란히 놓으면 두 줄이 다릅니다.
# 강의 자료
Current Tracking URI: http://0.0.0.0:5000
Artifact Location: /mlflow/mlruns/2
# 내 화면
Current Tracking URI: http://localhost:5001
Artifact Location: mlflow-artifacts:/2
틀린 게 아니라 실행 위치와 서버 설정이 달라서입니다.
- URI가 다른 이유 — 강사님은 컨테이너 안에서 실행해 내부 주소가 그대로 보이고, 저는 컨테이너 밖(맥)에서 실행해 포트 매핑 주소를 씁니다
- Artifact Location이 다른 이유 — 지난 편에서 --serve-artifacts로 바꿔뒀기 때문입니다. 폴더 경로가 아니라 mlflow-artifacts:/라는 형태로 나오는 게 "창고에 직접 들어가지 않고 접수처에 맡긴다"는 뜻이에요
처음엔 뭘 잘못 건드린 줄 알았는데, 지난 편에서 고쳐둔 설정이 그대로 살아 있다는 뜻이었습니다. "컨테이너 안과 밖은 다른 세상"이라는 4편 이야기가 여기까지 이어지네요.
✍️ 마무리 & 다음 단계
이번 편을 한 문장으로 줄이면 이렇습니다.
MLflow에게 기록을 시키기 전에 어느 서버로(Tracking URI), 어느 서랍에(Experiment) 보낼지 먼저 알려줘야 한다.
안 알려주면 에러도 없이 다른 데 저장된다.
한참 헤맸던 문제의 답이 강의 자료에 이미 적혀 있었다는 게 이번 편에서 제일 민망했던 부분이에요.
삽질하고 나서 다시 보니 그제야 그 문장이 눈에 들어오더라고요.
순서는 뒤바뀌었지만, 다음부터는 뭐가 안 보이면 URI부터 확인하게 될 것 같습니다.
다음 편은 실제로 기록하는 함수들입니다.
👉 다음 편 → [#6] log_param·log_metric·log_artifact 제대로 쓰기 (강의 진도에 따라 제목은 바뀔 수 있어요)
📎 출처: 이 글은 인프런 「실리콘밸리 엔지니어와 함께하는 MLflow」 강의의 영문 자료를 수강 후, 개인 학습 목적으로 이해한 방향에 따라 한국어로 재구성한 것입니다. 잘못 이해한 부분이 있다면 댓글로 알려주세요. 🙏
'새로운, 신나게 > MLFlow, 공부하는 중' 카테고리의 다른 글
| [MLflow 완전정복 #3] MLflow란 무엇인가? — 4가지 핵심 컴포넌트 (0) | 2026.07.07 |
|---|---|
| [MLflow 완전정복 #2] 기존의 모델 개발 사이클, 뭐가 문제였을까? (0) | 2026.07.07 |
| [MLflow 완전정복 #4] Docker로 MLflow 설치하고 첫 실험 기록해보기 (0) | 2026.07.07 |
| [MLflow 완전정복 #1] MLOps란 무엇인가? — 모델은 만들었는데, 운영은 누가 하지? (0) | 2026.07.06 |