이 글에서 다루는 것

Optional 레이어(Feature Store)를 실제로 ON/OFF하면서 Core 시스템이 독립적으로 동작하는지 검증하는 과정

선수지식


Optional ON/OFF

  • 확장 기능을 비파괴적으로 붙였다 떼는 구조

들어가며

ML 플랫폼을 설계하다 보면 자연스럽게 다음 질문이 등장합니다.

  • Feature Store를 붙일까?
  • 데이터 파이프라인 시스템을 추가할까?
  • 추가 실험 플랫폼을 도입할까?

이런 시스템들은 대부분 유용합니다.

하지만 동시에 다음과 같은 문제를 가져올 수 있습니다.

  • 플랫폼 복잡도 증가
  • 시스템 의존성 증가
  • 장애 전파 범위 확대

예를 들어 Feature Store를 Core 시스템에 강하게 연결하면

다음 상황이 발생할 수 있습니다.

Feature Store 장애
        ↓
Feature Pipeline 실패
        ↓
Training Pipeline 실패
        ↓
Serving Pipeline 영향

이런 구조는 운영 안정성을 떨어뜨립니다.

그래서 이 프로젝트에서는 확장 기능을

Core 시스템과 분리된 Optional 레이어로 설계했습니다.

그리고 중요한 목표가 하나 더 있었습니다.

Optional 기능을 실제로 붙였다 떼도 플랫폼이 정상 동작해야 한다.

이 글에서는 그 구조와 실제 실행 결과를 살펴봅니다.


Optional 레이어의 설계 목표

Optional 레이어의 핵심 목표는 다음 세 가지입니다.

1️⃣ Core와 완전히 분리

Optional 시스템은 Core 시스템과 독립적으로 동작해야 합니다.

즉,

Core
Baseline
Optional

세 레이어 사이에 필수 의존성이 없어야 합니다.


2️⃣ Attach / Detach 가능

Optional 기능은 다음이 가능해야 합니다.

Optional ON
Optional OFF

즉,

  • Feature Store를 붙일 수도 있고
  • 제거할 수도 있어야 합니다.

3️⃣ 제거 시 Core 영향 없음

Optional을 제거해도 다음 시스템은 정상 동작해야 합니다.

  • Airflow
  • MLflow
  • Triton
  • FastAPI

즉, 서빙 시스템이 Optional 기능에 의존하면 안 됩니다.


Optional ON 상태

먼저 Optional 기능이 활성화된 상태를 살펴보겠습니다.

Proof:

docs/proof/latest/optional_on/optional_on_run.txt

실제 실행 결과 일부:

[ON] OK: optional-envs-dev
[ON] OK: optional-envs-prod
[ON] OK: feast-dev
[ON] OK: feast-prod

즉, Optional 기능이 활성화되면 다음 애플리케이션이 생성됩니다.

optional-envs-dev
optional-envs-prod
feast-dev
feast-prod

이 시스템들은 Feature Store 환경을 구성합니다.


Optional 애플리케이션 구조

Optional 기능이 활성화되면

ArgoCD Application 목록에 다음 항목이 나타납니다.

Proof:

docs/proof/latest/optional_on/optional_scope_apps_after.txt

예시:

feast-dev
feast-prod
optional-envs-dev
optional-envs-prod
root-optional

이 구조를 보면 다음 특징을 확인할 수 있습니다.

  • Feature Store는 Optional 프로젝트에 속함
  • Root Optional Application이 이를 관리
  • Core 시스템과 완전히 분리됨

즉, Feature Store는 플랫폼에 추가된 확장 레이어입니다.


Optional OFF 구조

이제 Optional 기능을 제거하는 상황을 살펴보겠습니다.

Optional OFF는 단순히 Helm uninstall을 하는 방식이 아닙니다.

이 프로젝트에서는 Optional OFF를 다음 방식으로 수행합니다.

ArgoCD Application 삭제
→ Optional 레이어 detach

Proof:

docs/proof/latest/core_only/optional_off_run.txt

실제 실행 과정 일부:

[OFF] deleting app=feast-dev
[OFF] deleting app=feast-prod
[OFF] deleting app=optional-envs-dev
[OFF] deleting app=optional-envs-prod
[OFF] deleting app=root-optional

