개발자도 놀랐다: 내 글을 감사하는 로컬 AI 에이전트, 모든 게시물에 '빨간불'을 켜다!
2026. 3. 31.
개발자도 놀랐다: 내 글을 감사하는 로컬 AI 에이전트, 모든 게시물에 '빨간불'을 켜다!
혹시나 했지만 역시나였다. 내 글들을 향한 AI 에이전트의 심사는 가차 없었다. 7개 URL 모두 '실패' 판정. 맙소사.
Hashnode 프로필에는 H1 태그가 통째로 빠져 있었고, freeCodeCamp 튜토리얼 3개는 메타 설명이 없거나 160자를 훌쩍 넘겼다. DEV.to에 올린 글 두 편은 구글 검색 결과에 깔끔하게 표시하기엔 제목이 너무 길었다.
이 에이전트, 누가 만들었냐고? 바로 나다. 그리고 가장 먼저 내 글들에 돌려봤다. 이게 데모의 가장 솔직한 버전 아닌가. 사실, 저도 개발한 툴을 처음엔 제 콘텐츠에 적용해보면서 심장이 쫄깃했는데, 이런 결과를 마주하니 더 냉철하게 개선점을 찾게 되더라고요.
제가 실제로 풀고 싶었던 문제
디지털 마케팅 에이전시라면 어디든 이런 작업을 하는 사람이 있을 거다. 스프레드시트를 열고, 고객사 URL을 하나씩 방문해서 제목 태그, 설명, H1 태그를 확인하고, 깨진 링크는 없는지 일일이 점검한 다음, 이 모든 내용을 보고서에 붙여넣는다. 매주 반복되는 지루한 루틴이다.
이런 일을 담당하는 인력은 당연히 인건비가 든다. 게다가 이 작업은 규칙적이고 반복적이다. 여전히 수동으로 이루어지는 유일한 이유는 그 대안을 아무도 만들지 않았기 때문이다.
저는 이 대안을 주말 동안 만들어냈다. 실무에서 이런 단순 반복 작업에 투입되는 시간을 볼 때마다 '이건 무조건 자동화해야 한다'는 강한 충동을 느꼈는데, 비즈니스 로직과 기술 스택이 딱 맞아떨어져 주말에 시도해볼만 하더라고요.
선택된 기술 스택
그렇다면 이 자동화된 심사 에이전트는 어떤 기술 스택 위에 올라섰을까?
- 브라우저 자동화 (Python-native): 단순히 헤드리스 스크레이퍼가 아니다. 가시적인 Chromium 창에서 실제 페이지를 탐색한다. 사람이 보는 것과 동일한 페이지를 렌더링하고, 세션을 유지하며 실제 사용자 경험을 모방한다.
- Claude API (Sonnet): 페이지 스냅샷을 읽고 구조화된 JSON을 반환하는 핵심 브레인이다. 제목 상태, 설명 상태, H1 개수, 캐노니컬 태그, 그리고 문제가 되는 플래그까지. URL당 단 한 번의 API 호출로 모든 정보를 얻는다.
- httpx: 비동기 HEAD 요청을 사용하여 깨진 링크를 감지한다. 페이지당 최대 50개의 링크를 동시 처리하며, 각 요청은 5초 타임아웃으로 제한되어 있다. 빠르고 효율적이다.
- Flat JSON 파일:
state.json파일 하나로 감사 진행 상황을 추적한다. 중간에 실행을 중단해도 정확히 멈춘 지점부터 다시 시작할 수 있다. 복잡한 데이터베이스는 필요 없다.
총 7개의 파이썬 파일, 전체 코드 라인은 956줄. 그저 평범한 윈도우 랩톱에서 문제없이 구동된다. 복잡한 인프라 대신 state.json으로 상태를 관리한 건 개발 기간을 단축하는 데 큰 역할을 했어요. 특히 로컬 에이전트 프로젝트에서는 DB 셋업에 시간을 낭비하는 것보다 핵심 로직 구현에 집중하는 편이 훨씬 효율적이라고 봅니다.
대부분의 튜토리얼이 놓치는 부분: 인간 개입 (HITL)
자동화 에이전트가 로그인 페이지를 만나 벽에 부딪힌다. 예외를 뱉어내고, 실행은 그대로 멈춘다. 많은 자동화 튜토리얼에서 간과하는 현실적인 시나리오다.
하지만 제가 만든 에이전트는 그렇게 허무하게 멈추지 않는다.
에이전트가 200 이외의 HTTP 상태 코드, 로그인 페이지로의 리다이렉션, 또는 제목에 '로그인'이나 '접근 거부'와 같은 문구가 포함된 페이지를 감지하면, 잠시 멈춘다. 대화형(interactive) 모드에서는 '건너뛰기', '재시도', '종료' 옵션을 제공한다. --auto 모드에서는 자동으로 해당 URL을 건너뛰고 state 파일 내 needs_human[] 목록에 기록한 다음, 다음 작업으로 넘어간다.
자신의 한계를 아는 에이전트가 조용히 실패하는 에이전트보다 훨씬 유용하다. 이건 튜토리얼에서 잘 다루지 않기 때문에 대부분의 개발자들이 놓치는 중요한 설계 결정이다. 수년간 자동화 스크립트를 짜면서 가장 골치 아팠던 게 바로 이런 예상치 못한 예외 처리였어요. 그냥 뻗어버리면 처음부터 다시 돌려야 하니, 결국 사람의 개입이 필요하다는 전제로 설계하는 게 훨씬 실용적이라는 걸 깨달았습니다.
실제로 에이전트가 찾아낸 것들
제가 발행한 콘텐츠를 세 가지 플랫폼에 걸쳐 감사한 결과는 다음과 같습니다.
| URL | 실패 항목 |
|---|---|
| hashnode.com/@dannwaneri | H1 누락 |
| freeCodeCamp — how-to-build-your-own-claude-code-skill | 메타 설명 |
| freeCodeCamp — how-to-stop-letting-ai-agents-guess | 메타 설명 |
| freeCodeCamp — build-a-production-rag-system | 제목 + 메타 설명 |
| freeCodeCamp — author/dannwaneri | 메타 설명 |
| dev.to — the-gatekeeping-panic | 제목 너무 김 |
| dev.to — i-built-a-production-rag-system | 제목 너무 김 |
freeCodeCamp의 설명 문제는 부분적으로 플랫폼 자체의 영향도 있다. freeCodeCamp가 템플릿을 제어하고 메타 설명을 잘라내거나 아예 생략하는 경우가 있기 때문이다. 하지만 DEV.to의 제목 문제는 전적으로 나의 실수였다. 헤드라인으로는 멋지게 들리는 글 제목들이 <title> 태그에서는 종종 60자를 초과하곤 한다.
에이전트는 이런 사정을 봐주지 않았다. 그저 정해진 기준을 확인하고 결과를 보고할 뿐이었다. 개발자로서 저도 종종 플랫폼의 제약 때문에 원하는 대로 콘텐츠를 최적화하지 못할 때가 있어요. 하지만 그렇다고 표준을 무시할 수는 없죠. AI는 그런 인간적인 변수를 고려하지 않고 오직 데이터로만 말한다는 걸 다시 한번 느꼈습니다.
스케줄링을 통한 자동화: 매주 월요일 아침을 위한 설정
python index.py --auto
이 명령어 하나면 모든 것이 시작된다. API 키를 설정하는 .bat 파일을 추가하고, 윈도우 작업 스케줄러에 매주 월요일 오전 7시로 예약하면 끝이다. 출근해서 따뜻한 커피 한 잔과 함께 report-summary.txt 파일을 확인하면 된다.
이것이 바로 에이전시의 이상적인 워크플로우다. 더 이상 일일이 신경 쓸 필요가 없다. needs_human[]에 기록된 예외적인 케이스만 사람이 직접 검토하고, 나머지는 모두 자동으로 처리되고 보고된다. 개인적으로 저는 이렇게 반복되는 작업을 한 번 자동화해두면, 마치 나를 위한 작은 AI 직원이 생긴 것처럼 느껴져요. 매주 월요일 아침, 그 보고서를 볼 때의 뿌듯함이란!
이 에이전트, 실제 비용은 얼마나 들까?
URL당 Sonnet API 호출은 단 한 번. 페이지당 약 0.002달러 정도다. 20개 URL을 매주 감사한다고 해도 비용은 0.05달러(약 60원) 미만이다. Playwright 브라우저는 로컬에서 실행되므로, 클라우드 브라우저 비용이나 별도 구독료도 들지 않는다.
이 모든 시스템은 월 5달러 미만이라는 제 철학 아래 구축되었다. 다른 개인 프로젝트들에도 늘 적용하는 원칙이기도 하다. 저는 늘 '쓸데없이 비싼 솔루션은 피하자'는 주의라서, 이런 로컬 기반의 저비용 자동화 솔루션이야말로 진정한 생산성 혁신이라고 생각합니다.
코드 공개: 직접 사용해보세요!
전체 코드는 제 GitHub 저장소에 공개되어 있습니다.
GitHub: dannwaneri/seo-agent
사용법도 간단합니다. 저장소를 클론한 다음, input.csv 파일에 감사하고 싶은 URL들을 추가하고, 환경 변수에 ANTHROPIC_API_KEY를 설정해주세요. 이어서 pip install -r requirements.txt와 playwright install chromium을 실행한 후, python index.py를 실행하면 바로 작동합니다.
freeCodeCamp 튜토리얼에서는 브라우저 통합, Claude 추출 프롬프트, 비동기 링크 체커, 그리고 HITL 로직 등 각 모듈에 대한 상세한 설명을 다룰 예정입니다. 튜토리얼이 공개되면 댓글로 링크를 공유하겠습니다. 우선은 코드를 직접 확인해보세요! 직접 코드를 뜯어보면 제가 어떤 고민을 했는지, 그리고 어떻게 문제를 해결했는지 더 명확하게 이해하실 수 있을 겁니다. 언제든 궁금한 점은 질문 남겨주세요.
진정한 패러다임의 전환: 셀렉터에서 프롬프트로
브라우저 자동화는 지난 10년간 개발자들의 중요한 도구였다. Playwright, Selenium, Puppeteer 모두 강력했지만, 공통적으로 셀렉터를 작성하고 끊임없이 유지보수해야 하는 숙제를 안고 있었다. 버튼의 클래스 이름 하나만 바뀌어도 스크립트 전체가 망가지는 일이 다반사였다.
하지만 이 에이전트는 셀렉터를 사용하지 않는다. Claude가 페이지를 읽는 방식과 동일하게, 즉 접근성 트리를 통해 의미론적으로 페이지를 이해한다. CSS 클래스가 바뀌어도 '제출' 버튼은 여전히 '제출' 버튼으로 인식되는 식이다.
결국 추출 로직은 코드 내부가 아니라 프롬프트 안에 담겨 있다.
과거 방식: 페이지가 변경되면 자동화 스크립트가 멈춘다. 새로운 방식: AI의 추론 능력이 스스로 적응한다. 코드를 수정할 필요가 없다.
이것이 바로 진정한 변화의 핵심이다. 단순히 'AI가 일을 한다'는 의미를 넘어, '취약성이 이동했다'는 데에 주목해야 한다. 셀렉터의 취약성이 프롬프트로 옮겨갔고, 유지보수의 부담이 AI의 추론 능력으로 대체된 것이다. 실패 모드도 달라졌고, 복구 방식 또한 진화했다. 저 역시 셀렉터 문제로 야근한 적이 한두 번이 아닌데요. 이제는 페이지 구조가 바뀌어도 프롬프트만 잘 짜면 AI가 알아서 해석해주니, 개발 생산성이 엄청나게 향상된 기분입니다. 말 그대로 '게임 체인저' 같아요.
이 프로젝트는 에이전시 운영을 위한 실용적인 로컬 AI 에이전트 구축 시리즈의 첫 번째 결과물이다. freeCodeCamp 스텝 바이 스텝 튜토리얼은 곧 공개될 예정이니 많은 기대 바란다. 현재 리포지토리는 공개되어 있으니 지금 바로 확인해보시길!
원문: https://dev.to/dannwaneri/i-built-a-local-ai-agent-that-audits-my-own-articles-it-flagged-every-single-one-pkh 수집일: 2026-03-31 05:57:10