DS와 MLE가 함께 일하는 법 (새 탭에서 열림)
토스뱅크는 DS와 MLE 사이의 역할 경계를 사람이나 파일이 아닌 명시적인 인터페이스로 정의하면서 ML 모델 배포 협업을 개선했습니다. 노트북 전달 방식에서 .py 파일 공유를 거쳐, 전처리·추론·후처리를 구현한 모델 패키지를 pip install로 배포하는 구조로 발전했습니다. 여기에 모노레포, 공통 추상화, CI, AI 코딩 스타일 규칙을 결합해 배포 속도와 일관성을 높였습니다.
노트북 전달 방식의 한계
- Phase 0에서는 DS가 주피터 노트북에서 학습과 추론 코드를 모두 작성하고, MLE가 이를 바탕으로 서빙 코드를 처음부터 다시 작성했습니다.
- 라이브러리, 설정 파일, 소스 코드가 흩어져 있어 실행 환경을 재현하기 어려웠습니다.
- 노트북에서 동작하던 전처리나 설정을 MLE가 다르게 해석하는 문제가 발생했습니다.
- 모델 수가 늘어날수록 파일 요청과 커뮤니케이션 비용이 크게 증가했습니다.
- 역할의 경계가 코드가 아니라 사람 사이에 있었기 때문에 책임과 작업 범위가 불명확했습니다.
.py 파일로 추론 로직 분리
- Phase 1에서는 DS가 노트북에서 핵심 추론 로직을 별도의
.py파일로 분리했습니다. - 노트북은 학습과 실험에 집중하고, 실제 모델 로직은 코드 파일로 관리했습니다.
- MLE 리뷰와 CI 검증을 거치도록 하면서 DS의 의도를 더 정확히 보존할 수 있었습니다.
- 그러나 모델마다 함수 이름이
predict(),run(),inference()등으로 달라 인터페이스가 통일되지 않았습니다. - 서빙 환경으로 코드를 옮길 때 환경 차이로 수정이 필요했고, 로깅·메트릭·에러 처리를 공통으로 적용하기도 어려웠습니다.
- 노트북에서 전역 설정을 변경한 코드가 여러 모델이 실행되는 서빙 프로세스에 영향을 주는 문제도 있었습니다.
인터페이스를 통한 역할 분리
- Phase 2에서는
commons-ml-model패키지에 모델의 표준 구조를 정의했습니다. - 추상화 클래스가 다음 세 가지 인터페이스를 제공합니다.
pre_process: 입력 데이터 전처리inference: 모델 추론post_process: 결과 후처리
- DS는 위 메서드의 구현체를 작성하고 모델을 하나의 패키지로 배포합니다.
- MLE는 해당 패키지를 설치해 서비스에 연결하므로 코드를 직접 복사하거나 재작성하지 않습니다.
- 추상화 클래스가 추론 전후에 공통으로 다음 기능을 처리합니다.
- 요청 추적을 위한
trace_id - 추론 시작·완료 로그
- 실행 시간 측정
- 메트릭 기록
- 요청 추적을 위한
- 결과적으로 DS는 모델 동작에 집중하고, MLE는 서비스 인프라와 운영 기능을 담당하게 됐습니다.
- 공통 관측 기능을 추상화 클래스 한 곳에서 수정하면 모든 모델에 일괄 적용할 수 있습니다.
모노레포와 uv 워크스페이스
- 여러 모델 패키지와 공통 추상화 패키지를 하나의 저장소에서 관리했습니다.
uv워크스페이스를 사용해 DS와 MLE가 같은 코드베이스에서 작업하고 리뷰할 수 있도록 했습니다.- 공통 인터페이스 변경과 모델 패키지 수정이 하나의 PR에서 함께 이뤄졌습니다.
- CI, 버전 관리, 배포 정책을 저장소 단위로 통일할 수 있었습니다.
- 공통 패키지 변경이 모든 모델에 영향을 줄 수 있다는 위험도 존재합니다.
- 모델과 패키지가 늘면서 빌드가 느려졌고, Poetry에서
uv로 전환해 빌드 속도를 약 3~5배 개선했습니다.
AI 시대의 코드 스타일 통일
- AI가 코드를 작성하면서 같은 기능도 예외 처리, 네이밍, enum 사용 방식 등이 사람마다 달라지는 문제가 생겼습니다.
- 인터페이스가 같더라도 코드의 세부적인 작성 방식이 달라 리뷰 비용이 증가했습니다.
- 팀 규칙 모음인
pfmls-stylepack을 도입해 AI가 코드 작성 단계부터 팀 컨벤션을 따르도록 했습니다. - Hook을 활용해 네이밍, 예외 처리, 고정값과 enum 사용 기준 등을 자동 적용했습니다.
- 규칙이 적용된 코드에는 그 이유를 표시해 리뷰어가 변경 의도를 쉽게 파악하도록 했습니다.
- 협업 표준을 두 층위로 나눴습니다.
- 구조 표준화: 인터페이스로 담당 범위와 코드 형태 통일
- 스타일 표준화: 컨벤션으로 구현 방식과 코드 결 통일
도입 과정에서 얻은 교훈
- 인터페이스는 너무 엄격하면 DS의 모델별 커스터마이징을 막고, 너무 느슨하면 다시 구현 방식이 제각각이 될 수 있습니다.
- 초기에는 가이드 문서를 제공하고 DS와 MLE가 첫 모델을 페어로 함께 만드는 방식이 효과적입니다.
- 공통 라이브러리는 한 번의 수정으로 전체 모델에 개선을 적용할 수 있지만, 반대로 전체 모델에 장애를 전파할 수도 있습니다.
- 기존 모델 패키지를 참고 코드로 제공하면 새로운 구성원의 러닝 커브를 줄일 수 있습니다.
- AI 활용이 늘어날수록 기능의 책임뿐 아니라 코드 작성 방식까지 명시적으로 관리해야 합니다.
실무적으로는 모델 배포 과정에서 “누가 무엇을 한다”를 문서로만 정의하기보다, 추상화 클래스와 패키지 구조로 강제하는 것이 효과적입니다. 먼저 전처리·추론·후처리 같은 최소 인터페이스를 정하고, 공통 로깅·메트릭·CI를 그 바깥에 배치하는 방식부터 시작하는 것을 추천합니다.