Step 284. CTF 복기 블록 A + 팀 회의: 약점 분석 — 감이 아니라 데이터로 팀의 지도를 그린다
Level 3 — CTF 대회 사이클 | 난이도 ★★☆☆☆ | 예상 소요 시간 2일 (복기 0.5일 + 데이터 정리·팀 회의 1일)
전제: Step 279~283의 대회 3회 출전과 각 복기 블록 완료. 특히 Step 280의 복기 블록 A(틀린 문제 끝까지 파기) 절차.
- 준비물: 대회 #1~#3의 문제 목록과 팀 풀이 기록(또는 스코어보드 캡처), 팀 회의 도구(화상 회의든 채팅이든 무관), 아래에서 만들 파이썬 분석 스크립트. 스크립트 실행 화면은 실측, 대회 결과 데이터는 가상의 예시 데이터입니다.
- ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다. 오늘 다루는 스코어보드와 풀이 기록은 대회 운영진이 공개한 정보이므로 정당하게 수집한 데이터만 사용합니다.
- 이 챕터는 정리 챕터입니다 — 새 공격 기법은 없습니다. 대신 세 번의 대회에서 쌓인 기록을 "팀의 지도"로 바꾸는 방법을 배웁니다.
세 번의 대회를 치르고 나면 팀마다 비슷한 대화가 나옵니다. "우리 Web은 좀 하는 것 같은데." "Pwn은 솔직히 답이 없지 않아?" — 전부 감(感)입니다. 감으로 정한 훈련 방향은 한 달 뒤에도 감으로밖에 평가할 수 없습니다.
오늘은 그 대화를 숫자로 바꿉니다. 대회 #1~#3의 결과를 분야별 표로 정리하고, "우리가 못 푸는 분야"가 "모두가 못 푸는 분야"인지 "우리만 못 푸는 분야"인지 구분한 뒤, 60분짜리 팀 회의로 다음 대회의 훈련 방향을 확정합니다. 복기가 개인의 실력을 고치는 장치라면, 오늘의 회의는 팀의 실력을 고치는 장치입니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
- 대회 3회분의 결과를 분야별 시도/성공/소요 시간 표로 정리한다
- "우리가 약한 분야"와 "그 대회가 어렵게 나온 분야"를 전체 해결률로 구분한다
- 약점을 세 종류(실력 부족·담당 부재·시간 배분)로 분류해 원인별 처방을 정한다
- 안건과 시간 제한이 있는 팀 회의를 운영하고 회의록을 남긴다
- 분석 결과를 "다음 대회까지의 행동 계획(담당·기한)"으로 변환한다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | 파이썬 3 (집계 스크립트), CSV (대회 결과 정리), 마크다운 (회의록) |
| 오늘의 명령 | python ctf_stats.py results.csv — 직접 만드는 분석 도구 |
| 필요한 개념 | 득점 커버리지, 전체 해결률, 약점의 3분류, 안건·타임박스 회의 |
| 오늘의 산출물 | 분야별 약점 분석 표 + 팀 회의록 (결정 사항·담당·기한 포함) |
2-1. 왜 데이터인가 — 감으로는 팀을 못 고친다
개인 복기는 감으로 해도 어느 정도 됩니다. "그 문제는 내가 힙을 몰라서 못 풀었다" — 기억이 비교적 정확하니까요. 하지만 팀 단위로 가면 이야기가 달라집니다. 사람마다 기억하는 대회가 다르고, 자기 분야의 어려움만 과장되게 기억됩니다.
데이터가 필요한 진짜 이유는 회의의 언어 때문입니다. "Pwn이 약점 같아"라는 발언에는 "아니야, 그 대회 Pwn이 이상하게 어려웠어"라는 반박이 가능하고, 이 논쟁은 끝나지 않습니다. "Pwn 5문제 출제에 우리 시도 0, 전체 해결률은 25%"라는 표가 있으면 논쟁이 사라지고 처방 논의가 시작됩니다.
2-2. 약점의 3분류 — 같은 0점이라도 원인이 다르다
분석 표를 읽을 때 0점은 전부 같은 0점이 아닙니다. 원인에 따라 처방이 완전히 다릅니다.
| 분류 | 데이터상 특징 | 처방 |
|---|---|---|
| 실력 부족 | 시도는 하는데 성공률이 낮음, 전체 해결률은 높음 | 해당 유형 집중 학습 (Step 288의 특훈) |
| 담당 부재 | 시도 자체가 0 — 아무도 그 문제를 열지 않음 | 담당자 지정 또는 외부 영입, 입문 루트 배정 |
| 시간 배분 | 시도했으나 소요 시간 부족으로 포기 | 대회 운영 규칙 수정 (스왑 기준, 시간 상한) |
이 구분이 중요한 이유: 실력 문제에 인원 처방을 내리거나, 인원 문제에 학습 처방을 내리면 다음 대회에서 똑같이 무너집니다. 표를 보고 "왜"를 묻는 것이 회의의 핵심 안건입니다.
2-3. 전체 해결률 — "그 대회가 어려웠던 것"을 걸러내는 필터
대부분의 CTF는 대회 종료 후 문제별 해결 팀 수를 공개합니다. 해결 팀 수 ÷ 참가 팀 수가 전체 해결률입니다. 이 숫자가 필요한 이유는 단 하나 — 자기 기준의 착시를 없애기 위해서입니다.
전체 해결률 5%짜리 문제를 못 푼 것은 약점이 아니라 정상입니다. 전체 해결률 60%짜리를 세 대회 연속 놓친 것이 진짜 약점입니다. 회의에서 "우리 Web이 약하다"는 주장이 나오면 이 필터를 먼저 통과시키세요 — 절반은 그냥 어려운 대회였다는 사실로 정리됩니다.
2-4. 팀 회의 운영법 — 안건 없는 회의는 수다다
학습 팀의 회의가 흐지부지되는 이유는 대부분 운영 실패입니다. 안건이 없어서 잡담이 되거나, 시간 상한이 없어서 한 주제가 회의를 삼킵니다. 60분 회의의 표준 운영은 이렇습니다.
| 시간 | 안건 | 산출물 |
|---|---|---|
| 0~5분 | 목적 확인 — "오늘 결정할 것" 한 문장 | 회의 목표 문장 |
| 5~20분 | 데이터 리뷰 — 분야별 표를 같이 읽기 | 사실에 대한 합의 |
| 20~40분 | 원인 분석 — 약점별 3분류 판정 | 약점별 원인 태그 |
| 40~55분 | 처방 결정 — 담당자·분량·기한 | 행동 계획 표 |
| 55~60분 | 회의록 낭독 — 결정 사항 확인 | 회의록 확정 |
규칙은 두 개입니다. 시간이 되면 다음 안건으로 넘어간다(미해결 안건은 "보류"로 기록하고 넘어감), 모든 결정에는 담당과 기한을 붙인다. "다 같이 열심히"는 결정이 아니라 결정의 회피입니다 — 회의록에 담당자 이름이 없는 항목은 실행되지 않습니다.
3. 따라 하기
3-1. 먼저 복기 블록 A를 끝낸다
팀 회의는 개인 복기가 끝난 뒤에 열어야 합니다. Step 280에서 정한 복기 블록 A의 절차 — 이번 대회(CTF #3)에서 못 푼 문제 중 3개를 골라 끝까지 파는 훈련 — 을 각자 완료하고 회의에 옵니다.
복기 없이 회의부터 열면 "왜 못 풀었는가"의 답이 전부 추측이 됩니다. 각자가 복기에서 발견한 실패 원인을 한 줄로 가져오는 것이 회의의 입력입니다.
회의 참석 전 개인 준비물:
- 못 푼 문제 3개의 복기 노트 (Step 280 절차)
- 각 문제의 실패 원인 한 줄: "지식 부족 / 시간 부족 / 문제 미시도" 중 택1 + 구체 사유
3-2. 대회 결과를 CSV로 정리한다
대회 #1~#3의 문제 목록을 표로 모읍니다. 문제마다 여덟 칸 — 대회, 분야, 난이도, 문제명, 우리 팀의 시도 여부(0/1), 성공 여부(0/1), 소요 시간(분, 성공한 경우), 전체 해결률(%) — 을 채웁니다. 스코어보드가 남아 있다면 캡처를 보고 옮기고, 없다면 기억을 합쳐서 복원합니다.
예시 데이터 (아래 파일은 이 챕터의 설명용으로 만든 가상 데이터입니다):
대회,분야,난이도,문제명,시도,성공,소요분,전체해결률
CTF#1,Web,Easy,login-bypass,1,1,25,68
CTF#1,Web,Medium,ssti-note,1,0,90,22
CTF#1,Pwn,Easy,bof-basic,0,0,0,41
CTF#1,Crypto,Easy,rsa-small,1,1,40,55
CTF#2,Web,Easy,cookie-admin,1,1,20,71
CTF#2,Pwn,Easy,ret2win,0,0,0,38
CTF#3,Web,Easy,jwt-none,1,1,30,66
CTF#3,Crypto,Easy,base-layers,1,1,15,78
미시도 문제는 시도·성공·소요분을 전부 0으로 둡니다. 소요분을 기록해 두지 않았다면 이번엔 비워도 되지만 — 다음 대회부터는 상태표에 소요 시간 칸을 추가하세요. 평균 소요 시간은 팀의 속도를 재는 유일한 자료입니다.
3-3. 집계 스크립트를 만들고 실행한다
표를 눈으로 세어도 되지만, 문제가 20개를 넘어가면 손계산은 틀립니다. 아래 스크립트를 ctf_stats.py로 저장하세요 — 이 챕터의 코드와 출력은 실제 실행해 확인한 실측입니다.
# ctf_stats.py — 대회 결과 CSV를 분야별 약점 분석 표로 변환
# 사용법: python ctf_stats.py results.csv
import csv
import sys
from collections import defaultdict
def load(path):
rows = []
with open(path, encoding="utf-8") as f:
for r in csv.DictReader(f):
rows.append({
"대회": r["대회"], "분야": r["분야"], "난이도": r["난이도"],
"시도": int(r["시도"]), "성공": int(r["성공"]),
"소요분": int(r["소요분"]), "전체해결률": float(r["전체해결률"]),
})
return rows
def main(path):
rows = load(path)
agg = defaultdict(lambda: {"출제": 0, "시도": 0, "성공": 0,
"소요합": 0, "전체합": 0.0})
for r in rows:
a = agg[r["분야"]]
a["출제"] += 1
a["시도"] += r["시도"]
a["성공"] += r["성공"]
if r["성공"]:
a["소요합"] += r["소요분"]
a["전체합"] += r["전체해결률"]
print("| 분야 | 출제 | 시도 | 성공 | 커버리지 | 시도 대비 성공 | 평균 소요 | 전체 해결률 |")
print("|------|------|------|------|----------|----------------|-----------|-------------|")
total_solve = 0
total_n = 0
stats = {}
for cat in sorted(agg):
a = agg[cat]
cov = a["성공"] / a["출제"] * 100
att = a["성공"] / a["시도"] * 100 if a["시도"] else 0.0
avg_t = a["소요합"] / a["성공"] if a["성공"] else 0.0
field = a["전체합"] / a["출제"]
stats[cat] = (cov, field)
total_solve += a["성공"]
total_n += a["출제"]
avg_t_s = f"{avg_t:.0f}분" if a["성공"] else "-"
print(f"| {cat} | {a['출제']} | {a['시도']} | {a['성공']} | "
f"{cov:.0f}% | {att:.0f}% | {avg_t_s} | {field:.0f}% |")
print(f"\n전체 득점 커버리지: {total_solve}/{total_n} "
f"({total_solve / total_n * 100:.0f}%)")
print("\n[약점 진단]")
for cat, (cov, field) in sorted(stats.items(), key=lambda x: x[1][0]):
if cov == 0 and field >= 30:
verdict = "⚠ 실력 약점 — 다른 팀은 푸는데 우리만 0점"
elif cov == 0:
verdict = "△ 미착수 — 시도 자체가 없음, 담당 부재 의심"
elif cov + 20 < field:
verdict = "⚠ 상대적 열위 — 전체 해결률보다 크게 낮음"
else:
verdict = "○ 정상 범위"
print(f"- {cat}: 우리 {cov:.0f}% vs 전체 {field:.0f}% → {verdict}")
if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv) > 1 else "results.csv")
이 챕터의 예시 데이터(24문제)로 실행한 실측 결과입니다. 여러분의 데이터로 실행하면 수치는 달라집니다.
python ctf_stats.py results.csv
| 분야 | 출제 | 시도 | 성공 | 커버리지 | 시도 대비 성공 | 평균 소요 | 전체 해결률 |
|------|------|------|------|----------|----------------|-----------|-------------|
| Crypto | 6 | 5 | 4 | 67% | 80% | 39분 | 42% |
| Forensics | 3 | 0 | 0 | 0% | 0% | - | 50% |
| Pwn | 5 | 0 | 0 | 0% | 0% | - | 25% |
| Reversing | 3 | 3 | 2 | 67% | 67% | 45분 | 42% |
| Web | 7 | 6 | 3 | 43% | 50% | 25분 | 37% |
전체 득점 커버리지: 9/24 (38%)
[약점 진단]
- Forensics: 우리 0% vs 전체 50% → ⚠ 실력 약점 — 다른 팀은 푸는데 우리만 0점
- Pwn: 우리 0% vs 전체 25% → △ 미착수 — 시도 자체가 없음, 담당 부재 의심
- Web: 우리 43% vs 전체 37% → ○ 정상 범위
- Crypto: 우리 67% vs 전체 42% → ○ 정상 범위
- Reversing: 우리 67% vs 전체 42% → ○ 정상 범위
읽는 법: 이 예시 팀의 이야기가 표 한 장으로 정리됐습니다. Forensics는 시도 0인데 전체 해결률이 50% — Easy 문제를 아예 안 열어본 것이니 담당 부재가 1차 원인입니다. Pwn도 미착수지만 전체 해결률이 낮아 "우리만의 문제"인지는 판단 유보. Web은 커버리지 43%로 전체 평균(37%) 위에 있으니 약점이 아닙니다. 감으로는 "Pwn이 최악" 같았지만 데이터는 "Forensics부터"라고 말합니다.
3-4. 60분 팀 회의를 연다
2-4의 시간표대로 진행합니다. 진행자 한 명을 정하고(돌아가며 맡으세요), 화면에 3-3의 표를 띄운 채 시작합니다. 안건별로 실제로 오간 대화의 예시입니다.
[5~20분 데이터 리뷰]
진행자: "Forensics 3문제, 시도 0. 맞나?" → 전원 확인. 사실 확정.
[20~40분 원인 분석]
"왜 안 열었나?" → "팀에 Forensics 해본 사람이 없어서 누구도 자청 안 함"
→ 분류: 담당 부재 (실력 문제 아님 — 해본 적이 없는 것)
[40~55분 처방 결정]
- Forensics: A가 담당, 다음 대회까지 Step 244~247 루트 학습, Easy 5문제 풀이
- Pwn: 당장 인원 불가 → B가 입문만(pwnable.kr bof~collision), 기대치는 "시도"
- Web Medium 실패 3건: 개인 복기 공유 → Step 288의 특훈 주제로 이관
마지막 5분에 회의록을 소리 내어 읽습니다. "듣는 순간 이의가 없으면 확정" — 이 절차가 회의를 결정의 장치로 만듭니다.
3-5. 회의록을 남긴다
회의록 양식은 네 칸이면 충분합니다.
# CTF #3 복기 팀 회의록 (날짜: ____)
### 1. 데이터 요약
- 전체 득점 커버리지: __/__ (__%)
- 약점 진단: Forensics(담당 부재), Pwn(미착수), Web Medium(실력)
### 2. 약점별 원인
| 분야 | 데이터 | 원인 분류 |
|------|--------|-----------|
| Forensics | 시도 0 / 전체 50% | 담당 부재 |
| Web Medium | 시도 4 성공 0 | 실력 부족 — SSTI·SSRF 유형 |
### 3. 결정 사항 (담당 · 기한)
| 할 일 | 담당 | 기한 |
|-------|------|------|
| Forensics 입문 + Easy 5문제 | A | CTF #4 전 |
| pwnable.kr 입문 3문제 | B | CTF #4 전 |
| Web 특훈 유형 선정 | C | 이번 주 |
### 4. 보류
- Pwn 정규 담당자 문제 — 다음 회의에서 재논의
왜 이 형식인가: 3번 표가 없는 회의록은 회의를 안 한 것과 같습니다. 4번 칸은 미해결 안건이 사라지는 것을 막습니다 — 보류도 기록이어야 다음 회의의 안건이 됩니다.
4. 미션과 연습문제
미션 — 우리 팀의 약점 분석 회의록을 완성하라
- CTF #1~#3의 결과를 3-2의 CSV 형식으로 정리합니다 — 전체 해결률 칸 포함.
ctf_stats.py를 실행해 분야별 표와 약점 진단을 뽑습니다.- 각자 Step 280 절차의 복기 블록 A를 완료하고 실패 원인 한 줄을 준비합니다.
- 2-4의 시간표로 60분 회의를 열고, 약점마다 3분류(실력/담당/시간) 판정을 내립니다.
- 3-5의 양식으로 회의록을 작성합니다 — 결정 사항 전부에 담당과 기한이 있어야 합니다.
- 다음 대회(CTF #4)는 이 회의록의 결정 사항을 검증하는 자리가 됩니다 — Step 285에서 이어집니다.
연습문제
문제 1. "우리 팀은 Web이 약하다"는 주장이 회의에 나왔을 때, 어떤 데이터 두 가지로 이 주장을 검증해야 하나요?
문제 2. 약점의 3분류 중 "담당 부재"와 "실력 부족"은 데이터상 어떤 차이로 구분되나요? 처방은 각각 무엇인가요?
문제 3. 팀 회의에서 "다 같이 Pwn을 열심히 하자"로 마무리하는 것이 왜 문제인가요?
문제 4. 회의록에 "보류" 칸을 따로 두는 이유는 무엇인가요?
5. 모범 답안과 완료 기준
미션 모범 답안
검증 기준으로 확인하세요.
- CSV의 완결성: 3개 대회 전 문제가 행으로 있고, 미시도 행에도 전체 해결률이 채워져 있는가 — 해결률이 빠진 행은 진단에서 왜곡을 만듭니다.
- 표의 재현: 스크립트 출력의 수치가 CSV와 일치하는가 — 손으로 한두 행 검산해 보세요.
- 원인 판정의 근거: 각 약점의 3분류 판정에 "데이터 + 복기 노트" 둘 다가 근거로 붙어 있는가 — 감으로 붙인 태그는 회의의 의미를 지웁니다.
- 회의록의 실행 가능성: 결정 사항의 모든 행에 담당자와 기한이 있는가. "다 같이"가 담당인 행이 하나라도 있으면 미완성입니다.
- 검증 계획: 결정 사항이 다음 대회에서 무엇으로 검증되는지(예: "Forensics 시도 ≥ 1") 회의록이나 별도 메모에 적혀 있는가.
연습문제 해답
문제 1 해답. 첫째, 우리 팀의 Web 득점 커버리지(출제 대비 성공)와 둘째, 같은 문제들의 전체 해결률입니다. 커버리지가 낮아도 전체 해결률이 낮으면 그 대회 Web이 어려웠던 것이고, 전체 해결률은 높은데 우리만 낮으면 진짜 약점입니다. 하나만 보면 자기 기준의 착시에 걸립니다.
문제 2 해답. 시도 수로 구분됩니다. 시도 자체가 0이면 담당 부재(열람조차 안 한 것), 시도는 있는데 성공률이 낮으면 실력 부족입니다. 담당 부재의 처방은 담당자 지정과 입문 루트 배정이고, 실력 부족의 처방은 해당 유형의 집중 학습(Step 288의 특훈)입니다. 같은 0점이지만 원인이 다르므로 처방을 바꿔 쓰면 다음 대회에도 같은 결과가 나옵니다.
문제 3 해답. 담당이 "모두"인 결정은 담당이 없는 결정이기 때문입니다. 누가 무엇을 언제까지 하는지가 없으면 다음 회의에서 달성 여부를 물을 수 없고, 물을 수 없는 계획은 훈련이 아니라 바람입니다. "B가 pwnable.kr 입문 3문제를 CTF #4 전에"처럼 사람·분량·기한이 있어야 검증 가능한 결정입니다.
문제 4 해답. 시간 안에 결론이 안 난 안건이 증발하는 것을 막기 위해서입니다. 보류 칸이 없으면 미해결 안건은 "다음에 이야기하자"라는 말과 함께 사라지고, 다음 회의에서 같은 논의를 처음부터 다시 합니다. 기록된 보류는 다음 회의의 안건이 되어 논의가 이어집니다 — 회의의 연속성은 이 칸이 만듭니다.
완료 기준 체크리스트
- [ ] 대회 3회분의 결과를 CSV로 정리했다 (전체 해결률 포함)
- [ ]
ctf_stats.py로 분야별 표와 약점 진단을 출력했다 - [ ] 각자 복기 블록 A(틀린 문제 3개)를 완료하고 실패 원인 한 줄을 가져왔다
- [ ] 60분 회의를 시간표대로 진행했다 (진행자 지정 포함)
- [ ] 약점마다 3분류(실력/담당/시간) 판정을 내렸다
- [ ] 회의록 네 칸(데이터/원인/결정/보류)을 채웠다
- [ ] 모든 결정 사항에 담당자와 기한이 있다
- [ ] 다음 대회에서의 검증 기준을 정했다
6. 흔한 실수와 해결
벽 1. 스크립트를 실행하니 FileNotFoundError가 떠요
FileNotFoundError: [Errno 2] No such file or directory: 'results.csv'
원인: 스크립트를 실행한 폴더에 results.csv가 없습니다. CSV를 만든 폴더와 실행 폴더가 다른 경우가 대부분입니다.
해결: CSV가 있는 폴더로 이동해서 실행하거나, 파일 경로를 통째로 인자로 넘기세요 — python ctf_stats.py C:\ctf\results.csv. 참고로 이 메시지는 이 챕터 작성 시 실제로 재현해 확인한 것입니다.
벽 2. 한글이 깨져요 — CSV를 열었더니 글자가 이상해요
증상: 엑셀에서 저장한 CSV를 스크립트가 읽으면 UnicodeDecodeError가 나거나, 반대로 스크립트 결과를 엑셀에서 열면 한글이 깨집니다.
원인: 엑셀은 기본 저장 인코딩이 UTF-8이 아닌 경우가 많고(CP949), 이 스크립트는 encoding="utf-8"로 읽습니다.
해결: 메모장이나 VS Code로 CSV를 열어 "다른 이름으로 저장 → 인코딩 UTF-8"로 다시 저장하세요. 처음부터 텍스트 편집기로 CSV를 만드는 것이 가장 간단합니다.
벽 3. 회의가 60분을 넘겼는데 결정이 하나도 없어요
증상: 데이터를 보며 감상평만 주고받다가 시간이 갔습니다.
원인: 안건별 시간 상한이 없었거나, 진행자가 없었습니다.
해결: 다음 회의부터 진행자를 정하고, 진행자의 유일한 임무는 시계를 보는 것으로 하세요. 시간이 되면 "이 안건은 보류로 기록하고 넘어갑니다"라고 선언합니다. 결론이 안 나는 안건을 억지로 닫는 것보다, 보류로 기록하고 다음 안건으로 가는 것이 낫습니다 — 회의의 목적은 논의가 아니라 결정입니다.
벽 4. 전체 해결률 데이터를 못 구하겠어요
증상: 대회 플랫폼이 문제별 해결 팀 수를 공개하지 않았습니다.
원인: 소규모 대회는 통계를 안 주는 경우가 있습니다.
해결: 두 가지 대체재가 있습니다. 첫째, 대회 종료 직후 스코어보드의 상위 팀 득점 분포를 캡처해 두고 "몇 팀이나 이 문제 점수를 가졌나"를 직접 셉니다. 둘째, 공개 Write-up 수로 추정합니다 — 같은 문제의 Write-up이 많이 올라오는 문제는 대중적으로 풀린 문제입니다. 정확도는 떨어지지만 "우리만 못 푼 것"과 "원래 어려운 것"을 가리는 데는 충분합니다.
벽 5. 약점 분석 결과를 두고 팀원 사이가 어색해졌어요
증상: "Pwn 담당이 안 풀었다"는 표가 특정인에 대한 비난처럼 읽힙니다.
원인: 표는 사실이지만, 회의에서 그 사실을 사람 평가로 읽은 것입니다.
해결: 회의 시작 전에 규칙 하나를 합의하세요 — "표는 문제를 가리키지 사람을 가리키지 않는다". 그리고 표의 행은 "분야별"로만 만들고 개인별로는 만들지 않습니다. 개인의 성장은 개인 복기(Step 280)의 영역이고, 팀 회의의 영역은 구조(담당 배치·시간 규칙)입니다. 이 경계를 지키는 회의만이 데이터를 두려워하지 않는 팀을 만듭니다.
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| 득점 커버리지 | 출제된 문제 중 우리가 가져온 비율 — 팀의 화력 지표 |
| 전체 해결률 | 모든 팀 중 그 문제를 푼 비율 — 자기 기준 착시를 없애는 필터 |
| 약점의 3분류 | 실력 부족 / 담당 부재 / 시간 배분 — 원인이 다르면 처방이 다르다 |
| 안건·타임박스 회의 | 시간 상한이 있는 안건 진행 — 회의를 수다가 아니라 결정의 장치로 |
| 회의록 4칸 | 데이터 요약 / 원인 / 결정(담당·기한) / 보류 |
| 검증 가능한 결정 | 사람·분량·기한이 있어 다음 회의에서 달성 여부를 물을 수 있는 결정 |
오늘의 도구·서식
| 도구·서식 | 하는 일 |
|---|---|
| 결과 정리 CSV (8칸) | 대회 3회분의 기억을 집계 가능한 데이터로 |
ctf_stats.py |
CSV → 분야별 표 + 약점 진단 자동 출력 |
| 60분 회의 시간표 | 5개 안건에 시간을 배정해 결정을 강제 |
| 회의록 양식 | 결정 사항이 사라지지 않게 고정하는 틀 |
명령어보다 중요한 감각
복기가 개인을 고치는 장치라면, 오늘의 회의는 팀이라는 기계를 고치는 장치입니다. 개인의 실력은 복기로 오르지만, "아무도 Forensics를 안 여는 팀"이라는 구조적 결함은 아무리 개인이 노력해도 그대로입니다 — 구조는 회의에서만 고칠 수 있습니다.
그리고 이 장치의 연료는 데이터입니다. 감으로 여는 회의는 기분 좋게 끝나지만 다음 대회 결과가 같고, 데이터로 여는 회의는 불편하게 끝나지만 다음 대회 결과가 다릅니다. 표가 말해 주는 약점 — 예시 팀의 Forensics처럼 — 을 받아들이는 것이 성장의 시작입니다. 다음 대회는 오늘 회의록의 시험장입니다.
전부 체크되면 Step 284 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.