Context: cloudflared가 AlgoSu/infra/k3s/cloudflared.yaml을 직접 kubectl apply로 관리되어 ArgoCD tracking 대상이 아니었음(Sprint 69 G3). 동시에 aether-gitops에 algosu/base/monitoring/cloudflared.yaml 고아 매니페스트가 존재했지만 핫픽스/probe/securityContext가 누락되고 secret 이름도 달라 사용 불가 상태.
Context: MDX에서 icon={Crown} 형태로 lucide 식별자를 직접 참조 시 빌드 실패(Crown is not defined). MDX의 JSX expression은 모듈 스코프 import가 필요한데, compileMDX는 components 옵션의 React 컴포넌트만 자동 주입함.
Choice: src/components/blog/icons.ts에 lucide 아이콘 30개 string-keyed registry를 정의하고, 각 컴포넌트가 getIcon(name)으로 lookup. MDX에서는 icon="Crown"으로 사용. 6편 mdx 모두 import 불필요.
Alternatives: (a) mdx 파일별로 lucide import statement 추가 — 6편에 일일이 추가 필요, 유지보수 ↓. (b) compileMDX scope 옵션 — 5.0에서 명확하지 않고 type 안전성 ↓.
When to Reuse: kubectl apply로만 관리되던 리소스를 ArgoCD 추적으로 이관할 때. 동일 namespace/name/spec을 그대로 GitOps에 복제하면 ArgoCD가 RollingUpdate 없이 in-place로 adopt(annotation·label만 추가). 다운타임 0초. 단, spec이 한 글자라도 다르면 재생성됨 → 사전에 kubectl get -o yaml 백업 필수.
When to Reuse: next-mdx-remote compileMDX에서 mdx 본문이 React 컴포넌트의 prop으로 식별자(아이콘/타입 등)를 받아야 할 때. mdx에 import statement를 강요하지 말고 string key로 받아 컴포넌트 내부에서 registry lookup. 새 아이콘 추가 시 registry 한 곳만 수정.
When to Reuse: 블로그/문서에 다수의 ASCII 다이어그램이 있을 때 패턴별로 분류 (시스템 토폴로지/계층-트리/순차 파이프라인/Phase 마일스톤/시퀀스/상태 머신). 시퀀스·상태 머신은 Mermaid가 적합, 나머지는 손수 React 컴포넌트가 디자인 통제·다크모드·접근성 측면에서 우월. 동일 패턴이 3편 이상 반복되면 컴포넌트화 가치 충분.
P4: Phase 분할 + sample 검토 게이트 (Sprint 70-5/70-6 공통 워크플로우)
Where: 디자인/UX 변경 작업 전반
When to Reuse: 결과물의 시각적 만족도가 핵심인 작업(블로그 디자인, UI 컴포넌트). Phase 1에 인프라+sample 1~2편을 우선 진행 → PM 운영 환경 검토 → 만족 시 잔여 일괄 진행. Phase 2까지의 작업 일괄 commit이 아니라 sample 게이트를 둠으로써 디자인 가설을 빠르게 검증하고 toolchain 폐기 비용을 최소화.
Gotchas
G1: lucide-react 1.8.0의 export 누락 (Github 아이콘)
Symptom: npm install lucide-react 후 import { Github } from 'lucide-react' → Module '"lucide-react"' has no exported member 'Github' 빌드 실패.
Root Cause: 현재 npm registry의 [email protected]은 5822 export가 있지만 Github 자체는 deprecated. GitBranch, GitFork 등 git 관련 아이콘은 존재하지만 Github brand mark는 빠짐. LucideIcon type export도 없음.
Fix: Github import 제거(GitHub Worker는 GitBranch로 대체). LucideIcon 타입은 자체 정의(ComponentType<{className?, size?, strokeWidth?}>). 신규 lucide 아이콘 사용 전 node -e "console.log('Foo' in require('lucide-react'))" 로 사전 검증 권장.
G2: MDX JSX expression의 식별자 스코프 한계
Symptom: <HierarchyNode icon={Crown}/> 형태 mdx 작성 후 빌드 시 ReferenceError: Crown is not defined at stringify. compileMDX의 components 옵션은 컴포넌트 직접 사용(<Crown/>)만 주입할 뿐, JSX expression 안의 식별자 참조는 처리하지 않음.
Fix: prop을 React 식별자가 아닌 string key로 받고, 컴포넌트 내부에서 registry lookup(getIcon(name)). 본 스프린트의 D4 패턴 채택. 6편 mdx 어디에도 import statement 불필요.
G3: nginx try_files 패턴 — trailing slash로 404
Symptom: curl https://blog.algo-su.com/posts/system-architecture-overview/ → 404. trailing slash 없으면 200.
Root Cause: blog/nginx.conf의 try_files $uri $uri.html $uri/ =404는 trailing slash가 있으면 폴더 매칭 로직으로 갔다가 fallback 실패. Next.js export는 out/posts/{slug}.html(파일)과 out/posts/{slug}/index.html(폴더) 둘 다 생성하지만, nginx 패턴이 파일 우선이라 .html 확장 매칭이 동작하는 trailing slash 없는 형태가 정답.
Fix: PM 검토 URL 안내 시 trailing slash 없는 형태 사용. 또는 향후 nginx try_files 패턴을 $uri $uri.html $uri/index.html =404로 보강 가능(별도 작업).
G4: PM 검토 워크플로우 — sample 1편이 PM 만족 보장 안 함
Symptom: Sprint 70-5 Phase 3에서 system-architecture-overview를 Mermaid로 마이그레이션 후 sample push → 운영 검토 → "더 시각화해야지 무슨말인지" 피드백 → Sprint 70-6에서 컴포넌트 4종 신규 작성으로 재작업.
Root Cause: Phase 1 인프라 design 단계에서 디자인 가설(Mermaid 단순 flowchart)이 PM의 "풍부한 시각화" 기대와 어긋남. sample 검토 전에 디자인 가설의 강도를 시각적으로 PM에게 미리 알 수 없음.
Fix: 디자인 가설 강도가 약하면 sample 1편을 빠르게 push해서 운영 환경에서 검증(rollback 비용 < 추측 비용). Sprint 70-6에서는 Plan agent가 옵션 5가지를 제시 → PM이 옵션 C 선택 → 그 후 sample 진행 → 만족 → Phase 2. 옵션 단계에서 PM 의도를 명확히 한 게 핵심.