Step 294. CTF 복기 블록 A + Write-up 누적 50개 + 블로그 정돈 — 기록이 커리어가 되는 순간
Level 3 — CTF 실전과 공격 스킬 심화 | 난이도 ★★★☆☆ | 예상 소요 시간 2일 (복기 반나절 + 블로그 정돈 반나절 타임박스)
전제: Step 292의 Write-up 누적 40개, Step 293의 대회 #8(역할 로테이션 실험) 완료.
- 준비물: 지금까지 쓴 Write-up이 있는 블로그(정적 블로그든 팀 저장소든 무관), 대회 #8의 대회 로그, 파이썬 실행 환경, 정돈용 반나절. 이 챕터의 대회 복기 장면은 출력 예시이고, 블로그 검사 스크립트의 실행 결과는 여러분의 폴더에서 직접 확인하는 실측 대상입니다.
- ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다. Write-up에 실을 문제는 퇴출(retired) 처리됐거나 대회가 종료된 것만 사용하고, 활성 머신의 풀이 공개는 플랫폼 규정 위반입니다.
- 이 챕터는 정리입니다 — 새로 푸는 문제는 없고, 쌓아 온 기록을 "남이 읽을 수 있는 자산"으로 다듬습니다.
Write-up 50개는 CTF 커뮤니티에서 "꾸준히 활동하는 플레이어"의 기준선으로 통합니다. 한두 개의 잘 쓴 글은 운이 만들 수 있지만, 50개의 누적은 오직 시간과 루틴만이 만들 수 있습니다. 그래서 이 숫자는 채용 담당자와 커뮤니티에게 같은 문장으로 읽힙니다 — "이 사람은 멈추지 않는다."
문제는 50개가 쌓인 블로그가 정작 읽는 사람을 배려하지 못하는 경우가 많다는 것입니다. 태그가 제멋대로고, 대표작이 묻혀 있고, 방문자가 "이 사람이 뭘 잘하는지" 30초 안에 파악할 수 없습니다. 오늘은 대회 #8 복기로 50개를 완성한 뒤, 블로그를 포트폴리오 v1으로 정돈합니다. Level 4의 커리어 활용이 다가오기 전, 1차 완성입니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
- 복기 블록 A 루틴으로 대회 #8의 미해결 문제를 끝까지 파고 Write-up 누적 50개를 달성한다
- 스크립트로 블로그의 카테고리·태그 일관성과 깨진 링크를 자동 검사한다
- 채용·네트워킹 관점에서 대표작 5편을 선정하고 소개 페이지에 배치한다
- About 페이지에 커리큘럼 여정·대회 기록·기술 스택을 정리한다
- 정돈 작업을 반나절 타임박스로 제한해 콘텐츠 생산 중단을 막는다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | 파이썬 3(검사 스크립트), 마크다운(Write-up·About), 블로그 플랫폼 아무거나 |
| 오늘의 명령 | python blog_audit.py <글 폴더> — 직접 만드는 정돈 검사기 |
| 필요한 개념 | 복기 블록 A 루틴(Step 280), 대표작 선정 기준, 타임박스(timebox) |
| 오늘의 산출물 | 누적 Write-up 50개 + 정돈된 블로그(대표작 5편 + About + 인덱스) |
2-1. 50개의 무게 — 숫자가 말해주는 것
Write-up의 가치는 개수가 아니라 누적의 증명력에 있습니다. 채용 화면에서 지원자의 블로그를 연 담당자가 보는 것은 세 가지입니다 — 꾸준함(간격이 일정한가), 성장(최근 글이 옛날 글보다 나은가), 소통력(재현 가능하게 쓰는가). 50개는 이 세 가지를 한 번에 보여주는 최소 분량입니다.
네트워킹에서도 마찬가지입니다. 대회에서 만난 플레이어가 여러분의 블로그 주소를 받아 들어갔을 때, 분야별로 정리된 50편의 목록은 그 자체로 명함입니다. "웹은 이 사람에게 물어보자"는 기억을 남기는 것 — 그것이 포트폴리오의 첫 번째 일입니다.
2-2. 읽는 사람의 30초 — 대표작과 시리즈 묶기
방문자는 블로그에 30초를 줍니다. 그 안에 닿아야 할 것은 "최신 글"이 아니라 "가장 잘 쓴 글"입니다. 그래서 정돈의 첫 작업은 대표작 선정입니다.
대표작의 기준은 좋아요 수가 아닙니다. 다음 네 가지를 보세요.
| 기준 | 확인 질문 |
|---|---|
| 난이도 | 쉬운 문제가 아니라 당시의 나를 밀어붙인 문제인가 |
| 서사 | 시행착오와 버린 가설이 드러나는가 (성공 경로만 있으면 탈락) |
| 재현성 | 명령과 출력만으로 독자가 따라 할 수 있는가 |
| 분야 균형 | 5편이 한 분야에 몰리지 않는가 |
다음은 시리즈 묶기입니다. 흩어진 50편을 읽게 만드는 장치는 목록이 아니라 서사입니다 — "대회 #1부터 #8까지 성장 기록", "힙 특훈 10문제 연재"처럼 묶이면 방문자는 다음 편을 누릅니다.
2-3. 정돈의 대상 — 기계가 찾을 수 있는 것과 없는 것
블로그 정돈은 두 층으로 나뉩니다. 기계가 찾는 결함 — 카테고리 누락, 허용 목록 밖의 태그(web을 쓰다가 어느 날 webb, Web을 섞어 쓴 경우), 깨진 이미지·내부 링크. 이것은 스크립트가 잡습니다. 사람이 찾는 결함 — 대표작의 품질, About 페이지의 어조, 시리즈의 흐름. 이것은 여러분의 눈이 잡습니다.
오늘의 스크립트는 첫 번째 층을 담당합니다. 50개를 손으로 다 여는 대신, 글 폴더를 통째로 스캔해 결함 좌표를 뽑는 것 — CTF에서 배운 "자동화로 반복을 죽이기"의 블로그판입니다.
2-4. 타임박스 — 정돈이 생산을 잡아먹지 않게
소재의 경고를 그대로 옮깁니다 — 블로그 꾸미기에 빠져 콘텐츠 생산이 멈추는 함정. 테마를 바꾸고 폰트를 고르기 시작하면 반나절이 순식간에 사라지고, 정작 다음 대회 준비는 밀립니다.
그래서 오늘 정돈은 반나절 타임박스입니다. 시계를 켜고, 목록에 없는 작업(테마 교체, 로고 제작, 방문자 카운터)은 전부 금지합니다. 정돈은 도배가 아니라 정리입니다 — 물건을 버리고 제자리에 놓는 일이지, 집을 새로 짓는 일이 아닙니다.
3. 따라 하기
3-1. 블록 A 복기로 50개 채우기
대회 #8은 역할 로테이션 실험이었으므로 복기 거리가 평소보다 많습니다 — 비주력 분야에서 막힌 문제가 곧 복기 대상입니다. Step 280의 블록 A 루틴 그대로, "거의 왔던" 문제 3개를 골라 복기표를 채웁니다.
출력 예시 (복기표 — 대회 #8, 로테이션으로 맡은 비주력 분야 문제):
문제: rsa-fault (crypto, 350점)
내가 도달한 지점: N이 두 문제에서 공유됨을 발견, 그러나 활용법을 몰라 중단
정답의 다음 한 발: 공통 인수 gcd(N1, N2)로 소인수분해 (공통 인수 공격)
그걸 알려면 뭐가 필요했나: "같은 p를 재사용한 RSA 키 쌍" 패턴의 존재
플레이북 반영: crypto/공통인수.md — gcd 한 줄이면 끝. 다음 대회 즉시 사용 표시
읽는 법: 로테이션 대회의 복기는 한 줄이 추가됩니다 — "주력 담당자라면 몇 분 걸렸을까". 컨설팅을 요청했던 문제라면 그 답을 압니다. 이 차이가 곧 내 서브 분야와 주력의 거리이고, 특훈 분량의 근거입니다.
복기 3개를 Write-up으로 옮기면 누적이 50개에 도달합니다. 48시간 초고 규칙(Step 282)은 여전히 유효합니다 — 대회가 끝난 지 이틀이 지나면 시행착오의 디테일이 증발합니다.
3-2. 정돈 검사 스크립트 — 50개를 손으로 열지 않는다
이제 블로그 정돈의 기계 층입니다. 글 폴더를 스캔해 카테고리 분포, 태그 일관성, 깨진 링크를 한 번에 뽑는 스크립트를 만듭니다. 아래 코드를 blog_audit.py로 저장하세요.
# blog_audit.py — Write-up 블로그 정돈 검사기
# 사용: python blog_audit.py <블로그 글 폴더>
import re
import sys
from pathlib import Path
ALLOWED_TAGS = {"web", "pwn", "rev", "crypto", "forensics", "misc", "ctf"}
def parse_post(path: Path):
text = path.read_text(encoding="utf-8")
fm = re.match(r"^---\n(.*?)\n---\n", text, re.S)
tags, category = [], None
if fm:
m = re.search(r"^tags:\s*\[(.*?)\]", fm.group(1), re.M)
if m:
tags = [t.strip().strip('"').strip("'") for t in m.group(1).split(",") if t.strip()]
m = re.search(r"^category:\s*(.+)$", fm.group(1), re.M)
if m:
category = m.group(1).strip()
targets = re.findall(r"!?\[[^\]]*\]\((?!https?://)([^)]+)\)", text)
return category, tags, targets
def main():
root = Path(sys.argv[1])
posts = sorted(root.glob("*.md"))
cats, bad_tags, broken = {}, [], []
for p in posts:
category, tags, targets = parse_post(p)
cats[category or "(없음)"] = cats.get(category or "(없음)", 0) + 1
for t in tags:
if t.lower() not in ALLOWED_TAGS:
bad_tags.append((p.name, t))
for tgt in targets:
clean = tgt.split("#")[0]
if clean and not (p.parent / clean).exists():
broken.append((p.name, tgt))
print(f"누적 Write-up: {len(posts)}개")
print("\n[카테고리 분포]")
for c, n in sorted(cats.items(), key=lambda x: -x[1]):
print(f" {c}: {n}개")
print(f"\n[허용 목록 외 태그] {len(bad_tags)}건")
for name, t in bad_tags:
print(f" {name} -> 태그 '{t}'")
print(f"\n[깨진 내부 링크/이미지] {len(broken)}건")
for name, tgt in broken:
print(f" {name} -> {tgt}")
if __name__ == "__main__":
main()
실제 실행 결과입니다 — 52개의 샘플 Write-up 폴더(일부러 결함을 심어 둠)에 대고 돌린 실측입니다:
$ python blog_audit.py blog294/posts
누적 Write-up: 52개
[카테고리 분포]
web: 15개
pwn: 12개
rev: 8개
crypto: 8개
forensics: 6개
(없음): 2개
misc: 1개
[허용 목록 외 태그] 2건
2026-07-writeup-07.md -> 태그 'webb'
2026-41-writeup-41.md -> 태그 'reversing'
[깨진 내부 링크/이미지] 3건
2026-05-writeup-05.md -> images/ctf8-web3.png
2026-19-writeup-19.md -> ./old-writeup.md
2026-47-writeup-47.md -> images/bof-flow.png
읽는 법: 세 블록이 각각 정돈 작업 목록입니다. ① 카테고리 분포에서 (없음) 2개는 머리말에 카테고리를 안 쓴 글 — 분야별 색인에서 빠지는 글이니 채웁니다. ② 허용 목록 외 태그 — webb는 오타, reversing은 rev로 통일 대상. 태그가 흩어지면 "이 사람의 웹 글 전부 보기"가 안 됩니다. ③ 깨진 링크 3건 — 이미지 경로 오타와 삭제된 글을 가리키는 내부 링크. 방문자가 깨진 이미지를 보면 신뢰는 그 자리에서 끝납니다.
여러분의 폴더에서 직접 돌려 보세요. 건수는 달라도 구조는 같습니다 — 스크립트가 좌표를 주고, 여러분은 그 좌표만 고치면 됩니다.
3-3. 대표작 5편 선정과 소개 페이지
2-2의 기준표로 50개 중 5편을 고릅니다. 선정이 끝나면 블로그 첫 화면(또는 고정 페이지)에 배치합니다. 각 대표작에는 한 줄 추천사를 붙입니다 — "왜 이 글을 먼저 읽어야 하는가"를 방문자 대신 답하는 문장입니다.
출력 예시 (소개 페이지의 대표작 목록):
■ 대표 Write-up (고정 페이지)
1. [pwn] babyheap — 힙을 처음으로 "읽은" 날 (힙 특훈 10문제 연재의 결산)
2. [web] jwt-forge — alg=none이 안 통할 때, 그다음 수를 찾는 과정
3. [crypto] rsa-fault — gcd 한 줄의 위력, 공통 인수 공격 입문
4. [rev] rev-me-gently — 안티 디버깅과의 4시간, 버린 가설 3개의 기록
5. [forensics] packet-river — 패킷에서 자격 증명을 건지는 정석 순서
읽는 법: 분야가 흩어져 있고(균형), 제목 옆 한 줄이 "서사가 있다"고 광고합니다. 방문자가 어떤 분야의 사람이든 하나는 집어 들게 만드는 것이 균형의 역할입니다.
시리즈 묶기도 같은 페이지에 둡니다 — "대회 #1~#8 성장 기록", "힙 특훈 연재"처럼 링크 목록으로요. 대표작이 첫인상을, 시리즈가 체류 시간을 담당합니다.
3-4. About 페이지 — 숫자로 쓰는 자기소개
About 페이지는 감성 소개가 아니라 검증 가능한 사실의 목록으로 씁니다. 채용·네트워킹에서 읽히는 자기소개의 공식은 세 블록입니다.
■ About 페이지 (예시)
여정: 2026년 1월 파워쉘 첫걸음 → 9월 CTF 8개 대회 출전 (총 294일 차)
대회 기록: CTFtime 팀 페이지 링크, 최고 기록 상위 40% (대회 #7)
기술 스택: 웹(주력) / 포너블(서브) / Python, pwntools, Burp Suite
Write-up: 누적 50편 — 대표작은 위 목록 참조
연락: 디스코드 ID 또는 이메일 (공개 가능한 것만)
규칙 두 가지입니다 — 모든 수치는 확인 가능한 것만(CTFtime에 기록이 남는 순위만 씁니다), 개인정보는 가공(실명·소속 대신 핸들, 연락처는 대회용 계정). 블로그는 공개 장소이고, 공격자의 정보 수집 대상이기도 합니다 — 보안을 공부하는 사람의 블로그가 정보부터 새면 안 됩니다.
3-5. 통계 대시보드 — 순위 추이 한 장
마지막으로 대회별 순위 추이를 표로 만들어 About이나 대표작 페이지에 붙입니다. 그래프는 다음 스텝들에서 자세히 다루니(Step 297), 오늘은 표면 충분합니다.
| 대회 | 순위 | 백분위 | 푼 문제 | 비고 |
|------|------|--------|---------|------|
| #1 | 291/380 | 상위 77% | 2 | 첫 대회, 완주가 목표 |
| #3 | 178/356 | 상위 50% | 4 | 팀 첫 출전 |
| #6 | 201/433 | 상위 46% | 5 | 중간 평가, 50% 유지 |
| #8 | 158/395 | 상위 40% | 5 | 로테이션 실험 |
읽는 법: 방문자에게 이 표는 "오르락내리락하지만 우상향"이라는 한 문장으로 읽힙니다. 그리고 그 한 문장이 2-1의 "이 사람은 멈추지 않는다"를 데이터로 뒷받침합니다. 정확한 수치만 쓰고, 기록이 없는 회차는 비워 두세요 — 추측으로 채운 숫자는 나중에 스스로도 못 믿는 데이터가 됩니다.
4. 미션과 연습문제
미션 — 누적 50개 + 블로그 포트폴리오 v1
- 대회 #8 복기(블록 A 루틴)로 복기표 3개를 완성하고, 그중 Write-up을 작성해 누적 50개를 달성합니다.
blog_audit.py를 저장하고 여러분의 글 폴더에 대고 실행합니다 — 출력의 세 블록(카테고리·태그·깨진 링크)을 작업 목록으로 정리합니다.- 검사 결과의 결함을 전부 고치고 다시 실행해 "허용 목록 외 태그 0건, 깨진 링크 0건"을 확인합니다.
- 2-2의 기준표로 대표작 5편을 선정하고, 한 줄 추천사를 붙여 소개 페이지에 배치합니다 — 분야가 한쪽에 몰리면 다시 고릅니다.
- About 페이지를 세 블록(여정·기록·스택) 구조로 작성합니다 — 확인 불가능한 수치와 미가공 개인정보가 없는지 검토합니다.
- 대회 순위 추이 표를 만들어 게재합니다 — 정돈 작업 전체에 반나절 타임박스를 지킵니다.
연습문제
문제 1. Write-up 50개가 "꾸준히 활동하는 플레이어의 기준선"으로 읽히는 이유를, 채용 담당자가 블로그에서 확인하는 세 가지와 연결해 설명해 보세요.
문제 2. 대표작 선정 기준에 "서사(시행착오와 버린 가설의 존재)"가 포함되는 이유는 무엇인가요? 성공 경로만 담긴 글이 대표작으로 부적합한 이유와 함께 답해 보세요.
문제 3. 정돈 검사를 스크립트로 자동화할 때, 기계가 찾을 수 있는 결함과 사람이 찾아야 하는 결함을 각각 두 가지씩 들어 보세요.
문제 4. About 페이지에 "확인 가능한 수치만 쓴다"는 규칙이 필요한 이유는 무엇인가요? 과장된 수치가 나중에 어떤 문제를 만드는지 포함해 답해 보세요.
5. 모범 답안과 완료 기준
미션 모범 답안
검증 기준으로 확인하세요.
- 복기표 3개: "내가 도달한 지점 | 정답의 다음 한 발 | 필요했던 것" 세 칸이 전부 채워져 있는가 — "Write-up을 읽고 이해했다"로 끝난 복기는 블록 A가 아닙니다. 재현 가능한 문제는 끝까지 푼 기록이 있어야 합니다.
- 누적 50개: 블로그의 실제 글 수가 50개 이상이고, 스크립트의
누적 Write-up:출력으로 확인 가능한가. - 결함 0건: 재실행 결과 "허용 목록 외 태그 0건, 깨진 내부 링크/이미지 0건"인가 — 카테고리
(없음)도 0이어야 색인이 완성됩니다. - 대표작 5편: 네 기준(난이도·서사·재현성·분야 균형)을 모두 통과하고, 각각 한 줄 추천사가 있는가.
- About 페이지: 여정·기록·스택 세 블록이 있고, 모든 수치가 CTFtime 등에서 확인 가능하며, 연락처가 대회용 계정으로 분리돼 있는가.
- 타임박스: 정돈에 실제로 반나절 이내를 썼는가 — 테마 교체 같은 목록 외 작업을 했다면 그것부터 회고할 일입니다.
연습문제 해답
문제 1 해답. 50개라는 누적은 단기간에 위조할 수 없기 때문입니다. 채용 담당자가 확인하는 세 가지 — 꾸준함(게재 간격), 성장(과거와 현재 글의 품질 차이), 소통력(재현 가능한 서술) — 은 모두 "여러 편을 시간축으로 놓고 볼 때"만 드러납니다. 잘 쓴 글 3편은 집중해서 만들 수 있지만, 50편의 일정한 간격과 우상향은 루틴 없이는 불가능합니다. 그래서 50개는 실력의 증명이라기보다 지속력의 증명으로 읽히고, 실무 채용에서는 후자가 더 귀한 신호입니다.
문제 2 해답. 서사가 있는 글만이 "이 사람이 어떻게 생각하는가"를 보여주기 때문입니다. 성공 경로만 담긴 Write-up은 정답지의 복사에 가까워서, 읽는 사람은 작성자의 판단력을 알 수 없습니다. 반면 버린 가설과 그 폐기 근거가 있는 글은 "막혔을 때 어떻게 움직이는 사람인가"를 드러냅니다 — 채용·네트워킹에서 상대가 진짜 궁금한 것은 그것입니다. 대표작은 실력의 광고판이 아니라 사고방식의 샘플이어야 합니다.
문제 3 해답. 기계가 찾는 결함의 예: 카테고리·태그의 누락과 표기 불일치, 깨진 내부 링크·이미지 경로(오늘 스크립트가 잡은 것들) — 패턴과 존재 여부로 판정 가능한 것들입니다. 사람이 찾는 결함의 예: 대표작 글의 서사 품질과 재현성, About 페이지의 어조와 정보 범위 — "좋은가/적절한가"의 판단이 필요한 것들입니다. 구분의 기준은 판정 규칙을 문장으로 쓸 수 있는가입니다 — 쓸 수 있으면 기계에게, 못 쓰면 사람의 몫입니다.
문제 4 해답. 포트폴리오의 수치는 상대가 검증할 수 있고, 한 번 거짓이 드러나면 나머지 전부가 의심받기 때문입니다. CTFtime 순위는 공개 기록이라 대조하면 바로 드러나고, 면접에서 "이 대회에서 뭘 풀었나요"라는 질문 하나에도 무너집니다. 반대로 확인 가능한 수치는 보수적일수록 신뢰를 쌓습니다 — "상위 40%"가 사실로 확인된 사람의 다음 문장은 의심 없이 읽힙니다. 포트폴리오의 본질은 자기 PR이 아니라 검증 가능성의 축적입니다.
완료 기준 체크리스트
- [ ] 대회 #8 복기표 3개를 세 칸 구조로 완성했다
- [ ] Write-up 누적 50개를 달성하고 스크립트 출력으로 확인했다
- [ ]
blog_audit.py를 내 블로그에 실행해 결함 목록을 뽑았다 - [ ] 카테고리 누락·태그 불일치·깨진 링크를 전부 고치고 0건을 확인했다
- [ ] 대표작 5편을 네 기준으로 선정하고 한 줄 추천사와 함께 배치했다
- [ ] About 페이지를 세 블록 구조로 작성했다 (검증 가능 수치·가공된 개인정보)
- [ ] 대회 순위 추이 표를 게재했다
- [ ] 정돈 작업을 반나절 타임박스 안에 끝냈다
6. 흔한 실수와 해결
벽 1. 스크립트를 실행하니 인자 에러가 나요
증상:
root = Path(sys.argv[1])
~~~~~~~~^^^
IndexError: list index out of range
원인: 글 폴더 경로를 인자로 안 줬습니다. 이 스크립트는 sys.argv[1]로 폴더를 받습니다 (실측).
해결: python blog_audit.py 여러분의_글_폴더 형식으로 실행하세요. 경로에 공백이 있으면 큰따옴표로 감쌉니다 — python blog_audit.py "my blog/posts". 윈도우 탐색기에서 폴더를 터미널로 끌어다 놓으면 경로가 자동 입력됩니다.
벽 2. 검사 결과가 0건인데 뭔가 이상해요 — 글이 하나도 안 잡혀요
증상: 누적 Write-up: 0개로 나옵니다.
원인: 대부분 폴더를 한 단계 위/아래로 잘못 가리켰거나, 글이 .md가 아닌 확장자(.markdown, .txt)인 경우입니다. 스크립트는 *.md만 봅니다.
해결: 폴더 안에서 ls *.md(Git Bash) 또는 dir *.md(PowerShell)로 파일이 보이는지 먼저 확인하세요. 하위 폴더까지 글이 퍼져 있다면 root.glob("*.md")를 root.rglob("*.md")로 바꾸면 재귀 검색이 됩니다.
벽 3. 대표작을 고르다 보니 다 웹 글이에요
증상: 잘 쓴 글이 주력 분야에 몰려서 5편의 분야 균형이 안 맞습니다.
원인: 주력 분야 글이 절대 품질도 높은 것은 자연스러운 일입니다 — 그 분야에 시간을 썼으니까요.
해결: 균형 규칙을 완화하지 말고 선정 순서를 뒤집으세요 — 서브 분야에서 먼저 "그나마 가장 서사가 살아 있는" 1편씩을 고른 뒤, 남는 자리를 주력으로 채우는 겁니다. 서브 분야 글이 약해 보인다면 그것이 다음 Write-up의 개선 과제입니다. 대표작 선정은 과거의 심사이면서 미래의 작문 계획입니다.
벽 4. 정돈하다가 테마까지 바꾸고 있어요 — 반나절이 다 갔어요
증상: 폰트와 색을 고르기 시작했고, 글은 하나도 안 고쳤습니다.
원인: 정돈과 꾸미기를 한 바구니에 넣었기 때문입니다. 꾸미기는 끝이 없고, 즉시 성취감을 줘서 더 위험합니다.
해결: 작업 목록을 종이에 적고, 목록에 없는 행동을 하는 자신을 발견하면 즉시 멈추세요. "테마 바꾸고 싶다"는 욕구는 메모해 두고 타임박스가 끝난 뒤 별도 일정으로 잡습니다. 정돈의 완료 조건은 오직 하나 — 스크립트 재실행 결과가 0건이고 대표작이 배치된 것입니다.
벽 5. 50개를 셌더니 47개예요 — 숫자를 어떻게 채우죠?
증상: 대회 Write-up만으로는 50개가 안 됩니다.
원인: 정상입니다. 대회 문제만 쓰다 보면 대회 횟수에 수가 묶입니다.
해결: Step 286에서 했던 것처럼 HTB/THM 머신 풀이를 Write-up화하세요 — 단, 머신은 반드시 퇴출 확인 후 공개입니다. 복기하면서 재현한 문제들도 풀이를 다듬으면 훌륭한 Write-up입니다. 억지로 수를 채우는 것만은 금지 — "6개월 후의 내가 이 글로 재현 가능한가" 기준(Step 286)을 못 미치는 글은 누적 수에서 세지 않는 것이 오히려 포트폴리오를 지킵니다.
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| 50개의 기준선 | 위조 불가능한 누적 — 꾸준함·성장·소통력의 삼중 증명 |
| 읽는 사람의 30초 | 방문자가 주는 시간 — 최신 글이 아니라 대표작이 닿아야 한다 |
| 대표작 4기준 | 난이도·서사·재현성·분야 균형 — 사고방식의 샘플을 고른다 |
| 정돈의 두 층 | 기계가 찾는 결함(패턴) / 사람이 찾는 결함(판단) |
| 타임박스 | 정돈은 반나절 — 목록 외 작업 금지, 꾸미기는 별도 일정 |
| 검증 가능성 | 포트폴리오 수치는 대조 가능한 것만 — 신뢰의 본체 |
오늘의 도구·명령어
| 도구·명령 | 하는 일 |
|---|---|
python blog_audit.py <폴더> |
카테고리 분포·태그 일관성·깨진 링크 일괄 검사 |
ALLOWED_TAGS 집합 |
태그 표기 통일의 기준 목록 — 팀 규칙으로 고정 |
| 대표작 소개 페이지 | 방문자의 30초를 받는 첫 화면 — 한 줄 추천사 필수 |
| About 세 블록 | 여정·기록·스택 — 확인 가능 수치 + 가공된 연락처 |
| 순위 추이 표 | "멈추지 않는다"를 데이터로 뒷받침하는 한 장 |
명령어보다 중요한 감각
오늘 한 일은 겉으로는 정리정돈이지만, 본질은 시점의 전환입니다. 지금까지 블로그는 "미래의 나를 위한 복습 노트"였습니다 — 오늘부터는 "남이 나를 평가하는 문서"이기도 합니다. 같은 글이 독자를 얻으면 요구되는 품질이 달라집니다.
그리고 이 문서는 살아 있는 것입니다. 대회 #9, #10을 거치며 대표작은 갱신되고 추이 표는 길어집니다. 정돈은 1회성 이벤트가 아니라 누적 루틴의 일부 — 다음 마일스톤(Step 297의 10회 회고)에서 이 포트폴리오가 다시 심사대에 오릅니다. 오늘의 반나절은 그날의 준비였습니다.
전부 체크되면 Step 294 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.