배포 파이프라인에 SEO 감사 넣기: API, 종료 코드, CI 레시피
CI에서 사이트를 감사하는 작동 레시피: 세 개의 REST 엔드포인트, 빌드 게이트가 읽을 수 있는 점수 필드, 실제 회귀와 인프라 블립의 차이.
가장 가시성에 비용이 많이 드는 기술적 회귀는 코드 리뷰에서 보이지 않는다. 잘못된 호스트를 가리키는 canonical 태그, 자기 참조를 잃는 hreflang 블록, reverse-proxy 설정에서 삭제된 Content-Security-Policy 헤더, 하이드레이션 뒤로 콘텐츠를 이동하는 라우트 — 이 모든 것들은 차이(diff)에서 괜찮아 보이고 모든 테스트를 통과하지만 실제로는 문제가 있다. 이들은 몇 주 후, 트래픽 차트에서, 그들을 유발한 커밋 이후 오래 지나서 스크롤이 사라진 뒤에 나타난다. 해결책은 구조적이다: 누군가 기억할 때가 아니라 배포 시 감사를 실행한다. 모든 SEOReport 리포트는 REST을 통해 제공되며, 응답은 숫자 점수 블록을 담고 있고, 셸 스크립트는 그 블록을 종료 코드로 변환할 수 있다. 이것이 전체 메커니즘이다.
기계가 제때 잡아내는 네 가지 회귀 클래스
우리 엔진의 체크는 인간 리뷰에서 살아남는 실패 모드와 깔끔하게 매핑되며, 그것들을 구체적으로 명명할 가치가 있다. 왜냐하면 그것들이 실제로 게이트가 보호하는 것이기 때문이다.
Hreflang. 체크 세트는 자기 참조, 반환 링크, x-default 정확성, 잘 형성된 URL, 각 대체 대상이 색인 가능한지, 대상의 canonical이 일치하는지 여부를 포함한다. CMS 마이그레이션이 URL 패턴을 재작성하면 모든 로케일에서 반환 링크가 동시에 깨질 수 있으며, 개별 로케일에서는 깨진 것처럼 보이지 않는다.
Canonicalization. 존재, 대상 색인 가능성, 리다이렉트 없는 대상, 오프사이트 canonical. 이 실패의 최악 버전은 프로덕션에 배포된 스테이징 canonical이다 — 조용히 인덱싱하고 싶지 않은 호스트를 지명하는 페이지.
보안 헤더. Content-Security-Policy, HSTS, Referrer-Policy, X-Frame-Options, X-Content-Type-Options, Permissions-Policy. 이들은 인프라 구성에 있으며, 애플리케이션 코드가 아니다. 그래서 프록시나 엣지-컨피그 변경 중에 사라지고 아무도 눈치채지 못한다.
Render parity. 모든 감사는 홈페이지를 두 번 가져온다 — 평범한 HTTP, 그 다음 실제 브라우저 — 그리고 타이틀, H1, canonical, 메타 설명, JSON-LD, 본문 텍스트 볼륨을 두 번 비교한다. 우리에서 공개한 render-parity data가 판결에 이르렀을 때, 대부분의 사이트는 HTML을 읽는 모든 것에 물리적으로 더 얇은 페이지를 제공했다. 구성 파일에서 한 개의 ssr: false만으로도 사이트를 그 그룹에 넣을 수 있다.
네 가지 모두 결정론적이며, 네 가지 모두 저렴하게 검사할 수 있고, 네 가지 모두 사람이 이미 의심스러울 때만 검사하는 종류의 것들이다.
세 개의 엔드포인트와 하나의 루프
API이 파이프라인이 필요로 하는 것은 작다. 인증은 베어러 토큰이다: 계정을 만들고, dashboard에서 키를 발급받고, 그것을 Authorization: Bearer sr__live_your_api_key로 보낸다. 같은 키는 REST 및 MCP를 엽니다; 전체 참조는 개발자 페이지에서 확인할 수 있습니다.
보고서를 제출하는 것은 하나의 POST입니다:
JOB_ID=$(curl -sS -X POST https://seoreport.dev/api/v1/reports \-H "Authorization: Bearer $SEOREPORT_API_KEY" \-H "Content-Type: application/json" \-d '{"url": "https://example.com", "forceRerun": true}' \| jq -r '.report.jobId')
CI에서 특히 그 본문에 관한 두 가지 사항.
forceRerun은 API이 사용 가능한 스냅샷을 재사용하기 때문에 존재합니다 — 버튼을 클릭하는 사람에게는 합리적이지만, 배포 게이트에는 부적절하며, 그렇지 않으면 이전 릴리스를 평가하게 됩니다. 응답은 submission.reusedSnapshot에서 어떤 일이 발생했는지 알려줍니다. 강제 새 실행은 유료 계정 기능이며, 해당 권한이 없는 키는 이유를 명시하는 403을 받습니다.
감사 범위는 URL 경로에서 유추됩니다. 베어 오리진은 전체 사이트 감사를 수행하고, 경로가 있는 URL은 해당 페이지를 독립적으로 감시합니다. 따라서 파이프라인은 모든 배포에서 홈페이지를 게이트하고, 변경된 특정 경로를 추가할 수 있으며, 추가 매개변수는 필요 없습니다.
그 다음 폴링. GET /api/v1/reports/:id/ready는 저렴한 상태 엔드포인트입니다 — ready, status, stage, pollAfterMs을 반환하며, 실행이 실패하면 error 객체를 반환합니다:
for _ in $(seq 1 60); doREADY=$(curl -sS -H "Authorization: Bearer $SEOREPORT_API_KEY" \"https://seoreport.dev/api/v1/reports/$JOB_ID/ready")CODE=$(echo "$READY" | jq -r '.error.code // empty')if [ -n "$CODE" ]; thenecho "audit did not complete: $CODE"exit 75fi[ "$(echo "$READY" | jq -r '.ready')" = "true" ] && breaksleep 5done
그 exit 75은 고의적이며, 대부분의 통합이 잘못 이해하는 부분입니다.
회귀와 실제로 실행되지 않은 실행을 구분합니다
error.code 은 기계가 읽을 수 있는 이유와 retryable 부울 값을 담고 있습니다. DNS_FAILURE, CRAWLER_BLOCKED, REDIRECT_LOOP, TLS_ERROR, NO_CONTENT, 그리고 STALE_ENGINE_VERSION 은 재시도를 불가능하게 표시됩니다. 재시도하면 동일한 답을 얻기 때문입니다. 그 목록의 대부분은 사이트에 대한 조건을 설명하며, 리다이렉트 루프, TLS 오류, 이제 크롤러를 차단하는 봇 규칙 등은 실제 배포 결함으로 빌드를 실패시키기에 충분합니다. 그 세트 외의 코드는 일시적이며 다시 시도할 가치가 있습니다.
"사이트가 회귀했다"와 "감사가 실행되지 않았다"를 같은 빨간 빌드로 결합하는 게이트는 한 달 이내에 비활성화됩니다. 종료 코드에서 이들을 구분하세요: 게이트가 강제하도록 요청한 판결에 대해 1, 완전히 판결이 없었던 실행에 대해 75 — 전통적인 EX_TEMPFAIL — 을 사용합니다. 대부분의 CI 시스템은 두 번째 실행을 재시도하고 첫 번째 실행은 사람에게 전달하도록 구성할 수 있습니다.
점수 블록 읽기
ready 가 true 가 되면 GET /api/v1/reports/:id 가 보고서 객체를 반환합니다. score 블록은 게이트가 읽는 부분입니다:
REPORT=$(curl -sS -H "Authorization: Bearer $SEOREPORT_API_KEY" \"https://seoreport.dev/api/v1/reports/$JOB_ID")echo "$REPORT" | jq '.report.score| {overall, totalChecks, passedChecks, failedChecks,warnChecks, inconclusiveChecks, failingCriticalChecks}'
그 필드 중 세 개가 대부분의 신호를 전달합니다.
failingCriticalChecks 는 엔진이 비판적이라고 분류한 실패 수입니다 — 인덱스에서 페이지를 제거하거나 크롤러가 콘텐츠를 완전히 숨길 수 있는 경우입니다. 첫 번째 게이트에서는 이 숫자만 필요하며, > 0 는 첫날에 정당화할 수 있는 임계값입니다.
overall 은 복합 점수이며, 라쳇처럼 사용됩니다: 이전 배포의 값을 저장하고 새 값이 선택한 허용 오차보다 더 떨어지면 실패합니다. 이는 단일 검사에서 표시되지 않는 느린 침식도 포착합니다.
domainScores 은 점수를 seo, ai, performance, security, brand 로 나누며, 각각 자체 pass, fail, warn 카운트를 가집니다. 도메인별 바닥값은 서로 다른 팀이 서로 다른 예산을 소유하도록 하며 — 보안 점수는 엣지 구성을 담당하는 사람에게 의미 있는 게이트이며, 콘텐츠 팀이 배포한 것과는 무관합니다.
inconclusiveChecks 은 자체 규칙이 필요합니다: 절대로 게이트에 사용하지 마세요. 엔진이 정당한 판결에 도달하지 못했을 때 검사 결과가 불확정적이라고 보고하고, 이를 실패로 처리하면 모든 사람이 게이트를 무시하도록 훈련됩니다.
점수 블록은 보고서의 자유형 히어로 섹션에서 가져오므로 빌드 게이트는 전체 결과를 열지 않고도 이를 읽습니다. 전체 페이로드를 보관하려면 GET /api/v1/reports/:id/result 이 잠금 해제된 보고서의 전체 결과를 반환하고, GET /api/v1/reports/:id/download?format=json 은 동일한 객체를 다운로드 가능한 아티팩트로 반환합니다 — 두 배포 간 차이를 나중에 검사할 수 있도록 빌드에 첨부할 가치가 있습니다.
워크플로에 연결하기
위 내용은 CI 공급업체에 특화된 것이 아닙니다. GitHub Actions 에서 전체 게이트는 이미 가지고 있는 스크립트를 호출하는 하나의 단계입니다:
- name: SEO audit gateenv:SEOREPORT_API_KEY: ${{ secrets.SEOREPORT_API_KEY }}AUDIT_URL: https://example.comrun: ./scripts/seo-gate.sh
seo-gate.sh이 제출하고, 투표하고, 결정을 내리는 곳:
CRITICAL=$(echo "$REPORT" | jq -r '.report.score.failingCriticalChecks // 0')SECURITY=$(echo "$REPORT" | jq -r \'.report.score.domainScores[] | select(.domain == "security") | .score')if [ "$CRITICAL" -gt 0 ]; thenecho "::error::$CRITICAL critical checks failing"exit 1fiecho "clean — security domain at $SECURITY"
배포가 끝난 후에 실행하고, 미리보기 환경 대신에 실행합니다. 미리보기 URL은 일반적으로 기본 인증 또는 봇 챌린지 뒤에 있으며, 페이지를 가져올 수 없는 감사는 점수가 아니라 CRAWLER_BLOCKED를 보고합니다. 실제 출처에 배포 후 실행하는 것이 더 간단하고 크롤러가 경험하는 것에 더 가깝습니다.
인접한 두 모양을 아는 것은 가치가 있습니다. 귀하의 오케스트레이션이 이미 스크래핑 플랫폼에 있다면, 우리 Apify 액터는 이 접착제 없이 동일한 엔진을 일정에 따라 실행합니다. 그리고 에이전트의 경우, 동일한 베어러 키가 https://seoreport.dev/mcp에서 MCP 연결을 인증하며, 보고 도구는 connect에서 광고됩니다 — 트래픽 감소를 조사하는 에이전트는 감사를 실행하고 결과를 직접 읽을 수 있으며, 이는 개발자 페이지의 REST 표면과 함께 문서화되어 있습니다.
게이트가 다루지 않는 것
배포 게이트는 한 가지 질문에 답합니다: 이 릴리스가 회귀를 도입했는가. 배포 없이 변경되는 모든 것에 대해 무음입니다 — 만료되는 인증서, 대시보드에서 편집된 CDN 구성, 렌더링을 차단하기 시작하는 서드파티 스크립트, 귀하의 정규화가 충돌하는 것을 변경하는 경쟁사의 마이그레이션. 도메인별 모니터링은 게이트의 항상 켜진 보완이며, 동일한 계정과 동일한 키에서 읽습니다, 개발자 페이지에서 설명한 것처럼.
좁은 버전으로 시작하십시오. 하나의 엔드포인트, 하나의 필드, failingCriticalChecks > 0, 그리고 감사를 전혀 실행할 수 없었을 때의 정직한 exit 75. 연간 두 번 발동하고 두 번 모두 신뢰받는 게이트는 모든 사람이 건너뛰도록 배웠던 포괄적인 게이트보다 더 가치가 있습니다.
사이트 순위 확인하기
실행 가능한 인사이트와 우선 순위 수정을 포함한 무료 AI 기반 SEO 보고서를 받아보세요.
가입 필요 없음.