CH09 - 살아있는 운영 표준의 탄생
이 저장소는 「AI 시대에 개발자가 알아야 하는 인프라 구성 배포 with 클로드 코드」 책 스터디를 진행하며 정리한 내용을 다룹니다.
지금까지 설정을 만들고, 문서를 남기고, 결정을 기록하였다
이번 챕터에서는 AI에게 저장소를 분석시키고, 쌓인 것을 돌아보며 git과 AI 그리고 Ops가 어떻게 연결되었는지 정리한다.
저장소 분석
AI에게 notiflex-platform 저장소 구조, 커밋 히스토리, JOURNEY.md와 실제 상태 일치 여부, 클러스터-Git 일치 여부를 분석시킨다.
분석 결과
구조
notiflex-platform/
├── app/ # Go 애플리케이션 (main.go, webhook-bridge)
├── argocd/apps/ # App of Apps 하위 Application들
├── k8s/
│ ├── smb/ # 기본 테넌트 (Rollout, Service, CronJob, Gateway)
│ ├── enterprise/ # 멀티테넌시 (ch7.4)
│ ├── kafka/ # KafkaNodePool, Kafka, KafkaTopic
│ └── monitoring/ # alert-rules, webhook-bridge, tempo-datasource
├── helm-values/ # kube-prometheus, loki, fluent-bit, tempo
├── claude-context/ # 아키텍처 스냅샷
├── docs/ # ADR (architecture-decisions.md)
├── command-guardrails/ # 위험 작업 절차서
└── .github/workflows/ # CI (ci.yaml)파일/코드 규모는 YAML 712줄(26개) > Markdown 566줄(9개) > Go 310줄(2개)다. 매니페스트가 코드보다 2배 이상 많은 게 이 프로젝트 성격을 보여준다 — 애플리케이션 로직보다 "그걸 어떻게 배포·운영하는지"에 훨씬 많은 노력이 들어갔다는 뜻. K8s/GitOps 학습 저장소다운 비율이다.
커밋 히스토리 (총 50개)
| 챕터 | 커밋 수 | 핵심 내용 |
|---|---|---|
| ch2 | 6 | 초기 커밋, README, /update-docs 스킬, /version 엔드포인트, CI 추가 |
| ch3 | 3 | ArgoCD Application, kube-prometheus/Loki values |
| ch4 | 4 | 로그 추가, webhook-bridge(torchi.app), CA 인증서 수정 |
| ch5 | 5 | Gateway API, Blue/Green 전환, v0.3.0, ADR-001~007 |
| ch6 | 6 | Valkey INCR, Secret Manager+CSI 전환, Canary 전환, ADR-008~010 |
| ch7 | 8 | 노드풀 분리, App of Apps, 멀티테넌시, enterprise 시크릿 전환, ADR-011~014 |
| ch8 | 5 | Kafka Producer/Consumer(v0.7.0), OTel+Tempo(v0.8.0), CronJob, 위험 작업 절차서 |
| ci 자동 | 6 | GitHub Actions가 이미지 태그 갱신하며 자동 커밋 |
패턴: feat 커밋 → CI가 자동으로 ci: update image 커밋 추가 → 필요시 docs 커밋으로 JOURNEY/ADR 정리, 이 리듬이 매 장마다 반복된다.
JOURNEY.md ↔ 실제 상태 대조
작업 직후마다 JOURNEY.md를 갱신해와서 문서와 클러스터 상태가 일치한다. 노드풀 구성(default-pool 2 + api-pool 1 + worker-pool 1, ops-pool 미생성), 이미지 태그(sha-0c1d8bb, v0.8.0), Kafka 4.3.0·Tempo 2.9.0 버전 전부 기록과 일치.
클러스터 ↔ Git 일치 여부
NAME SYNC HEALTH
notiflex-enterprise Synced Healthy
notiflex-smb Synced Healthy
root-app Synced Healthy전부 Synced+Healthy. 다만 Prometheus/Grafana/Loki/Fluent Bit/Valkey/Kafka/Tempo는 Helm으로 직접 설치되어 ArgoCD Application으로 관리되지 않는다. GitOps 원칙이 지켜지는 건 notiflex-smb/notiflex-enterprise 두 앱뿐이고, 나머지 인프라 구성 요소는 매니페스트가 Git에 있어도 ArgoCD가 감시하지 않는 상태 — 회고에서 다룰 만한 구조적 공백이다.
쌓인 것들 돌아보기
회고
CLAUDE.md는 사실 안 자랐다
의외의 발견. notiflex-platform/CLAUDE.md는 최초 커밋 이후 단 한 번도 수정되지 않았다(28줄 그대로). 장이 진행될수록 컨텍스트가 쌓이는 문서는 CLAUDE.md가 아니라 JOURNEY.md였다. CLAUDE.md는 "프로젝트가 무엇인지"(기술 스택, GCP 설정, 행동 규칙) 같은 안정적인 상수를 담고, JOURNEY.md가 "무엇을 왜 선택했는지"를 계속 누적하는 역할 분담이 자연스럽게 이루어진 셈이다.
도구 선택 의사결정 종합 (JOURNEY.md 기준, 총 18건)
| 영역 | 선택 | 주요 대안 | 트레이드오프 |
|---|---|---|---|
| GitOps (ADR-001) | ArgoCD | Flux | CRD+UI 있음 vs 더 가벼움 |
| CI (ADR-002) | GitHub Actions | Cloud Build, Jenkins | 같은 플랫폼 vs 벤더 종속 없음 |
| 메트릭 (ADR-003) | Prometheus+Grafana | Datadog, Victoria Metrics | 표준 vs 매니지드 편의성 |
| 로그 (ADR-004) | Loki+Fluent Bit | ELK, CloudWatch | 저비용 라벨 인덱싱 vs 풀텍스트 검색력 |
| 알림 (ADR-005) | Alertmanager+webhook-bridge | PagerDuty, OpsGenie | 직접 구현 유연성 vs SaaS 편의성 |
| 트래픽 (ADR-006) | GKE Gateway API | NGINX, Istio | GKE 네이티브 vs 이식성 |
| 배포 전략 (ADR-007, ch6.3) | Blue/Green → Canary | 유지 | 리소스 2x vs 1.2x, 위험 분산 |
| 캐시 (ch6.1) | Valkey | Redis, Memcached | 라이선스 자유 vs 생태계 성숙도(Redis) |
| 시크릿 (ADR-009, ch7.4 재사용) | Secret Manager+CSI+WI | External Secrets, 평문 Secret | 키 없는 인증 vs GCP 종속 |
| 노드 배치 (ch7.2) | nodeSelector | taint/toleration | 단순함 vs "거부" 기능 없음 |
| 앱 관리 (ch7.3) | App of Apps | ApplicationSet | 순수 YAML vs 템플릿 확장성 |
| 멀티테넌시 (ch7.4) | Namespace+per-tenant | vCluster | 리소스 효율 vs 강한 격리 |
| 메시징 (ch8.1) | Kafka | NATS, RabbitMQ | 실무 전이율 vs 클러스터 규모 적합성(NATS가 사실 더 나음) |
| 트레이싱 (ch8.2) | Tempo | Jaeger, Zipkin | Grafana 통합 vs 독립 UI |
| 배치 자동화 (ch8.3) | K8s CronJob | Airflow, Argo Workflows | 네이티브 단순함 vs DAG 표현력 |
반복되는 선택 기준 4가지
돌아보니 매 장의 결정에 이 네 가지가 계속 나타난다.
- GKE/managed 우선: ArgoCD 설치 방식, Gateway API 리전 선택, Secret Manager+GKE managed CSI — 학습 환경에서 운영 부담을 최소화하고 클라우드 네이티브 방식을 몸에 익히는 쪽을 매번 택함
- Argo 생태계 통일: ArgoCD와 Argo Rollouts를 묶어서 UX와 도구 체인을 하나로 유지 — 서로 다른 벤더를 섞지 않음
- Grafana 통합 관측: Prometheus, Loki, Tempo를 전부 Grafana 데이터소스로 붙여서 메트릭·로그·트레이스를 한 화면에서 상관 분석할 수 있게 만듦
- GitOps 호환 우선: PrometheusRule, ADR, 모든 매니페스트를 UI 설정이 아니라 Git에 선언 — "설정을 어디서 바꾸는가"의 답이 항상 "Git"이었음
이 네 원칙이 장이 바뀌어도 결정 방식 자체는 일관되게 만들어준 축이다. 다만 완벽히 지켜지진 않았다 — 저장소 분석에서 확인했듯 Prometheus/Loki/Valkey/Kafka/Tempo는 실제로는 Helm 직접 설치라 ArgoCD가 관리하지 않는, 원칙 4번의 예외 지대다.
다시 선택한다면 — 후회가 아니라 트레이드오프 환기
- CSI Secret Driver vs Sealed Secrets (ch6.2): 지금은 GCP managed CSI로 갔지만, 클라우드 중립성이 중요했다면 Sealed Secrets도 검토할 가치가 있었다(대신 키 회전 부담을 직접 져야 함).
- Canary 도입 시점 (ch6.3): Blue/Green 직후 바로 Canary로 넘어갔는데, 멀티테넌시(ch7.4) 이후로 미뤘다면 두 테넌트에 걸친 트래픽 분배 시연이 더 풍부했을 수 있다.
- Valkey vs Redis Streams (ch6.1): 캐시는 Valkey, 메시징은 ch8에서 별도로 Kafka를 들였는데, Redis Streams로 캐시+메시징을 하나의 컴포넌트로 묶는 선택지도 있었다(대신 Kafka만큼의 파티션/컨슈머그룹 학습 기회는 없었을 것).
기대하지 않았던 효과
전통적인 운영 문서는 별도의 위키에 작성된다, 작성한 시점에는 정확하지만 시간이 지나면 코드와 괴리가 생긴다
- 문서를 업데이트하는 것을 잊기 때문
notiflex-platform의 문서는 코드와 같은 저장소에 위치해있다 작업 후에 /update-docs로 코드 변경과 동시에 문서를 갱신하여 매번 최신화를 하였다
- 개인적으로 코드의 컨벤션이나 구조와 같은 문서도 code와 가깝게 있는게 좋다고 생각한다
결국 AI가 내 의도에 맞는 결과를 내기 위해서는 컨텍스트가 공유되어야 한다
살아있는 문서가 AI의 아웃풋을 살아있게 한다 그리고 기존 구조에서 새로운 산출물을 만들 수 있게 함
GitAIOps 분석: Git, AI, Ops의 연결
분석
세 요소가 이 프로젝트에서 실제로 한 역할
Git: 코드(app/main.go)뿐 아니라 매니페스트(k8s/), 의사결정(JOURNEY.md, docs/architecture-decisions.md), 운영 절차(command-guardrails/)까지 전부 하나의 저장소에 있다. 이번 세션에서만 50개 커밋 중 대부분이 "코드 변경"이 아니라 "구성/문서 변경"이었다 — Git이 단순 소스 저장소가 아니라 운영 상태 전체의 기록으로 쓰였다.
AI(Claude Code): 요청이 들어올 때마다 decision-guides/로 탐색·비교를 돕고, prompt-guardrails/로 실행하고, 그 결과를 JOURNEY.md에 기록한다. ch7.2 IP 쿼터 문제처럼 가드레일에 없는 상황을 만나면 즉석에서 대안을 판단하고(private-nodes vs worker-pool 통합), 그 판단 자체도 다시 문서화한다.
Ops: JOURNEY.md에 적힌 도구 선택(ArgoCD, Argo Rollouts)이 실제로 클러스터를 Git 상태와 동기화하는 엔진이 된다. kubectl apply가 아니라 "커밋 → ArgoCD sync → 클러스터 반영"이 기본 경로였고, notiflex-smb/notiflex-enterprise 두 앱은 실제로 이 루프가 끝까지 작동한다.
실제로 관찰된 루프
독자 입력 (자연어)
↓
[탐색] decision-guides 참조 ──→ [비교] 대안 트레이드오프 제시 ──→ [실행] prompt-guardrails 따라 매니페스트/명령 생성
↓ ↓ ↓
JOURNEY.md 진행현황 갱신 도구선택 기록 한 줄 추가 Git push → ArgoCD sync → 클러스터 적용
↓ ↓ ↓
/update-docs로 ADR·아키텍처 스냅샷 누적
↓ ↓ ↓
다음 장 진입 시 AI가 JOURNEY.md·claude-context/ 자동 참조루프가 가속되는 게 실제로 보였다. ch7.2(멀티 노드풀)은 탐색→비교→실행에 IP 쿼터 트러블슈팅까지 겹쳐서 대화가 길었는데, ch8.1(Kafka)~8.3(CronJob)은 "Kafka로 설치해줘", "CronJob 만들어줘"처럼 탐색·비교를 생략하고 곧장 실행으로 들어가는 요청이 많았다. 이미 ch7에서 nodeSelector 패턴, worker-pool 배치 관행이 JOURNEY.md와 대화 맥락에 쌓여있어서, 매번 "왜 이 도구를 쓰는지"부터 다시 설명할 필요가 줄어든 것.
3-프롬프트 패턴과의 연결
책 전체를 관통하는 탐색→비교→실행 패턴이 사실 이 GitAIOps 루프 한 바퀴를 표현한 것이다. 가드레일과 JOURNEY.md가 쌓일수록:
- 탐색이 짧아짐: "Kafka 써야하지?" 같은 질문에 이미 ch8.1 decision-guide가 문맥과 함께 답을 갖고 있음
- 비교가 생략됨: 이미 대안을 알고 있으면 바로 "Kafka로 설치해줘"로 직행
- 실행만 남음: 매 장 뒤로 갈수록 "실행" 단계 비중이 커짐 — 책이 후반부로 갈수록 진행이 빨라지는 이유
JOURNEY.md 자체가 이 세 요소의 산물이다 — Git이 있어야 저장되고, AI가 있어야 매번 자동으로 채워지고, Ops(ArgoCD)가 그 내용을 실제 클러스터 상태와 계속 대조 가능하게 만들어준다. 이 셋 중 하나라도 빠지면 "살아있는 운영 표준"이 아니라 그냥 오래된 위키가 됐을 것이다.
스터디를 마무리하며
처음에 이 스터디에 관심을 갖게 된 이유는 서비스의 첫 시작을 위한 인프라 구축부터, 서비스가 커짐에 따라 고도화되는 인프라까지 이런 걸 처음부터 끝까지 느껴보고 싶어서였다.
하지만 실제 서비스가 아니다 보니 정말 운영을 하면서 얻을 수 있는 경험을 하기보단, 이 책이 GitAIOps에 포커싱을 맞춘 만큼 작업을 하고 기록을 하는 과정 자체를 반복해서 경험하게 되었다.
- 책에서 나온 다양한 도구는 한번 해봤다고 아는것이 아니라 개별적으로 더 깊은 학습이 필요하다
GitOps도 AI패러다임 전에 정말 매력적으로 느껴졌었는데 AI를 접목시키니 메리트들을 직접 경험할 수 있어서 좋았다.
기록하는 과정이 매번 귀찮다고 느껴졌었는데 작은 프로젝트라도 이렇게 유의미한 결과들을 만들어내는 것을 보면 더 더욱 중요하다고 느낄 수 있었다.
온라인 스터디는 이번이 처음이었는데 같이하는 사람이 있다는 것만으로 학습 의지를 이어갈 수 있었다
학습 후 결과물을 공유해야 하고, 그렇지 못하면 탈락되는 장치가 있어서 그랬나 싶기도 하다
이 스터디를 열어주시고 운영해주신 서종호(가시다)님 그리고 책의 저자 조훈님에게 감사드린다.