Skip to content

CH09 - 살아있는 운영 표준의 탄생 ​

이 저장소는 「AI 시대에 개발자가 알아야 하는 인프라 구성 배포 with 클로드 코드」 책 스터디를 진행하며 정리한 내용을 다룹니다.

지금까지 설정을 만들고, 문서를 남기고, 결정을 기록하였다
이번 챕터에서는 AI에게 저장소를 분석시키고, 쌓인 것을 돌아보며 git과 AI 그리고 Ops가 어떻게 연결되었는지 정리한다.

저장소 분석 ​

AI에게 notiflex-platform 저장소 구조, 커밋 히스토리, JOURNEY.md와 실제 상태 일치 여부, 클러스터-Git 일치 여부를 분석시킨다.

분석 결과

구조 ​

text
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개) ​

챕터커밋 수핵심 내용
ch26초기 커밋, README, /update-docs 스킬, /version 엔드포인트, CI 추가
ch33ArgoCD Application, kube-prometheus/Loki values
ch44로그 추가, webhook-bridge(torchi.app), CA 인증서 수정
ch55Gateway API, Blue/Green 전환, v0.3.0, ADR-001~007
ch66Valkey INCR, Secret Manager+CSI 전환, Canary 전환, ADR-008~010
ch78노드풀 분리, App of Apps, 멀티테넌시, enterprise 시크릿 전환, ADR-011~014
ch85Kafka Producer/Consumer(v0.7.0), OTel+Tempo(v0.8.0), CronJob, 위험 작업 절차서
ci 자동6GitHub 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 일치 여부 ​

text
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)ArgoCDFluxCRD+UI 있음 vs 더 가벼움
CI (ADR-002)GitHub ActionsCloud Build, Jenkins같은 플랫폼 vs 벤더 종속 없음
메트릭 (ADR-003)Prometheus+GrafanaDatadog, Victoria Metrics표준 vs 매니지드 편의성
로그 (ADR-004)Loki+Fluent BitELK, CloudWatch저비용 라벨 인덱싱 vs 풀텍스트 검색력
알림 (ADR-005)Alertmanager+webhook-bridgePagerDuty, OpsGenie직접 구현 유연성 vs SaaS 편의성
트래픽 (ADR-006)GKE Gateway APINGINX, IstioGKE 네이티브 vs 이식성
배포 전략 (ADR-007, ch6.3)Blue/Green → Canary유지리소스 2x vs 1.2x, 위험 분산
캐시 (ch6.1)ValkeyRedis, Memcached라이선스 자유 vs 생태계 성숙도(Redis)
시크릿 (ADR-009, ch7.4 재사용)Secret Manager+CSI+WIExternal Secrets, 평문 Secret키 없는 인증 vs GCP 종속
노드 배치 (ch7.2)nodeSelectortaint/toleration단순함 vs "거부" 기능 없음
앱 관리 (ch7.3)App of AppsApplicationSet순수 YAML vs 템플릿 확장성
멀티테넌시 (ch7.4)Namespace+per-tenantvCluster리소스 효율 vs 강한 격리
메시징 (ch8.1)KafkaNATS, RabbitMQ실무 전이율 vs 클러스터 규모 적합성(NATS가 사실 더 나음)
트레이싱 (ch8.2)TempoJaeger, ZipkinGrafana 통합 vs 독립 UI
배치 자동화 (ch8.3)K8s CronJobAirflow, Argo Workflows네이티브 단순함 vs DAG 표현력

반복되는 선택 기준 4가지 ​

돌아보니 매 장의 결정에 이 네 가지가 계속 나타난다.

  1. GKE/managed 우선: ArgoCD 설치 방식, Gateway API 리전 선택, Secret Manager+GKE managed CSI — 학습 환경에서 운영 부담을 최소화하고 클라우드 네이티브 방식을 몸에 익히는 쪽을 매번 택함
  2. Argo 생태계 통일: ArgoCD와 Argo Rollouts를 묶어서 UX와 도구 체인을 하나로 유지 — 서로 다른 벤더를 섞지 않음
  3. Grafana 통합 관측: Prometheus, Loki, Tempo를 전부 Grafana 데이터소스로 붙여서 메트릭·로그·트레이스를 한 화면에서 상관 분석할 수 있게 만듦
  4. 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 두 앱은 실제로 이 루프가 끝까지 작동한다.

실제로 관찰된 루프 ​

text
독자 입력 (자연어)
    ↓
[탐색] 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를 접목시키니 메리트들을 직접 경험할 수 있어서 좋았다.

기록하는 과정이 매번 귀찮다고 느껴졌었는데 작은 프로젝트라도 이렇게 유의미한 결과들을 만들어내는 것을 보면 더 더욱 중요하다고 느낄 수 있었다.

온라인 스터디는 이번이 처음이었는데 같이하는 사람이 있다는 것만으로 학습 의지를 이어갈 수 있었다
학습 후 결과물을 공유해야 하고, 그렇지 못하면 탈락되는 장치가 있어서 그랬나 싶기도 하다

이 스터디를 열어주시고 운영해주신 서종호(가시다)님 그리고 책의 저자 조훈님에게 감사드린다.