시리즈: AI 팀과 함께 기술블로그 만들기 | Episode 2
이전 에피소드에서 Claude Code Agent Teams로 3인 AI 팀을 꾸렸습니다. UI/UX 담당, 기술 아키텍처 담당, 코드 리뷰 담당. 각자 독립적으로 블로그를 분석하고 보고서를 제출했습니다.
이번 글에서는 3명이 각각 무엇을 발견했는지, 그리고 그 결과를 실제로 적용하면서 내가 따른 것과 무시한 것을 솔직하게 기록합니다.
결론부터 말하면, AI의 기술적 분석은 놀라울 정도로 정확했지만 모든 권장 사항을 그대로 따르면 안 됩니다. 왜 그런지 구체적으로 보여드리겠습니다.
보고서 스펙
3명의 에이전트가 제출한 보고서의 규모부터 보겠습니다.
| 에이전트 | 보고서 분량 | 주요 섹션 | 비교 분석 |
|---|---|---|---|
| UI/UX 담당 | ~1,000줄 | 8개 섹션 | 테마 4종, 플러그인 4종, 폰트 6종 |
| 아키텍처 담당 | ~1,430줄 | 8개 섹션 | docker-compose 전체 재설계, CI/CD 파이프라인 |
| 코드 리뷰 담당 | ~760줄 | 9개 섹션 | 22개 이슈 (Critical 7, Warning 9, Info 6) |
총 3,190줄, 25개 섹션. 한 사람이 이 정도 조사를 하려면 최소 2~3일은 걸렸을 겁니다.
UI/UX 담당: “기술블로그에 최적화된 UX를 설계해줘”
테마 전략: TT5 자식 테마를 강력 권장
UI/UX 에이전트는 기존 테마인 Twenty Twenty-Five(TT5)의 theme.json을 분석했습니다. 그리고 꽤 흥미로운 발견을 했습니다.
“TT5는 이미 Fira Code를 코드 블록 전용 폰트로 번들링하고 있으며, core/code 블록에 대한 스타일이 theme.json에 사전 정의되어 있다. 이것은 기술블로그에 상당히 유리한 출발점이다.”
4가지 옵션을 비교한 끝에 TT5 자식 테마를 최종 권장했습니다. Fira Code가 이미 번들되어 추가 로드 불필요하고, FSE(Full Site Editing) 지원으로 theme.json 상속만으로 커스터마이징이 가능하며, 8개 스타일 변형을 다크 모드 기반으로 활용할 수 있다는 이유였습니다.
그런데 나는 이 권장 사항을 따르지 않았습니다.
내가 GeneratePress를 선택한 이유
TT5 자식 테마 대신 GeneratePress FREE를 선택했습니다. AI의 분석이 틀린 건 아닙니다. 기술적으로 TT5 자식 테마는 훌륭한 선택입니다. 하지만 실제 구축 과정에서 우선순위가 달라졌습니다.
| 기준 | TT5 자식 테마 | GeneratePress |
|---|---|---|
| 초기 설정 시간 | 자식 테마 생성, theme.json, functions.php 필요 | Customizer에서 클릭 몇 번 |
| 코드 블록 | Fira Code 번들됨 | CSS에서 CDN 로드 |
| 커스터마이징 | theme.json + PHP | Customizer + Additional CSS |
| 유지보수 | TT5 업데이트 시 호환성 확인 필요 | 독립적 |
핵심은 시간이었습니다. 블로그는 글을 쓸 때 가치가 있지, 테마를 만드는 데 시간을 쓸 때가 아닙니다.
교훈 1: AI는 “기술적으로 가장 우아한 솔루션”을 권장하지만, 실제로는 “가장 빨리 동작하는 솔루션”이 더 나을 때가 있다.
타이포그래피: 거의 100% 채택
반면 타이포그래피 권장 사항은 거의 그대로 따랐습니다. Pretendard(본문) + Fira Code(코드) 조합은 toss.tech, velog 등 국내 기술블로그에서 이미 검증된 조합이라 신뢰도가 높았습니다.
| 항목 | AI 권장 | 실제 적용 | 채택 |
|---|---|---|---|
| 본문 폰트 | Pretendard | Pretendard Variable (CDN) | O |
| 코드 폰트 | Fira Code | Fira Code (CDN) | O |
| 본문 행간 | 1.8 | 1.8 | O |
| 콘텐츠 폭 | 720px | 720px (max-width) | O |
| 코드 블록 배경 | #1e1e2e (항상 다크) | #1e1e2e | O |
한 가지 인상적이었던 것은 “코드 블록은 라이트 모드에서도 항상 다크 배경”이라는 원칙입니다. VS Code, GitHub, Stack Overflow에서 개발자들이 이미 익숙한 패턴을 따르자는 것인데, 이건 혼자서는 명시적으로 정리하지 못했을 통찰이었습니다.
아키텍처 담당: “Docker 구성을 최적화해줘”
docker-compose.yml 전면 재설계
| 항목 | Before | After |
|---|---|---|
| WordPress 이미지 | wordpress:latest | wordpress:6.9-php8.3-apache |
| Health check | 없음 | 모든 서비스에 추가 |
| Resource limits | 없음 | 메모리 제한 설정 |
| PostgreSQL | 실행 중 (미사용) | 제거 |
| Redis | 설정 없음 | 128MB, LRU, AOF |
| 로깅 | 무제한 | max-size 10m, 3파일 |
이 부분은 거의 100% 채택했습니다. 인프라 구성은 “빠르게 대충”이 아니라 “제대로 한 번”이 맞기 때문입니다.
Redis 캐시 전략: 3단계 레이어
[사용자] → [Caddy (정적 캐시)] → [WordPress + PHP]
↓
[Redis Object Cache]
↓
[MariaDB]
실제 적용한 Redis 설정:
redis:
image: redis:7-alpine
command: >
redis-server
--requirepass ${REDIS_PASSWORD}
--maxmemory 128mb
--maxmemory-policy allkeys-lru
--appendonly yes
--appendfsync everysec
단순히 redis:alpine으로 띄우던 것에서, 메모리 제한(128MB), LRU 정책(메모리 가득 차면 가장 오래된 키 삭제), AOF 영속성(데이터 유실 방지)까지 설정한 것입니다.
내가 따르지 않은 것: Caddy HTTPS 자동화
아키텍처 에이전트와 코드 리뷰 에이전트 모두 “Caddy 레이블에서 http:// 프리픽스를 제거해야 자동 HTTPS가 활성화된다”고 권장했습니다.
# AI 권장
labels:
caddy: "yndl.dev" # http:// 없음 → 자동 HTTPS
# 실제 적용
labels:
caddy: "http://yndl.dev" # http:// 있음 → HTTP만 서빙
AI 권장 대로 http://를 제거했을 때 벌어진 일:
- Caddy가 auto-HTTPS를 활성화
- Let’s Encrypt에 인증서 발급 요청
- DNS-01 챌린지 시도 → Cloudflare 프록시 뒤에 있어서 실패
- 사이트 전체 다운 (308 무한 리다이렉트)
Cloudflare가 SSL을 처리하므로 Caddy는 HTTP만 서빙하면 됩니다. AI는 인프라의 전체 그림(Cloudflare → Caddy → WordPress)을 모른 채 Caddy만 보고 판단한 것입니다.
교훈 2: AI는 개별 컴포넌트의 Best Practice는 정확히 아는 반면, 컴포넌트 간의 상호작용(Cloudflare + Caddy + WordPress 체인)은 놓칠 수 있다. 인프라의 전체 그림은 사람이 판단해야 한다.
코드 리뷰 담당: “보안 취약점을 찾아줘”
코드 리뷰 에이전트는 가장 실용적인 결과를 냈습니다. 총 22개 이슈를 발견했는데, Critical 7개 중 대부분이 실제로 위험한 것들이었습니다.
Critical-01: PostgreSQL 포트가 인터넷에 노출
# 발견된 문제
postgres:
ports:
- "5432:5432" # 0.0.0.0:5432에 바인딩
WordPress가 사용하지도 않는 PostgreSQL이 인터넷에 포트가 열려 있었습니다. 방화벽이 없으면 누구든 DB에 직접 접속을 시도할 수 있는 상태였습니다.
Critical-04: DB 비밀번호 불일치 + Docker $ 보간 문제
.env 파일에서 MARIADB_PASSWORD와 WORDPRESS_DB_PASSWORD가 다른 값으로 설정되어 있었습니다. 게다가 비밀번호에 $와 @ 같은 특수문자가 있었는데, Docker의 환경변수 보간에서 $M이 변수로 해석되어 비밀번호가 깨지는 문제도 있었습니다.
# Before (위험 — $가 Docker 변수로 해석됨)
MARIADB_PASSWORD=d&a9X5McNt7s2PX^@$M^
# After (안전 — hex-only)
MARIADB_PASSWORD=a36e81299c2218db0be92434155a2b87
교훈: .env의 비밀번호는 hex-only (openssl rand -hex 16)로 생성하면 Docker $ 보간 문제를 완전히 피할 수 있습니다.
채택률: 22개 중 19개 (86%)
| 등급 | 발견 | 채택 | 비율 |
|---|---|---|---|
| Critical (7) | 7 | 7 | 100% |
| Warning (9) | 9 | 8 | 89% |
| Info (6) | 6 | 4 | 67% |
| 합계 | 22 | 19 | 86% |
3명이 동의한 것, 그리고 겹친 것
Agent Teams의 가장 가치 있는 순간은 독립적 수렴이 일어날 때입니다.
| 주제 | UI/UX | 아키텍처 | 코드 리뷰 |
|---|---|---|---|
| Prismatic 채택 | 290+ 언어, 경량 | Prism.js 업계 표준 | – |
| Rank Math 채택 | 무료로 Schema 지원 | 한국어 UI, 경량 | – |
| PostgreSQL 제거 | – | 불필요한 리소스 | 포트 노출 위험 |
| 이미지 버전 고정 | – | 재현 가능한 배포 | latest 태그 위험 |
같은 결론인데 도달 경로가 다릅니다. 아키텍처 담당은 PostgreSQL을 “불필요한 리소스 소모”로 봤고, 코드 리뷰 담당은 “보안 위험(포트 노출)”으로 봤습니다. 두 관점이 합쳐지면 제거의 근거가 한층 단단해집니다.
관점이 보완된 경우: Redis
아키텍처 담당은 Redis의 기능적 최적화(메모리 정책, 영속성, 성능)를 설계했고, 코드 리뷰 담당은 같은 Redis에서 보안 이슈(비밀번호 미설정)를 발견했습니다. 두 관점을 합치면 “기능적으로 최적화된 + 보안이 강화된” Redis 설정이 완성됩니다. 이것이 Agent Teams의 진짜 가치입니다.
AI 권장 vs 실제 결정: 최종 대조표
| 항목 | AI 권장 | 실제 결정 | 채택 | 이유 |
|---|---|---|---|---|
| 테마 | TT5 자식 테마 | GeneratePress FREE | X | 속도 우선 |
| 본문 폰트 | Pretendard | Pretendard | O | 검증된 조합 |
| 코드 하이라이팅 | Prismatic | Prismatic | O | 만장일치 |
| SEO | Rank Math | Rank Math | O | 만장일치 |
| Caddy HTTPS | auto-HTTPS | HTTP 모드 | X | Cloudflare 환경 |
| Docker 이미지 | 버전 고정 | 버전 고정 | O | |
| PostgreSQL | 제거 | 제거 | O | 만장일치 |
| Redis 인증 | 추가 | 추가 | O | |
| 콘텐츠 폭 | 720px | 720px | O |
채택률: 86% — AI 권장을 따르지 않은 2건 모두 “AI가 틀렸기” 때문이 아니라 “AI가 모르는 컨텍스트가 있었기” 때문입니다.
보고서에서 가장 인상 깊었던 것 3가지
1. 한국어 기술 콘텐츠의 타이포그래피 과제
“한국어 기술블로그는 세 가지 글자 체계가 혼재한다: 한글 본문(설명, 개념 서술), 영문 기술 용어(API, JavaScript, Docker), 코드 블록(순수 영문 + 기호). 이 세 가지가 자연스럽게 어우러지려면 폰트 선택이 매우 중요하다.”
이 문제를 명시적으로 정리한 적이 없었는데, AI가 대신 정리해 주니 이후 모든 타이포 결정이 쉬워졌습니다. 문제가 정의되면 해결책은 따라옵니다.
2. 보안 이슈의 연쇄 발견
비밀번호에 $가 포함 → Docker 변수 보간으로 깨짐
→ MariaDB와 WordPress 비밀번호 불일치
→ DB 인증 실패
→ WordPress 설치 불가
이 연쇄를 한 번에 파악하고 “hex-only 비밀번호를 사용하라”는 근본 해결책을 제시한 것은 코드 리뷰 에이전트의 가장 큰 공헌이었습니다.
3. CI/CD 파이프라인 청사진
아키텍처 에이전트는 GitHub Actions 기반 배포 파이프라인을 완전히 설계해 왔습니다. 마크다운 파일을 Git에 push하면 WordPress REST API로 자동 발행하는 구조까지요. 아직 구현하지 않았지만, 구현할 때 시간이 크게 절약될 것입니다.
세 에이전트의 한계
한계 1: 외부 서비스와의 상호작용을 모른다
에이전트들은 프로젝트 디렉토리 안의 파일만 볼 수 있습니다. Cloudflare 설정, DNS 구성, 서버 방화벽 같은 외부 컨텍스트는 알 수 없습니다. 그래서 “Caddy에서 auto-HTTPS를 켜라”는 권장이 나온 것입니다.
한계 2: “기술적 우아함”을 과대평가한다
TT5 자식 테마 vs GeneratePress 결정이 대표적입니다. AI는 1주 후의 품질을 최적화하고, 사람은 오늘의 속도를 최적화합니다. 둘 다 합리적인 판단이지만, 이 블로그는 사람의 판단이 맞았습니다.
한계 3: 비용 의식이 없다
에이전트들이 제안한 플러그인 스택을 전부 설치하면 10개가 넘습니다. 플러그인이 많으면 충돌 위험, 업데이트 부담, 성능 저하가 따라옵니다. 현재 설치한 플러그인: Redis Object Cache, Prismatic, Rank Math. 딱 3개.
이 과정에서 배운 것
- AI 보고서는 “의사 결정 프레임워크”로 가장 유용하다. “실행 매뉴얼”이 아니라 “어떤 옵션이 있고 각각의 장단점이 뭔지”를 파악하는 도구.
- 교차 검증의 가치는 생각보다 크다. 세 에이전트가 독립적으로 같은 결론에 도달하면 의심 없이 채택할 수 있다.
- Critical 이슈는 무조건 따라라. 보안과 안정성에 관한 문제는 “나중에”가 없다.
- 보고서의 수명은 짧다. AI 보고서는 “지금 결정을 내리기 위한 도구”이지 “영구 참고 문서”가 아니다.
다음 에피소드 예고
보고서 분석은 여기까지. 다음 에피소드에서는 이 결정들을 실제로 구현하면서 마주친 문제들을 다룹니다. 특히 Caddy 리버스 프록시에서 발생한 3가지 장애와 그 해결 과정은 꽤 드라마틱합니다.
예고: Episode 3 — Caddy와 싸운 하루: 308 루프, 로그인 무한 리다이렉트, 사이트 블록 증발
시리즈 안내: AI 팀과 함께 기술블로그 만들기
| 회차 | 제목 | 상태 |
|---|---|---|
| 1 | Agent Teams란? 3인 AI 팀 구성기 | 발행 |
| 2 | AI 3인이 내 블로그를 진단했다 | 현재 글 |
| 3 | Caddy와 싸운 하루: 리다이렉트 루프 3연전 | 발행 |
| 4 | Docker + WordPress + Redis: AI가 설계한 인프라 적용기 | 발행 |
| 5 | 기술블로그 UX: 코드가 읽히는 블로그 | 발행 |
| 6 | AI 코드 리뷰어가 찾아낸 22개 이슈 | 발행 |
| 7 | 마크다운으로 글 쓰고 자동 발행하기 | 예정 |
| 8 | AI 팀 vs 혼자 코딩: 비용 대비 효과 분석 | 예정 |
이 글은 Claude Code Agent Teams (Research Preview)를 사용하여 작성되었습니다.
프로젝트: yndl.dev