Step 281. ★ CTF #2: 이번엔 팀으로 — 분업의 효율과 소통의 비용을 동시에 배우는 날
Level 3 — CTF 실전과 공격 스킬 심화 | 난이도 ★★★☆☆ | 예상 소요 시간 1개 주말 (대회 24~48시간 + 팀 회고 1시간)
전제: Step 279의 솔로 대회 완주, Step 280의 복기 루틴, Step 190의 팀 규칙 초안.
- 준비물: 팀 2~4명(Step 190에서 만든 팀 또는 커뮤니티 합류), 디스코드 서버(음성+문자 채널), 공유 스프레드시트, 개인별
ctf_log.py, 그리고 오늘 만드는 팀 상태표 병합 스크립트. - ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다. CTFtime에 등록된 CTF 대회는 주최 측이 참가하라고 연 합법 플랫폼입니다 — 대회가 제공하는 문제 서버 외에는 어떤 대상도 공격하지 않으며, 대회 중 타 팀과의 풀이 공유는 규정 위반임을 기억합니다.
- 주의: 대회 플랫폼과 디스코드 화면은 전부 화면 예시입니다. 팀원 로그 병합 스크립트의 출력만 로컬 실측입니다.
CTF는 원래 팀 스포츠입니다. 혼자서는 물리적으로 불가능한 분야 커버리지를 팀이 만들어 줍니다. 그런데 두 번째 대회에서 여러분을 기다리는 새로운 발견이 있습니다 — 팀은 분업의 효율만큼 소통의 비용을 청구한다는 사실. 오늘의 목표는 우승이 아니라, 이 두 가지를 같은 대회에서 동시에 체험하는 것입니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
- 킥오프 미팅 30분으로 분야 배정과 단서 공유 규칙을 합의한다
- 공유 상태표(문제 목록/담당/상태)를 만들고 1시간마다 갱신한다
- "이 단서 쓸 사람?" 커뮤니케이션으로 분야 간 협업을 만든다
- 2시간 스왑 규칙으로 막힌 문제의 담당을 교체한다
- 팀원 개별 로그를 합쳐 팀 상태표와 합산 성적을 산출한다
- 팀 회고로 분업의 잘된 점과 소통 미스를 구분해 기록한다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | 디스코드(음성/문자), 공유 스프레드시트, 개인 로그 CSV, 파이썬(병합 스크립트) |
| 오늘의 화면·도구 | 팀 킥오프 안건, 상태표 템플릿, merge_board.py(로그 병합 + 중복 착수 경고) |
| 필요한 개념 | 분야 배정, 단서 공유 규칙, 1시간 갱신, 2시간 스왑, 중복 착수, 팀 회고 |
| 오늘의 산출물 | 팀 상태표 + team_log.csv(팀 합산 로그) + 협업 회고 메모 |
2-1. 솔로와 팀의 차이 — 같은 대회, 다른 게임
솔로 대회의 최적 전략은 "내 시간의 배분"이었습니다. 팀 대회는 여기에 두 개의 축이 더해집니다.
| 축 | 솔로 | 팀 |
|---|---|---|
| 커버리지 | 내가 아는 분야만 | 팀원 전원의 분야 합집합 |
| 막힘의 처리 | 2시간 규칙으로 drop | 다른 눈으로 스왑 가능 |
| 지식의 흐름 | 내 플레이북 안에서만 | "이 단서 쓸 사람?"으로 실시간 이동 |
| 비용 | 없음 | 소통·조율·중복 착수의 비용 |
마지막 행이 오늘의 핵심 긴장입니다. 팀의 이득(커버리지, 스왑, 지식 공유)은 전부 소통이 작동할 때만 실현됩니다. 소통이 무너진 팀은 "점심을 같이 먹는 솔로 3명"일 뿐이고, 그런 팀은 솔로 3명의 합계보다 못합니다 — 중복 착수라는 새 손실이 생기기 때문입니다.
2-2. 사전 준비 — 채널, 상태표, 규칙의 삼종 세트
대회 전날까지 준비할 것은 세 가지입니다.
① 디스코드 채널 구조. 최소 구성은 이 정도면 충분합니다.
📢 announce — 대회 공지·중요 합의 사항 고정
🚩 flags — 플래그 인증 성공 보고 (문제명 + 누가)
💡 clues — "이 단서 쓸 사람?" 단서 던지기 전용
🔊 voice-lounge — 상시 접속 음성 채널
채널을 나누는 이유는 대회 중반의 채팅 폭주 때문입니다. 모든 것이 한 채널에 섞이면, 플래그 인증 소식이 잡담에 묻히고 결정적인 단서가 스크롤 너머로 사라집니다.
② 공유 상태표. 스프레드시트에 열은 다섯 개면 됩니다 — 문제명 | 분야 | 배점 | 담당 | 상태(미착수/진행/막힘/해결). 대회 시작과 동시에 전체 문제 목록을 옮겨 적는 것이 첫 작업입니다.
③ 규칙 합의. Step 190의 팀 규칙 초안을 실전용으로 다듬습니다. 최소 세 가지에 합의가 필요합니다 — 착수 즉시 상태표 기록, 단서 발견 즉시 💡 채널 투척, 1시간마다 상태표 갱신.
2-3. 킥오프 미팅 30분 — 대회 시작 전의 합의
대회 시작 30분 전, 음성 채널에 모입니다. 안건은 정해져 있습니다.
[킥오프 안건 — 30분]
5분: 문제 목록 전체 훑기 (다 함께 상태표에 옮기며)
10분: 분야 배정 — 각자 주력 분야 선언, 공백 분야 확인
5분: 단서 공유 규칙 합의 — "발견 즉시 던지기, 판단은 받는 사람이"
5분: 스왑 규칙 합의 — 한 문제 2시간 막히면 채널에 "스왑 구함" 선언
5분: 수면 교대 — 누가 언제 자는지 (48시간 대회라면 필수)
분야 배정의 원칙은 Step 190과 같습니다 — 겹치지 않게. 공백 분야가 나오면(예: Pwn 담당이 없음) 정직하게 선언합니다: "Pwn은 건드리지 않는다"가 아니라 "Pwn 쉬운 문제 하나는 맨 마지막 날 오전에 다 같이 본다"처럼 공백의 처리도 계획의 일부입니다.
2-4. 대회 중 운영 — 세 개의 리듬
대회가 시작되면 팀은 세 개의 시계로 돌아갑니다.
- 1시간 리듬 — 상태표 갱신. "지금 무엇을 보고 있는가"가 항상 표에 있어야 합니다. 이 리듬이 무너지면 팀은 솔로들의 합으로 퇴화합니다.
- 2시간 리듬 — 스왑. 솔로의 2시간 규칙이 drop이었다면, 팀에서는 스왑이 먼저입니다. 내가 2시간 본 문제는 다른 눈에는 10분짜리일 수 있습니다 — 배경 지식이 다르기 때문입니다. 스왑할 때의 예의: 지금까지의 시도를 세 줄로 정리해 넘깁니다.
- 식사·수면 리듬 — 2-3에서 합의한 교대표대로. 팀원이 사라질 시간을 미리 알면 남은 사람이 담당 공백을 메울 수 있습니다.
2-5. "이 단서 쓸 사람?" — 팀 고유의 점수 발생 장치
솔로에게는 없는 점수 발생 장치가 있습니다. Web 문제의 응답에서 이상한 헤더를 발견했는데 내 문제와 무관해 보일 때 — 솔로는 그냥 흘립니다. 팀은 💡 채널에 던집니다.
💡 clues — 화면 예시
minho: jwt-forgery 응답에 X-Debug: /backup/config.bak 헤더 보임. 내 문제랑은 무관한 듯. 쓸 사람?
alice: 그거 내 file-upload-rce의 업로드 경로 힌트일 수도. 받음.
이 한 줄의 대화가 점수가 되는 메커니즘: 한 문제의 부산물이 다른 문제의 열쇠인 경우가 대회마다 반드시 있습니다. 주최 측도 그렇게 설계합니다. 그래서 "판단은 받는 사람이 한다"는 규칙이 중요합니다 — 던지는 사람이 "이건 쓸모없겠지"라고 스스로 검열하는 순간 이 장치는 멈춥니다.
3. 따라 하기
3-1. 팀 소집과 사전 준비 (화면 예시)
Step 190의 팀(또는 커뮤니티에서 합류한 팀)에 대회 참가를 제안합니다. 대회는 2-1의 첫 대회와 비슷한 등급의 주말 대회로 고릅니다 — 팀 운영 자체가 새 변수인데 대회 난이도까지 올리면 변수가 둘이 됩니다.
준비는 2-2의 삼종 세트를 만드는 것으로 끝입니다. 상태표 템플릿을 미리 만들어 두고, 팀원 전원이 편집 권한을 갖는지 확인하세요 — 대회 시작 후 권한 요청을 기다리는 것만큼 어색한 시간 낭비가 없습니다.
3-2. 개인 로그에 이름표 달기
팀 대회에서도 개인 로그 습관(Step 279)은 그대로입니다. 다만 나중에 합칠 것을 생각해, 각자의 로그 파일명을 이름으로 저장합니다 — alice.csv, bob.csv, minho.csv처럼. 규칙은 하나뿐입니다: 이벤트 양식을 팀 전원이 똑같이 — ctf_log.py의 출력 형식 그대로 쓰면 자동으로 맞춰집니다.
3-3. 팀 로그 병합 스크립트 (실측)
대회 중 또는 종료 후, 팀원의 로그를 합쳐 팀 전체 상태표와 합산 성적을 뽑는 스크립트입니다. merge_board.py로 저장하세요.
# merge_board.py — 팀원 개별 로그를 합쳐 공유 상태표와 팀 합산 로그를 만든다
import csv, sys
from datetime import datetime
FMT = "%m-%d %H:%M"
rows = []
for path in sys.argv[1:]:
owner = path.split(".")[0] # 파일명 = 팀원 이름
with open(path, newline="", encoding="utf-8") as f:
for r in csv.DictReader(f):
r["담당"] = owner
rows.append(r)
rows.sort(key=lambda r: r["시각"]) # 파일 순서가 아니라 시간순으로 상태를 쌓는다
problems = {}
for r in rows:
p = problems.setdefault(r["문제"], {"분야": r["분야"], "배점": r["배점"],
"담당": set(), "상태": "미착수", "start": None, "end": None})
p["담당"].add(r["담당"])
t = datetime.strptime(r["시각"], FMT)
if r["이벤트"] == "start":
p["상태"] = "진행 중"
p["start"] = t if p["start"] is None else min(p["start"], t)
elif r["이벤트"] == "stuck":
p["상태"] = "막힘"
elif r["이벤트"] == "drop":
if p["상태"] != "해결":
p["상태"] = "포기"
elif r["이벤트"] == "solve":
p["상태"] = "해결"
p["end"] = t
print("문제 | 분야 | 상태 | 담당 | 경과")
print("--------------------|------------|--------|-----------------|-----")
solved_pts = 0
for name, p in problems.items():
elapsed = "-"
if p["start"] and p["end"]:
elapsed = f"{int((p['end'] - p['start']).total_seconds() // 60)}분"
owners = ",".join(sorted(p["담당"]))
flag = " ⚠ 중복 착수" if len(p["담당"]) > 1 else ""
if p["상태"] == "해결" and p["배점"]:
solved_pts += int(p["배점"])
print(f"{name:<20}| {p['분야']:<10} | {p['상태']:<5} | {owners:<15} | {elapsed}{flag}")
n_solved = sum(1 for p in problems.values() if p["상태"] == "해결")
print()
print(f"팀 합계: {len(problems)}문제 착수 / {n_solved}문제 해결 / {solved_pts}점")
with open("team_log.csv", "w", newline="", encoding="utf-8") as f:
fields = ["시각", "이벤트", "분야", "문제", "배점", "메모", "담당"]
w = csv.DictWriter(f, fieldnames=fields)
w.writeheader()
w.writerows(sorted(rows, key=lambda r: r["시각"]))
print("team_log.csv 저장 완료 (팀 합산 로그)")
핵심 동작 두 가지: ① 모든 로그를 시간순으로 정렬한 뒤 상태를 쌓습니다 — 파일을 읽은 순서대로 쌓으면, 뒤에 읽은 파일의 옛날 기록이 앞 파일의 최신 상태를 덮어버립니다. ② 한 문제에 담당이 둘 이상이면 ⚠ 중복 착수 경고를 붙입니다 — 풀렸더라도 경고가 남습니다. 중복으로 태운 시간은 해결 여부와 무관하게 손실이기 때문입니다.
3-4. 병합 실행 — 상태표와 중복 착수 경고 (실측)
예시 팀(alice, bob, minho)의 실제 기록으로 실행해 보았습니다. 세 사람의 로그를 넣은 결과, 실측 출력입니다.
$ python merge_board.py alice.csv bob.csv minho.csv
문제 | 분야 | 상태 | 담당 | 경과
--------------------|------------|--------|-----------------|-----
jwt-forgery | Web | 해결 | alice | 47분
bof-ret2win | Pwn | 해결 | bob | 142분
substitution-101 | Crypto | 해결 | minho | 34분
file-upload-rce | Web | 해결 | alice,minho | 670분 ⚠ 중복 착수
packed-binary | Rev | 막힘 | bob | -
usb-pcap | Forensics | 해결 | minho | 50분
disk-image-1 | Forensics | 해결 | alice | 45분
rsa-small-e | Crypto | 해결 | bob | 47분
팀 합계: 8문제 착수 / 7문제 해결 / 1300점
team_log.csv 저장 완료 (팀 합산 로그)
읽는 법: ① 8문제 착수 7문제 해결 — 솔로 대회(6착수/3해결)와 비교해 커버리지의 위력이 보입니다. ② 그런데 file-upload-rce에 ⚠ 중복 착수 경고가 붙었습니다 — alice가 22:10에 착수한 것을 minho가 모르고 22:30에 착수해 40분을 태운 뒤 진행판을 보고 넘긴 사건입니다. ③ packed-binary는 bob이 막힌 채 끝났습니다 — 스왑이 안 일어난 문제입니다. 이 두 줄이 오늘 팀 회고의 안건입니다.
이 스크립트도 실수를 거쳤습니다. 첫 판은 파일 처리 순서대로 상태를 쌓아서, 나중에 읽은 파일의 옛날 "막힘" 기록이 앞 파일의 "해결"을 덮어버렸습니다(file-upload-rce가 해결인데도 막힘으로 표시). 로그를 시간순으로 정렬한 뒤에야 올바른 상태표가 나왔습니다 — "상태는 시간순으로만 쌓인다"는 원칙을 코드로 확인한 셈입니다.
3-5. 종료 후 팀 회고 — 1시간의 안건
대회 종료 후 24시간 안에 음성으로 모입니다. 개인 회고(Step 279)와 다른, 팀 회고만의 안건은 세 가지입니다.
[팀 회고 안건 — 60분]
1. 잘된 분업 (15분): 어떤 배정이 점수를 만들었나
- 예: Forensics 둘을 alice/minho가 나눠 먹어 350점 확보
2. 소통 미스 (20분): 상태표/채널이 막았어야 할 사고
- 예: file-upload-rce 중복 착수 40분 — 착수 즉시 기록이 늦었음
- 예: packed-binary — bob이 "스왑 구함"을 선언하지 않음
3. 다음 개선점 (25분): 규칙 문장으로 만들어 합의
- "착수 기록은 문제를 연 그 자리에서" — 로그를 나중에 몰아 쓰지 않는다
- "스왑 구함은 자존심이 아니라 의무" — 2시간 지나면 무조건 선언
회고의 산출물은 반드시 규칙 문장이어야 합니다. "소통을 잘하자"는 다짐은 다음 대회에서 사라지지만, "2시간 지나면 스왑 구함 선언이 의무"는 지킬 수 있는 문장입니다. 이 개선점들이 Step 283에서 목표와 함께 다시 등장합니다.
4. 미션과 연습문제
미션 — 팀 대회 완주와 협업 회고
- 팀(2~4명)으로 주말 대회에 등록하고, 2-2의 삼종 세트(채널·상태표·규칙)를 대회 전에 완성합니다.
- 킥오프 미팅 30분을 진행하고, 분야 배정과 스왑 규칙 합의를
announce채널에 고정합니다. - 대회 중 1시간 리듬으로 상태표를 갱신하고, 💡 채널에 단서를 최소 3개 던집니다.
- 종료 후 팀원 로그를
merge_board.py로 합쳐 팀 상태표와 합산 성적을 산출합니다. - 3-5의 안건으로 팀 회고를 열고, 개선 규칙 문장 3개를 확정해 저장합니다.
연습문제
문제 1. 소통이 무너진 팀이 "솔로 3명의 합계보다 못한" 이유를 중복 착수의 개념으로 설명해 보세요.
문제 2. 솔로 대회의 2시간 규칙(drop)과 팀 대회의 2시간 스왑이 다른 결론을 내리는 이유를 설명해 보세요.
문제 3. "판단은 받는 사람이 한다"는 단서 공유 규칙이 없으면 어떤 일이 생기나요?
문제 4. 3-4의 실측 상태표에서 팀의 다음 대회 개선점 두 가지를 데이터 근거와 함께 도출해 보세요.
5. 모범 답안과 완료 기준
미션 모범 답안
검증하는 법: ① 킥오프 합의(분야 배정·스왑 규칙)가 채널에 문장으로 남아 있는가 — 구두 합의는 대회 중반에 증발합니다. ② 상태표에 갱신 흔적이 대회 전 시간대에 걸쳐 있는가(시작 때만 쓰고 방치된 표는 장식입니다). ③ 💡 채널에 단서가 실제로 던져졌고, 받은 사람이 "받음"으로 응답했는가. ④ 병합 결과에 ⚠ 중복 착수가 있다면 회고 안건으로 올라갔는가 — 경고를 보고도 회고에서 다루지 않으면 측정의 의미가 없습니다. ⑤ 개선 규칙이 "잘하자"형이 아니라 "언제 무엇을 한다"형 문장 3개인가.
연습문제 해답
문제 1 해답. 솔로 3명이 각자 풀면 같은 문제를 셋이 봐도 각자의 시간이고 결과도 독립적입니다. 그러나 팀으로 묶인 상태에서 중복 착수가 일어나면, 팀 전체 자원(3명 × 시간)의 일부가 같은 문제에 중복 투입되면서도 분업의 이득(커버리지)은 포기한 상태가 됩니다. 소통 비용만 내고 분업 이득을 못 챙기는 구조이므로, 합계 이하로 떨어집니다.
문제 2 해답. 솔로의 drop은 "내 배경 지식으로는 2시간 안에 못 푼다"는 판단입니다. 그런데 배경 지식은 사람마다 다릅니다 — 내게 2시간짜리 벽이 팀원에게는 익숙한 유형일 수 있습니다. 팀에는 다른 눈이 존재하므로, 막힘의 첫 처방은 포기가 아니라 관점의 교체입니다. 스왑마저 실패한 문제가 그때 비로소 팀의 drop이 됩니다.
문제 3 해답. 던지는 사람이 스스로 쓸모를 검열하게 됩니다. "이건 내 문제와 무관하니까"라는 판단은 자기 분야의 지식 안에서 내린 것이라, 다른 문제의 열쇠라는 가능성을 본질적으로 알 수 없습니다. 검열이 시작되면 💡 채널은 멈추고, 한 문제의 부산물이 다른 문제의 열쇠가 되는 사건들이 전부 사라집니다.
문제 4 해답. ① file-upload-rce의 ⚠ 중복 착수(40분 손실) → "착수 기록은 문제를 연 그 자리에" 규칙 필요. ② packed-binary가 막힘 상태로 종료(스왑 미발생) → "2시간 막히면 스왑 구함 선언 의무화" 규칙 필요. 둘 다 추상적 다짐이 아니라 상태표의 특정 행이 증거인 개선점입니다.
완료 기준 체크리스트
- [ ] 킥오프 30분의 안건(배정·단서 규칙·스왑·수면 교대)을 설명할 수 있다
- [ ] 채널을 용도별로 나누는 이유를 설명할 수 있다
- [ ] 1시간 상태표 갱신 리듬을 대회 내내 유지했다
- [ ] 단서 던지기를 실제로 3개 이상 실행했다
- [ ] 팀원 로그를 병합해 합산 성적과 중복 착수 경고를 확인했다
- [ ] 팀 회고에서 개선 규칙 문장 3개를 확정했다
- [ ] 솔로와 팀의 2시간 규칙 차이(drop vs 스왑)를 설명할 수 있다
6. 흔한 실수와 해결
벽 1. 각자 따로 풀다가 대회가 끝났어요
증상: 분위기는 좋았는데, 끝나고 보니 누가 무엇을 했는지 모릅니다. 초보 팀의 가장 흔한 실패 패턴입니다.
원인: 상태표 갱신이 "규칙"이 아니라 "하면 좋은 것"으로 합의됐습니다.
해결: 1시간 리듬을 장치로 만드세요 — 음성 채널에 정시 알림 봇을 걸거나, 매시 정각에 캡틴이 "상태표 타임" 한 줄을 치는 것만으로 됩니다. 상태표가 살아 있으면 소통은 저절로 생깁니다. 거꾸로는 절대 안 됩니다.
벽 2. 같은 문제를 두 명이 잡고 있었어요
증상 (실측 — 3-4의 출력):
file-upload-rce | Web | 해결 | alice,minho | 670분 ⚠ 중복 착수
원인: minho가 착수 전에 상태표를 보지 않았고, alice도 착수 기록을 늦게 했습니다. 둘의 40분이 한 문제에 겹쳐 태워졌습니다.
해결: 착수의 순서를 뒤집으세요 — 상태표에 이름을 먼저 쓰고, 그 다음에 문제를 엽니다. "문제부터 열고 나중에 기록"이 중복의 어머니입니다. 병합 스크립트의 경고는 사후 확인용이고, 예방은 이 순서 뒤집기 하나입니다.
벽 3. 스왑을 제안했는데 아무도 안 받아요
원인 1순위: 인수인계 없이 "이거 누가 좀 봐주세요"만 던졌습니다. 받는 사람은 2시간의 맥락을 처음부터 다시 쌓아야 하니 피하게 됩니다.
해결: 스왑은 세 줄 인수인계와 함께입니다 — ① 지금까지 확인한 사실, ② 버린 가설과 이유, ③ 내가 의심하는 다음 후보. 이 세 줄이 있으면 받는 사람의 진입 비용이 수십 분에서 수 분으로 줄어듭니다.
벽 4. 음성 채널이 잡담으로 흐르거나, 반대로 죽어 있어요
원인: 음성 채널의 역할 합의가 없었습니다.
해결: 음성은 "상시 접속 라운지"로 정하고, 기록이 필요한 것(착수/해결/단서/합의)은 전부 문자 채널과 상태표에 남기는 규칙을 쓰세요. 음성의 말은 휘발되므로, 중요한 합의는 그 자리에서 announce에 문장으로 옮기는 것까지가 합의입니다.
벽 5. 실력 차이가 커서 눈치가 보여요
증상: 신입 팀원이 단서 던지기를 주저하고, 고수 팀원이 문제를 독점합니다.
원인: 역할이 "분야"로만 나뉘고, 신입의 기여 경로가 설계되지 않았습니다.
해결: 신입의 명시적 역할을 정하세요 — 상태표 관리, 💡 채널의 첫 반응자, 쉬운 문제(워밍업) 전담. 특히 상태표 관리자는 팀 전체 진행을 보는 자리라, 실력과 무관하게 대회 전체 그림을 가장 빨리 배우는 자리입니다. 고수는 고수대로 "막힌 문제의 스왑 수신자"라는 역할이 있어야 독점이 풀립니다.
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| 분업의 효율 | 분야 합집합으로 커버리지가 넓어지는 팀의 이득 |
| 소통의 비용 | 조율·기록·중복 착수 — 작동하지 않으면 솔로 합계 이하 |
| 킥오프 30분 | 배정·단서 규칙·스왑·수면 교대를 대회 전에 문장으로 합의 |
| 1시간 리듬 | 상태표 갱신 주기 — 팀이 솔로들의 합으로 퇴화하지 않는 장치 |
| 2시간 스왑 | 막힌 문제의 담당 교체 — 다른 눈은 다른 배경 지식 |
| 💡 단서 던지기 | 한 문제의 부산물을 다른 문제의 열쇠로 연결하는 팀 고유 장치 |
| 중복 착수 | 같은 문제에 둘이 착수하는 손실 — 예방은 "기록 먼저, 문제는 나중" |
| 팀 회고 | 잘된 분업/소통 미스를 구분하고 개선점을 규칙 문장으로 확정 |
오늘의 도구와 명령어
| 도구·명령 | 하는 일 |
|---|---|
| 디스코드 채널 (announce/flags/clues) | 합의 고정, 인증 보고, 단서 유통 |
| 공유 상태표 | 문제별 담당·상태의 단일 진실 공급원 |
python merge_board.py alice.csv bob.csv ... |
개별 로그 병합 → 상태표 + 중복 경고 + 팀 합산 |
team_log.csv |
병합된 팀 로그 — Step 283 목표 산출의 입력 |
| 세 줄 인수인계 | 확인한 사실/버린 가설/다음 후보 — 스왑의 진입 비용 절감 |
핵심 감각
팀 대회에서 점수를 만드는 것은 실력만이 아닙니다 — 정보가 이동하는 속도입니다. 단서가 발견에서 채널까지 1분, 채널에서 맞는 사람의 눈까지 1분에 도달하는 팀은, 개인 실력이 같아도 한 등급 위의 성적을 냅니다. 오늘 만든 규칙들은 전부 그 이동 속도를 위한 배관입니다.
그리고 회고에서 확정한 개선 규칙들을 버리지 마세요. 다음 대회 — Step 283 — 에서는 그 규칙들을 지키는 것 자체가 측정 가능한 목표가 됩니다.
전부 체크되면 Step 281 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.