21 KiB
1단계 · 운영 사실
- 교시: 1교시 강의 (09:00
09:50) · 2교시 Lab 01 실습 5개 (10:0010:50) - 이 단계가 끝나면: 운영 담당자가 아침에 묻는 것을 영역 여섯으로 나눠 말하고, 흩어진 출처를 정의가 정해진 사실 하나로 모으고, 기간에 따르는 숫자와 "지금" 숫자를 나누고, 0(없었음)과
null(모름)을 구분하고, 정해진 기준으로 영역마다 색을 매기고, 출처 하나가 멈춰도 나머지 사실을 내놓을 수 있다. - 숫자: 모두 강사 노트북 실측입니다 (65일차 n8n 2.42.6, 79일차 판 데이터 API — 2026-11-04 08:30 운영 아침 상태, 실행 기록 666건, 11/01 실습을 5개로 늘린 뒤 정답 워크플로우를 학생 순서대로 1회). 사실 · 상태는 Code라 누가 돌려도 같습니다. 출력 전부는 수업 뒤 공개되는
Last3Mon/79/answers/LAB-TEST-RESULT.md에 있습니다. - 실습 가리키기: 이 문서에서 "Lab 01 예제 1"은 2교시 Lab 01 문서의 그 절입니다. 파일 경로(
cases/·requests/·my-work/·reference/)는 실습 폴더~/aio-01d4-stu/Last3Mon/79기준입니다.
flowchart LR
A["1. 운영 도우미"] --> B["2. 출처 여섯 ·<br/>없는 칸"] --> C["3. 사실 하나로"] --> D["4. 기간과 지금 ·<br/>0과 null"] --> E["5. 상태는 규칙으로"]
E --> F["6. 출처가 멈추면"] --> G["7. 요청문으로"]
0. 이 시간 (50분)
| 시간 | 절 · 개요 | 하는 일 |
|---|---|---|
| 09:00~09:06 | 개요 1~6장 | 오늘 하루, 수요일 아침 08:30, 실습 15개 |
| 09:06~09:13 | 1 · 개요 7장 | 운영 도우미가 하는 일 · 하지 않는 일 |
| 09:13~09:20 | 2 · 개요 8~9장 | 출처 여섯, 기준 대시보드의 없는 칸 |
| 09:20~09:28 | 3 · 개요 10장 | 사실 하나로 — 정의는 다시 만들지 않는다 |
| 09:28~09:34 | 4 · 개요 11장 | 기간과 지금, 0과 null |
| 09:34~09:43 | 5 · 6 · 개요 12~14장 | 상태는 규칙으로, 출처가 멈추면 |
| 09:43~09:50 | 7 · 8 · 확인 질문 | 요청문, 자주 하는 실수 |
2교시 Lab 01에서 이어서 하는 것
| 2교시 실습 (시각) | 이 강의의 절 | 실습에서 하는 일 | 쓰는 파일 · 명령 |
|---|---|---|---|
| 시작 (10:00) | — | 운영 도우미 설계표 복사 | cp templates/OPS-ASSISTANT-TEMPLATE.md my-work/OPS.md (오늘의 사실 · 기준 · 거절을 모두 여기에) |
| Lab 01 예제 1 (10:00~10:10, 에이전트 없이) | 1 · 2 | 출처를 morning으로 둘러보고 기준 대시보드와 비교 |
morning, call base-ops-facts requests/week2.json → OPS.md 1절 |
| Lab 01 예제 2 (10:10~10:25) | 3 | 운영 사실 my-ops-facts |
my-work/ops-facts.json (새로), 테스트 cases/lab01.json (전: --webhook base-ops-facts) |
| Lab 01 예제 3 (10:25~10:32, 에이전트 없이) | 4 | 기간을 바꾸면 | test cases/lab01-period.json -v → OPS.md 2절 |
| Lab 01 과제 1 (10:32~10:42) | 5 | 영역별 상태 | 테스트 cases/lab01-challenge.json → OPS.md 3절 |
| Lab 01 과제 2 (10:42~10:50) | 6 | 출처가 멈추면 | 테스트 cases/lab01-challenge2.json (사용량 출처를 멈춤) |
1. 운영 도우미: 아침 08:30에 묻는 것 (2교시 Lab 01 예제 1)
일반 설명
생활 속 예 · 병원 아침 인수인계. 아침 8시 반, 밤 근무 간호사가 낮 근무에게 병동을 넘깁니다. "열이 오른 환자 둘, 수액이 끝나 가는 환자 하나, 검사 결과를 기다리는 환자 셋." 차트 열두 개를 처음부터 다 읽지 않고, 정해진 항목을 정해진 순서로 말합니다. 넘겨받는 사람은 "지금 괜찮나? 무엇부터 볼까?"만 알면 됩니다. 오늘 만드는 운영 도우미가 이 인수인계입니다.
운영 도우미(operations assistant)는 "지금 괜찮나? 무엇부터 볼까?"에 답하는 프로그램입니다. 서비스를 운영하면 정보가 여러 곳에 흩어집니다 — 실행 기록, 울린 알림, 처리하지 못하고 쌓인 일, 데이터 품질, 쓴 비용, 지금 나가 있는 판(버전). 운영 담당자는 아침마다 이것을 하나씩 열어 봅니다. 업계에서는 이것을 한 화면 · 한 대화로 모으는 일을 이렇게 부릅니다.
| 이름 | 하는 일 | 예 |
|---|---|---|
| 운영 대시보드 | 숫자 · 색을 한 화면에 | Grafana, Datadog 대시보드 |
| ChatOps | 대화창에서 운영 상태를 묻고 답을 받음 | Slack 봇, PagerDuty · Opsgenie의 Slack 연동 |
| AIOps | 운영 데이터에 AI(이상 탐지 · 요약 · 분류)를 씀 | Datadog Bits AI, Dynatrace Davis |
| 아침 브리핑 · 스탠드업 리포트 | 정해진 시간에 먼저 볼 것을 정리 | 당번 인수인계 문서 |
원칙은 하나입니다: 숫자 · 상태는 Code(프로그램)가, 글은 LLM이, 작업은 사람이. 숫자를 세고 색을 정하는 일은 언제나 같은 답이 나와야 해서 프로그램이 하고, 사람이 읽기 좋은 문장만 LLM이 씁니다. 그리고 운영 도우미는 읽기만 합니다. 실패한 일을 다시 돌리거나, 새 판을 끄거나, 예산을 바꾸는 작업은 사람이 런북(runbook, "이런 일이 생기면 이렇게 한다"를 미리 적어 둔 작업 안내서)대로 합니다 (2단계).
오늘 실습에서
uv run tools/flow.py morning으로 본 2026-11-04 08:30 (Lab 01 예제 1):
| 출처 | 지금 | 남긴 날 |
|---|---|---|
| 알림 | 6건 (높음 3): FAQ timeout · 429 · B-1 거절 · 낮은 점수 둘 · 접수 API 503 | 76 · 77 · 78일차 |
| DLQ | 3건, parked 2 | 76일차 |
| 품질 기록 · 격리함 | 4줄 (점수 0 · 0.8 · 0.8333 · 1) · 격리 1 | 78일차 |
| 사용량 · 예산 | $0.073604 / $0.08 (약 92%) | 75일차 |
| 릴리스 | 1.1.0 + 카나리 1.2.0 20% | 74일차 |
| 실행 기록 | 666건 (10/19~10/30) | 77일차 |
2. 출처 여섯과 기준 대시보드: 없는 칸이 가장 위험하다 (2교시 Lab 01 예제 1)
일반 설명
생활 속 예 · 체온만 적힌 인수인계 메모. 밤 근무가 "모두 체온 정상"이라고만 적어 두었습니다. 거짓은 없습니다. 그런데 메모에 "수액" 칸이 없어서, 수액이 끝난 환자가 있다는 것을 낮 근무는 모릅니다. 틀린 숫자는 누군가 고치지만, 없는 칸은 아무도 묻지 않습니다.
대시보드의 실수는 두 가지입니다: 틀린 숫자와 없는 칸. 틀린 숫자는 누군가 "이상한데?" 하고 알아챕니다. 없는 칸은 "그 영역은 괜찮다"처럼 보입니다. 그래서 운영 도우미를 만들 때는 먼저 무엇을 물어야 하는지(영역)를 정합니다.
| 영역 | 묻는 것 | 빠지면 |
|---|---|---|
| 실행 | 오류가 늘었나, 느려졌나, 답을 못 하나 | 장애를 사용자가 먼저 앎 |
| 알림 | 무엇이 울렸나, 얼마나 급한가 | 높은 알림이 묻힘 |
| DLQ (처리하지 못한 일을 모아 두는 곳) | 사람이 볼 일이 남았나 | 접수 건이 사라짐 (76일차) |
| 품질 | 들어온 데이터를 믿을 수 있나 | 틀린 FAQ로 답함 (78일차) |
| 비용 | 한도 안인가, 누가 쓰나 | 오후에 서비스가 멈춤 (75일차) |
| 릴리스 | 지금 무슨 판(버전)이 나가나, 새 판은 괜찮나 | 일부 사용자에게 먼저 내보낸 새 판(카나리)이 나쁜데 계속 나감 (74일차) |
Google SRE의 "네 가지 황금 신호"(지연 · 트래픽 · 오류 · 포화)가 서비스 하나의 영역이라면, 오늘의 여섯은 AI 워크플로우 운영의 영역입니다 — 품질 · 비용 · 릴리스가 더해집니다.
오늘 실습에서
팀의 기준 대시보드(base-ops-facts)에 지난주를 물으면 (Lab 01 예제 1):
| 출처 | morning |
기준 대시보드 |
|---|---|---|
| 실행 | (지난주 357건) | 666건 · 오류율 3.153153… (기간 무시 · 백분율) |
| 알림 · DLQ | 6 · 높음 3, 3 · parked 2 | 6, 3 (높음 · parked 없음) |
| 품질 · 릴리스 | 4줄 · 격리 1, 카나리 1.2.0 20% | 칸 없음 |
- 기준만 보는 사람은 오늘 가장 급한 둘(parked 2건 · 카나리)을 모릅니다.
3. 사실 하나로: 정의는 다시 만들지 않는다 (2교시 Lab 01 예제 2)
일반 설명
생활 속 예 · 병원 공용 차트 양식. 간호사마다 자기 공책에 "고열"을 다르게 적으면(37.5도? 38도?) 인수인계 때마다 다툽니다. 병원은 그래서 차트 양식 하나에 "고열 = 38도 이상"을 박아 두고 모두 그것을 씁니다. 새 화면을 만들 때도 양식을 새로 쓰지 않고 그 차트를 읽습니다.
운영 사실(facts)은 여섯 출처를 정해진 정의로 모은 JSON 하나입니다. 다음 단계(질문 답변 · 브리핑 · 평가 · 터미널 도구)는 모두 이 사실만 읽습니다. 정의가 사실 한 곳에 있으면, 질문 답변이 말하는 오류율과 브리핑 표의 오류율이 같습니다. 업계에서는 지표의 정의를 한 곳에 두는 층을 시맨틱 레이어(semantic layer, metrics layer — dbt Semantic Layer · Cube · LookML)라고 부릅니다.
| 원칙 | 까닭 |
|---|---|
| 77일차 정의 그대로 (오류율 · p95 · 답 못 함) | 정의가 두 벌이면 같은 날 다른 숫자 (77일차에 겪음) |
| 비율은 0~1, 소수 4자리 | 백분율(3.15)과 비율(0.0315)을 섞으면 기준(0.01)과 비교가 틀림 |
| 계산은 Code 하나 | LLM은 숫자를 세지 않음 — 세는 순간 날마다 달라짐 |
| 출처는 읽기만 | 사실을 만드는 데 상태를 바꿀 까닭이 없음 |
오늘 실습에서
내 my-ops-facts의 지난주 (Lab 01 예제 2, lab01 5/5):
| 영역 | 사실 |
|---|---|
| 실행 | 357건 · 오류 21 · 0.0588 · p95 2598ms · 답 못 함 0.0476 · 실패 1위 Search FAQ timeout 16 |
| 알림 · DLQ | 6 · 높음 3 · 이유별, 3 · parked 2 · 대기 1 |
| 품질 | 4배치 · 평균 0.6583 · 마지막 1 · 거절 1 · 격리 1 |
| 비용 | 156요청 · 192호출 · $0.073604 / $0.08 = 0.9201 · 1위 test-bot 37% |
| 릴리스 | 1.1.0 · 카나리 1.2.0 20% · 다시 묻기 7.73% 대 62.5% |
- 357 · 0.0588 · 2598 · 16은 77일차
my-log-report의 둘째 주와 같은 숫자입니다. 출처 여덟을 읽어 Code 하나에서 0.1초.
4. 기간과 지금: 0과 null은 다르다 (2교시 Lab 01 예제 3)
일반 설명
생활 속 예 · "어젯밤 몇 번 열이 났나"와 "지금 체온". 인수인계에는 두 가지 시간이 섞입니다. "밤새 열이 두 번" — 기간의 숫자. "지금 37.2도" — 지금의 숫자. 그리고 "어젯밤 소변량은 재지 않았음"은 "소변 0"과 전혀 다릅니다. 0이라고 적으면 큰일 납니다.
숫자에는 시간의 종류가 있습니다.
| 종류 | 뜻 | 흔한 예 |
|---|---|---|
| 기간(window) 숫자 | 정한 기간에 일어난 일의 합 · 비율 | 지난주 주문 수, 지난달 오류율 |
| 지금(point-in-time) 숫자 | 바로 이 순간의 상태 | 지금 쌓여 있는 문의 수, 지금 남은 예산 |
기간을 바꾸면 기간 숫자만 바뀌어야 합니다. "지난달을 보여 줘"라고 했는데 지금 쌓인 문의 수까지 지난달 값으로 바뀐다면 정의가 섞인 것입니다. 보고할 때도 "실행은 지난주, 나머지는 오늘 아침 지금"처럼 두 시간을 나눠 말합니다.
그리고 "없었다"와 "모른다"를 나눕니다.
| 값 | 뜻 | 예 |
|---|---|---|
| 0 | 셀 것이 있었고, 그 결과가 0 | 주문이 0건인 날의 오류율 = 0 |
null (값 없음) |
셀 수 없었다 · 말할 수 없다 | 주문이 0건인 날의 "가장 많이 실패한 상품", 그 판이 한 번도 쓰이지 않은 날의 그 판 오류율 |
null을 0으로 바꾸면 "모른다"가 "좋다"로 보입니다. 다음 절의 색 판정에서 바로 문제가 됩니다. 데이터베이스의 NULL, 통계의 결측값(missing value)과 같은 생각입니다.
오늘 실습에서
같은 사실에 기간 넷 (Lab 01 예제 3, 5/5):
| 기간 | 실행 | 다시 묻는 비율 (1.1.0 · 1.2.0) | 지금 숫자 |
|---|---|---|---|
| 두 주 | 666 · 0.0315 | 7.73% · 62.5% | 그대로 |
| 하루 (10/26) | 70 · 0.2286 | null · null — 두 판은 10/28부터 |
그대로 |
| 빈 주 (11/02~) | 0 · 오류율 0 · p95 0 · 실패 1위 null |
null · null |
그대로 |
| 기간 없음 | 357 (지난주) | 7.73% · 62.5% | 그대로 |
5. 상태는 규칙으로: 숫자에 색을 매기기 (2교시 Lab 01 과제 1)
일반 설명
생활 속 예 · 병동 현황판의 빨강 · 노랑 자석. 현황판에 환자마다 색 자석을 붙입니다. 빨강은 "지금 가서 봐야 함", 노랑은 "오늘 안에 봐야 함". 색은 간호사의 기분이 아니라 기준표로 붙입니다 — "체온 38.5도 이상이면 빨강". 그래야 누가 붙여도 같은 색입니다.
상태(health)는 숫자에 정해진 기준을 대어 영역마다 색을 매긴 것입니다. 업계에서는 RAG 상태(Red · Amber · Green), 헬스 체크(health check), SLO 판정(77일차)이라고 부릅니다. 사람이 숫자 여섯 개를 보고 매번 "괜찮은가"를 따지지 않아도, 색만 보면 무엇부터 볼지 알 수 있습니다.
| 색 | 뜻 | 기준을 정하는 법 (예) |
|---|---|---|
| 🔴 빨강 | 지금 가서 봐야 함 | 약속(SLO)을 어김, 사람이 처리해야 할 일이 남음 |
| 🟡 노랑 | 오늘 안에 봐야 함 | 약속에 가까워짐, 지켜볼 일이 생김 |
| 🟢 초록 | 괜찮음 | 위 기준에 하나도 걸리지 않음 |
기준은 숫자의 뜻에서 나옵니다: 오류율은 팀이 정한 SLO, 비용은 예산의 몇 %, 쌓인 일은 "사람이 볼 일이 남았나". 그리고 기준표를 프로그램이 적용해야 누가 봐도 같은 색이 나옵니다. LLM에게 "괜찮은지 판단해 줘"라고 하면 같은 숫자에 날마다 다른 색이 나올 수 있습니다.
색은 숫자를 바꾸지 않습니다. 같은 숫자에 기준을 댄 것입니다. 그리고 비교할 수 없으면(앞 절의 null) 빨강이라 하지 않고 노랑으로 둡니다 — "모르니 지켜보자".
오늘 실습에서
지난주 사실의 상태 (Lab 01 과제 1, 5/5):
| 🔴 red | 🟡 yellow | 전체 |
|---|---|---|
| runs (0.0588) · dlq (parked 2) · release (62.5% > 2 × 7.73%) | alerts · quality (격리 1) · cost (0.9201) | 🔴 |
- 첫 주: 오류 0이지만 답 못 함 5.5% → runs 🟡, 카나리 비율
null→ release 🟡 (비교 불가). 예산을 $1로 올리면 비용 🟢, parked 둘을 처리하면 DLQ 🟡.
6. 출처가 멈추면: 부분 실패를 견디기 (2교시 Lab 01 과제 2)
일반 설명
생활 속 예 · 검사실 전화가 안 될 때. 아침에 검사실 전화가 먹통이라 혈액 검사 결과를 못 받았습니다. 그렇다고 인수인계 전체를 미루지 않습니다. 체온 · 수액 · 투약은 그대로 넘기고, "검사 결과: 받지 못함"이라고 적습니다. "검사 결과 정상"이라고 적으면 안 됩니다.
출처 하나의 실패가 전체를 멈추게 두지 않습니다. 정보를 여섯 곳에서 모으면, 언젠가는 그중 한 곳이 응답하지 않는 날이 옵니다. 분산 시스템에서는 이것을 부분 실패(partial failure)라고 부르고, 일부가 멈춰도 나머지 기능은 계속 주는 설계를 우아한 저하(graceful degradation)라고 부릅니다. 원칙은 셋입니다.
| 원칙 | 하는 일 | 하지 않으면 |
|---|---|---|
| 나머지는 그대로 | 출처마다 실패를 따로 받아, 하나가 실패해도 다음 단계로 넘어감 | 한 곳 때문에 전체가 오류로 끝나 숫자가 하나도 없음 |
| 모르는 것은 모른다고 | 그 영역의 값은 "값 없음", 상태는 "모름", 어느 출처가 멈췄는지 적음 | 0으로 적어 초록으로 보임 |
| 전체는 좋게 말하지 않음 | 빨강이 없어도 "모름"이 하나라도 있으면 적어도 노랑 | 실제로는 위험한데 "모두 초록" |
이 셋을 지키면 대시보드를 보는 사람은 "무엇은 괜찮고, 무엇은 지금 확인할 수 없는지"를 정확히 압니다.
오늘 실습에서
테스트가 사용량 출처를 멈추고(fault usage error) 부르면 (Lab 01 과제 2):
| 고치기 전 | 고친 뒤 | |
|---|---|---|
| 응답 | 500 — 다섯 영역의 사실도 없음 | 200 · cost: null · sources_down: ["cost"] |
| 상태 | — | health.cost: "unknown", 빨강 셋 그대로 · 전체 🔴 |
| 출처가 돌아오면 | — | [] · 비용 🟡 0.9201 |
- 비용을 0으로 적었다면 🟢(예산의 0%)였을 것입니다. 실제로는 92%를 썼습니다.
7. 요청문(프롬프트)으로 에이전트에게 맡기기
사실 요청문은 "운영 대시보드 만들어 줘"가 아니라 정의를 적습니다 (AGENTS.md 1절: 에이전트는 먼저 "어느 출처의 무엇을 어떻게 세는지"를 표로 보여 줌).
| 넣을 것 | 예 |
|---|---|
| 파일 · 웹훅 · 이름 | "my-work/ops-facts.json, 웹훅 my-ops-facts, 이름 79 Ops facts (my)" |
| 기간 | "from · to를 /logs/query에, 비면 2026-10-26 ~ 2026-10-30, 기간은 실행 기록에만" |
| 정의 | "AGENTS.md 3절 사실 표 그대로, 실행은 77일차 정의, 비율은 0~1 소수 4자리" |
0과 null |
"0건이면 비율 · p95는 0, 실패 1위 · 다시 묻는 비율은 null" |
| 하지 않을 것 | "LLM은 쓰지 않는다, 상태를 바꾸는 요청을 보내지 않는다" |
| 기대 결과 | "cases/lab01.json, 앞의 테스트도 그대로" |
8. 자주 하는 실수
| 실수 | 결과 | 바로잡기 |
|---|---|---|
| "대시보드 만들어 줘"만 씀 | 에이전트가 고른 칸만 (기준처럼) | 영역 여섯과 정의를 요청문에 |
| 기간을 데이터 API에 안 넘김 | 무엇을 물어도 666건 | from · to를 그대로 |
| 오류율을 백분율로 | 3.15 > 0.01 → 언제나 빨강 | 비율 0~1 |
| 지금 숫자에도 기간을 댐 | 빈 주에 알림 0 | 기간은 실행 기록에만 |
null을 0으로 |
모르는데 🟢 | null 그대로, 상태는 비교 불가 |
| 색을 LLM에게 정하게 | 같은 사실에 날마다 다른 색 | 기준표를 Code로 |
| 출처 하나의 오류를 그대로 둠 | 사실 전체가 500 | neverError + 응답 모양으로 판단 |
| 사실을 만들며 상태를 바꿈 | 볼 때마다 아침이 달라짐 | 읽는 요청만 |
확인 질문
1. 기준 대시보드는 숫자를 하나도 "틀리게" 계산하지 않았는데도 위험하다고 했습니다. 왜인가요?
계산이 맞아도 칸이 없으면 그 영역은 "괜찮다"처럼 보입니다. 기준에는 parked · 품질 · 릴리스 칸이 없어, 오늘 가장 급한 parked 2건과 카나리 1.2.0을 모릅니다. 대시보드를 만들 때 먼저 정하는 것은 계산이 아니라 무엇을 물어야 하는가(영역)입니다. (실행 666건은 기간을 무시한 것이라 지난주를 물은 사람에게는 틀린 답이기도 합니다.)
2. 오늘 사실의 실행 숫자(357 · 0.0588 · 2598)가 77일차 숫자와 같다는 것이 왜 중요한가요?
정의를 다시 만들지 않았다는 증거입니다. 오늘 오류율을 새로 정의했다면 77일차 보고서와 오늘 도우미가 같은 주에 다른 오류율을 말했을 것입니다. 사실 한 곳에 정의를 두면 질문 답변 · 브리핑 · 터미널 도구가 모두 같은 숫자를 말합니다 (시맨틱 레이어).
3. 빈 주에 오류율은 0인데 실패 1위는 `null`입니다. 둘 다 "없다"인데 왜 다르게 두나요?
오류율은 "실행 0건 중 오류 0건"이라 0이라고 말할 수 있습니다 (정의로 정함). 실패 1위는 셀 것이 없어 말할 수 없습니다. null로 두면 상태 판정이 "비교 불가 → 노랑"으로 갈 수 있고, 0이나 빈 문자열로 두면 "실패 없음 → 초록"으로 읽힙니다.
4. 카나리의 다시 묻는 비율이 `null`이면 릴리스를 왜 빨강이 아니라 노랑으로 두나요?
빨강은 "카나리가 두 배 넘게 나쁘다"는 증거가 있을 때입니다. 비율이 없으면 증거도 없습니다. 그렇다고 초록도 아닙니다 — 카나리는 켜져 있고 아직 모릅니다. "켜져 있으니 지켜보자"가 노랑입니다.
5. 사용량 출처가 멈췄을 때 비용을 0으로 두면 무엇이 문제인가요? 전체 상태는 어떻게 되어야 하나요?
비용 0 → 예산의 0% → 🟢로 보입니다. 실제로는 92%를 썼습니다. 모르는 것을 좋게 말하는 대시보드가 가장 위험합니다. 비용은 null · unknown으로 두고 sources_down에 적습니다. 전체는 빨강이 있으면 red, 없더라도 unknown이 있으면 적어도 yellow — "모두 초록"이라고 말하지 않습니다.