이 과정을 통해 Optional 애플리케이션이 제거됩니다.


Optional 제거 결과

Optional OFF 이후 Application 목록을 확인하면

Optional 앱이 완전히 사라진 것을 볼 수 있습니다.

Proof:

docs/proof/latest/core_only/optional_scope_apps_after.txt

결과:

OK: scope=optional apps = 0

즉,

  • Feature Store 관련 애플리케이션이 모두 제거되었고
  • Optional 레이어가 완전히 분리되었습니다.

중요한 포인트: Namespace는 유지

여기서 중요한 설계 결정이 하나 있습니다.

Optional OFF 시 namespace는 제거하지 않습니다.

Proof:

docs/proof/latest/core_only/optional_off_run.txt

예시:

feature-store-dev    Active
feature-store-prod   Active

즉,

  • namespace는 유지
  • 실제 리소스만 제거

이 방식에는 중요한 이유가 있습니다.

이유

namespace를 삭제하면 다음 문제가 발생할 수 있습니다.

  • PVC 제거
  • Storage 데이터 삭제
  • Access 정책 초기화

그래서 Optional OFF는 비파괴 detach 방식으로 설계했습니다.


Optional OFF 이후 Core 상태

Optional을 제거한 뒤

Core 시스템이 정상 동작하는지 확인해야 합니다.

Proof:

docs/proof/latest/core_only/core_health_probes.txt

결과:

FastAPI health

{"status":"ok"}

Triton readiness

HTTP/1.1 200 OK

즉,

  • Feature Store 제거 후에도
  • 서빙 시스템은 정상 동작합니다.

Optional 구조가 중요한 이유

이 구조의 가장 큰 장점은

운영 복잡도를 통제할 수 있다는 점입니다.

예를 들어 다음 상황을 생각해 볼 수 있습니다.

Feature Store 실험

Optional ON

→ Feature Store 실험 가능


Feature Store 장애

Optional OFF

→ Core 시스템 영향 없음


플랫폼 단순화

Optional OFF

→ 최소 ML 플랫폼 유지


즉, 플랫폼을 확장 가능한 구조로 만들면서도

Core 시스템을 안정적으로 유지할 수 있습니다.


이 설계의 핵심 메시지

이 프로젝트에서 Optional 레이어는

단순히 “추가 기능”이 아닙니다.

오히려 다음 문제를 해결하기 위한 구조입니다.

확장 기능이 코어 시스템을 망가뜨리지 않도록 하는 것

그래서 Optional 기능은 다음 특성을 가집니다.

Attach 가능
Detach 가능
Core와 독립
Baseline과 독립

이 구조 덕분에 플랫폼은

  • 단순한 형태로 시작할 수 있고
  • 필요할 때 확장할 수 있으며
  • 확장을 제거해도 안정적으로 유지됩니다.

다음 글

지금까지는 플랫폼 구조를 설명했습니다.

하지만 ML 플랫폼에서 가장 중요한 부분은

모델 생명주기 자동화 파이프라인입니다.

다음 글에서는 Airflow DAG을 중심으로

  • Feature Pipeline
  • Drift Gate
  • Train
  • Promotion / Shadow
  • Deploy
  • Observability

로 이어지는 E2E 파이프라인 구조를 살펴보겠습니다.

특히 다음 질문을 중심으로 설명합니다.

왜 학습 성공이 곧 운영 반영을 의미하지 않도록 설계했는가?

관련 코드:

dags/e2e_full.py
dags/pipelines/full_e2e.py
dags/mlops_lib/core/policy.py
dags/mlops_lib/quality/drift_gate.py

설계 판단 (Why This Way?)

Optional OFF 시 namespace를 삭제하지 않고 ArgoCD Application만 제거하는 비파괴 detach 방식을 채택하여 PVC와 데이터를 보존하면서 기능만 분리합니다. Optional 제거 후 FastAPI health와 Triton readiness를 실제 실행 결과로 확인하여 Core 독립성을 Proof로 증명했습니다.


다음에 읽을 글

GitOps 기반 E2E ML Platform - 운영 환경 반영 제어 — E2E DAG 파이프라인 구조