트러블슈팅

  • 대표 이미지가 잘리는 이유, 템플릿 비율 3:2→16:9 차이

    대표 이미지가 잘리는 이유, 템플릿 비율 3:2→16:9 차이

    이미지가 잘린다는 제보를 받았다. 대표 이미지에 넣은 ‘AgentLog’ 로고 텍스트가 앞글자 ‘A’만 잘려서 ‘gentLog’처럼 보인다는 캡처였다.

    내 화면에서는 멀쩡했다. 데스크탑도, 모바일 에뮬레이션(브라우저에서 개발자 도구로 흉내 내는 모바일 화면)도 전부 정상이었다. 그래서 처음엔 캐시(cache, 웹사이트 속도를 높이려고 이전 화면을 임시 저장해두는 것) 문제라고 생각했다.

    아니었다.

    같은 이미지인데 왜 어디서는 잘릴까?

    이미지 자체의 문제가 아니었다. 소스 이미지는 1200×675픽셀, 정확히 16:9 비율로 만들었다. 문제는 그 이미지를 감싸는 HTML 박스의 비율이 페이지마다 달랐다는 것이다.

    블로그 홈 카드(목록 화면에서 글을 미리 보여주는 카드형 UI)에서는 이미지 박스가 16:9였다. 그런데 글 상세 페이지의 대표 이미지 블록(block, 워드프레스에서 콘텐츠를 구성하는 단위)은 3:2였다.

    object-fit: cover는 이미지를 박스에 꽉 채우되, 비율이 안 맞으면 삐져나온 부분을 잘라낸다. 16:9 이미지를 3:2 박스에 넣으면 가로가 남는다. 남은 부분이 양옆에서 잘린다. 그래서 로고 텍스트의 왼쪽이 사라진 것이다.

    CSS만 보고 “object-fit: cover면 다 똑같이 나오겠지” 하고 넘어갔으면 계속 몰랐을 문제다. 같은 이미지라도 어느 템플릿(template, 페이지 구조를 정해놓은 틀)에서 렌더링(rendering, 코드를 실제 화면으로 그려내는 것)되느냐에 따라 잘리는 방식이 완전히 달라진다.

    curl로 실제 코드를 확인해보기, 원인은 HTML에 있었다

    눈으로 확인이 안 되니까 curl(curl, 터미널에서 웹 주소로 요청을 보내 응답을 받아보는 도구)로 라이브 페이지의 실제 HTML을 직접 떠봤다.

    홈 카드에서 뽑은 <img> 태그:

    style="aspect-ratio:16/9"

    글 상세 페이지에서 뽑은 <img> 태그:

    style="aspect-ratio:3/2"

    숫자가 달랐다. 홈 카드용 CSS는 직접 16:9로 맞춰놨는데, 글 상세 페이지는 워드프레스 테마 템플릿 자체의 대표 이미지 블록 설정이 3:2로 고정돼 있었다.

    대표 이미지가 자꾸 잘려 보인 이유 — 템플릿마다 다른 비율(3:2 vs 16:9) 스크린샷 1

    위 캡처가 그 차이를 그대로 보여준다. 같은 이미지, 다른 숫자 하나.

    원인은 명확했다. 이제 고치면 됐다.

    워드프레스 템플릿을 REST API로 수정하기

    보통은 사이트 에디터(Site Editor, 워드프레스 관리자 화면에서 페이지 구조를 시각적으로 편집하는 도구) UI에 들어가서 블록을 클릭하고 비율 드롭다운을 바꾼다. 몇 번 클릭하면 끝나는 일이다.

    그런데 워드프레스 최신 버전은 이 템플릿을 REST API(REST API, 웹에서 데이터를 주고받는 표준 방식. 주소에 요청을 보내면 결과가 돌아온다)로도 읽고 쓸 수 있다. 주소는 이렇다:

    /wp-json/wp/v2/templates/{id}

    이 엔드포인트의 정식 스펙은 워드프레스 공식 REST API Handbook에 나와 있다. GET 요청으로 템플릿 원본 콘텐츠를 읽어오면, 안에 이런 블록 설정이 문자열로 들어있다:

    <!-- wp:post-featured-image {"aspectRatio":"3/2"} /-->

    이 부분을 "aspectRatio":"16/9"로 바꾸고, POST 요청으로 다시 보내면 끝이다. UI를 열고 찾고 클릭하는 것보다 빠르다. 실수할 여지도 적다. 바꿀 문자열이 정확히 무엇인지 보이니까.

    API 인증은 워드프레스 애플리케이션 비밀번호(Application Password, 관리자 화면 사용자 설정에서 발급하는 API 전용 비밀번호)를 쓰면 된다. curl에 -u 유저명:앱비밀번호를 붙이면 된다.

    캐시가 삭제 안 될 때, save_post 훅으로 우회하기

    템플릿은 고쳤다. 그런데 반영이 안 됐다.

    이전에도 다뤘던 라이트스피드 캐시가 예전 3:2 버전 HTML을 계속 들고 있었다. 원래라면 관리자 화면 상단바의 ‘전체 캐시 삭제’ 버튼을 누르면 된다. 그런데 브라우저 자동화 도구가 그 시점에 완전히 죽어있었다. 관리자 화면 자체에 들어갈 수가 없었다. 몇 번을 재시도해도 ‘browser closed’ 에러만 떴다.

    이건 좀 웃겼다. 템플릿은 API로 고쳐놨는데 캐시 하나 못 지워서 막힌 상황이었다.

    라이트스피드 REST API에 캐시 퍼지 전용 엔드포인트가 있는지 먼저 찾아봤다. 없었다.

    대신 워드프레스의 기본 동작을 이용했다. 글을 REST API로 다시 저장하면 , 실질적인 내용 변경 없이, status 값을 그대로 재전송해서 저장만 트리거하면 , 워드프레스의 save_post 훅이 실행된다. 라이트스피드는 이 훅에 연결돼 있어서, 훅이 실행되면 해당 글의 캐시를 자동으로 비운다.

    발행된 글 8개, 예약된 글 6개. 총 14개를 이 방식으로 한 번씩 재저장시켰다.

    캐시가 실제로 비워졌는지는 응답 헤더로 확인했다. curl에 -I 옵션을 붙이면 헤더만 볼 수 있다. x-litespeed-cache: miss가 뜨면 캐시 없이 원본 서버에서 응답이 온 것이다.

    대표 이미지가 자꾸 잘려 보인 이유 ,  템플릿마다 다른 비율(3:2 vs 16:9) 스크린샷 2

    miss가 확인된 다음에야 진짜 반영된 걸 믿었다.

    초보자도 활용할 수 있는 API 우회법

    UI가 막혔을 때 바로 포기하지 마라. 워드프레스는 REST API로 할 수 있는 일이 생각보다 많다.

    • 템플릿 읽기·쓰기: GET/POST /wp-json/wp/v2/templates/{id}
    • 글 저장 트리거: POST /wp-json/wp/v2/posts/{id} , 바디에 {"status":"publish"}만 넣어도 된다
    • 캐시 반영 확인: curl -I로 x-litespeed-cache 헤더 값을 본다

    인증은 반드시 애플리케이션 비밀번호를 써야 한다. 관리자 계정 비밀번호를 API에 직접 쓰지 마라. 관리자 화면 → 사용자 → 프로필 → 애플리케이션 비밀번호 항목에서 발급하면 된다.

    그리고 save_post 훅 방식은 캐시를 지우는 게 목적이지, 글 내용을 바꾸는 게 아니다. 실수로 status를 draft로 보내면 발행된 글이 비공개로 바뀐다. 요청 바디를 보내기 전에 현재 status 값을 GET으로 먼저 읽어야 한다. 당연한 말이지만 한 번은 짚고 넘어가야 한다.

    예전에 홈페이지 메타 설명이 반영 안 됐던 문제도 비슷했다 , 설정 화면에 값이 있다고 실제로 쓰이는 건 아니었다.

    이번 문제는 솔직히 이미지 생성 코드가 아니라 템플릿 설정을 끝까지 확인하지 않은 데서 생겼다. 홈 카드 CSS는 직접 썼으면서, 글 상세 페이지 템플릿 설정은 기본값을 그냥 믿었다.

    다음에 이미지 비율을 다루는 기능을 만들면, 렌더링되는 페이지 전부의 템플릿 설정을 먼저 확인하고 시작할 것이다.

    같은 워드프레스 주제로 이어서 읽으면 좋은 글: WPCode로 보안 헤더 추가하다 코드가 깨진 이유, 이미지가 삐져나가는 버그, 원인 찾고 자동화까지 한 후기, 워드프레스 SEO 플러그인 충돌 피하기 , 켜야 할 것, 꺼야 할 것.

  • 워드프레스 SEO 버그 5개, curl로 찾은 공통 원인

    워드프레스 SEO 버그 5개, curl로 찾은 공통 원인

    블로그에 글이 15개쯤 쌓였을 때 돌아봤다. 그중 5개가 전부 워드프레스 SEO 설정을 자동화하거나 고치다가 만난 버그 이야기였다. 흩어져 있으니까 불편했다. 나중에 비슷한 문제를 다시 만났을 때 어느 글을 찾아야 할지 헷갈렸다. 그래서 한 페이지에 몰아서 정리하기로 했다.

    설정을 저장했는데도 작동하지 않은 이유

    다섯 개를 나란히 놓고 보니까 패턴이 보였다. 전부 같은 이야기였다.

    ‘설정 화면에 값이 있다고 해서 실제로 그게 적용되고 있다는 보장은 없다.’

    WPCode에서는 코드를 저장했는데 실제로는 깨진 채로 배포됐다. 랭크매스에서는 홈페이지 메타 설명을 입력해도 워드프레스 읽기 설정 때문에 그 값이 조용히 무시됐다. REST API(워드프레스에 데이터를 보내고 받는 통로)로 포커스 키워드를 보내도 저장이 안 되는 경우도 여러 번 있었다.

    관리자 화면의 저장 성공 메시지, REST API의 200 응답, 설정 페이지에 입력된 값. 이런 것들은 전부 ‘내가 뭔가를 입력했다’는 증거일 뿐이다. ‘그게 실제로 작동하고 있다’는 증거가 아니다.

    아래 다섯 개가 그 증거다.

    버그 1: 랭크매스 점수가 재계산되지 않는 이유 (16점→76점의 함정)

    랭크매스(워드프레스용 SEO 플러그인)가 매기는 SEO 점수가 16점이었다. 뭘 고쳐야 할지 몰랐다. 점수만 보면 아무것도 알 수 없었다.

    처음에는 REST API로 점수를 강제로 재계산시키려고 했다. 여기서 함정에 빠질 뻔했다. API 응답은 200으로 떴다. 성공처럼 보였다. 그런데 실제 점수는 그대로였다.

    원인은 단순했다. 랭크매스 SEO 점수는 wp-admin(워드프레스 관리자 에디터 화면)을 직접 열어야 제대로 계산된다. API로 우회하면 점수가 갱신되지 않는다. 에디터를 열고 나서야 점수가 76점으로 올라갔다.

    이 경험에서 배운 것은 하나다. API 응답이 성공이어도 실제 결과를 화면에서 직접 확인해야 한다. 200은 ‘요청이 도착했다’는 뜻이지 ‘원하는 대로 됐다’는 뜻이 아니다.

    → 전체 진단 과정: 랭크매스 SEO 16점→76점, API 함정 피하고 올린 과정

    버그 2: WPCode 보안 헤더가 깨지는 현상 (저장은 됐는데 적용 안 됨)

    WPCode(워드프레스에 코드 조각을 추가하는 플러그인)로 보안 헤더(Security Header, 브라우저에 보안 정책을 전달하는 HTTP 응답값)를 추가했다. PHP 코드 스니펫(snippet, 짧은 코드 조각)을 넣고 저장했다. 저장 성공 메시지가 떴다.

    그런데 실제로는 헤더가 적용되지 않고 있었다.

    curl(터미널에서 웹 페이지 응답을 직접 확인하는 명령어)로 라이브 페이지 응답 헤더를 확인하고 나서야 알았다. 보안 헤더가 없었다. 원인은 사소한 문법 오류였다. PHP 코드 안에 오타가 있었고, 그 오류 때문에 코드 전체가 실행되지 않았다.

    저장 성공 메시지만 보고 넘어갔으면 계속 몰랐을 거다. WPCode는 코드 내용의 오류를 검증하지 않는다. 저장 자체는 항상 성공한다. 그래서 더 위험하다.

    보안 설정을 추가한 뒤에는 반드시 curl로 응답 헤더를 직접 확인해야 한다. 저장 성공 메시지를 믿지 마라.

    curl -I https://내-사이트-주소.com

    위 명령어를 터미널에 입력하면 응답 헤더 목록이 나온다. 추가한 헤더 이름이 거기 있어야 진짜 적용된 거다.

    → 전체 진단 과정: WPCode로 보안 헤더 추가하다 코드가 깨진 이유

    버그 3~4: fire-your-seo-agency와 AI Link Genius로 만난 예상 밖의 문제들

    fire-your-seo-agency는 Claude Code에서 쓸 수 있는 스킬(skill, AI에게 특정 작업 방식을 지정하는 설정)이다. 이걸로 블로그 4개를 한꺼번에 SEO 점검했다.

    중간에 파일이 세 번 중복으로 받아지는 해프닝이 있었다. 이건 좀 웃겼다. 그래도 생각보다 빠르게 끝났다. 스킬 하나로 블로그 4개를 동시에 점검한다는 게 실제로 되는 일이라는 걸 이때 처음 확인했다.

    → 전체 진단 과정: fire-your-seo-agency 스킬로 4개 블로그 자동 SEO 최적화한 후기

    네 번째 버그는 AI Link Genius 이야기다. AI Link Genius는 랭크매스 안에 있는 내부 링크 분석 기능이다. 설치는 해놨는데 한 번도 안 써봤다. 어느 날 다시 살펴보다가 고아 포스트(Orphan Post, 다른 글에서 링크를 하나도 받지 못한 글)가 2개 있다는 걸 발견했다.

    그 글들은 검색 엔진이 찾아오기 어려운 상태였다. 내부 링크를 걸어주고 나서야 제대로 연결됐다.

    → 전체 진단 과정: 랭크매스 무료 기능으로 고아 포스트 2개 찾아낸 이야기

    이 두 버그에서 공통으로 배운 게 있다. 설치는 해놨지만 한 번도 안 써본 플러그인 기능이 있는지 주기적으로 점검해야 한다. 있는 기능을 모르고 있으면 없는 거나 마찬가지다.

    버그 5: 메타 설명이 검색엔진에 반영 안 되는 이유 (읽기 설정의 함정)

    홈페이지가 색인됐는데 메타 설명이 이상했다. 랭크매스에 분명히 입력해뒀는데, 검색 결과에 다른 문구가 나왔다.

    ‘색인 = 노출’이라고 착각하고 있었다. 아니었다. 색인됐어도 메타 설명이 틀리면 검색 결과가 이상하게 보인다.

    원인은 워드프레스 읽기 설정이었다.

    워드프레스 관리자 화면 → 설정 → 읽기 에서 홈페이지 표시가 ‘최신 글’로 설정되어 있으면, 랭크매스에 입력한 홈페이지 메타 설명이 무시된다. 대신 워드프레스 기본 태그라인이 메타 설명 자리에 들어간다.

    랭크매스 설정 화면에는 분명히 내가 쓴 문구가 있었다. 그런데 실제 HTML에는 태그라인이 들어가 있었다. curl로 확인하기 전까지 몰랐다.

    curl -s https://내-사이트-주소.com | grep -i "meta name=\"description\""

    위 명령어로 실제 HTML에 박힌 메타 설명을 확인할 수 있다. 설정 화면에 뭐가 적혀 있든 상관없다. 이 결과가 진짜다.

    홈페이지 메타 설명을 제대로 쓰려면 읽기 설정에서 ‘정적 페이지’를 선택하고 홈페이지를 지정해야 한다. 그래야 랭크매스가 입력한 값을 실제로 가져다 쓴다.

    → 전체 진단 과정: 메타 설명 오류 — 색인됐는데 검색 안 되던 이유

    다음 버그를 빨리 찾는 4가지 확인 순서 (curl 포함)

    다섯 번을 겪고 나서 확인 순서가 생겼다. 비슷한 문제를 만나면 이 순서로 본다.

    • 첫째, 설정을 저장한 뒤 바로 curl로 라이브 페이지를 확인한다. 저장 성공 메시지는 신뢰하지 않는다. curl -s 주소 | grep 확인할내용 으로 실제 HTML에 반영됐는지 바로 본다.
    • 둘째, REST API 응답이 200이어도 응답 바디를 다시 읽는다. 200은 요청이 도착했다는 뜻이다. 원하는 처리가 됐다는 뜻이 아니다. 응답 안에 실제로 뭐가 담겨 있는지 확인해야 한다.
    • 셋째, 설정 화면 말고 ‘진짜 소스’가 따로 있는지 의심한다. 워드프레스는 표면 설정 화면 뒤에 그 값을 실제로 가져다 쓰는 다른 설정이 있을 수 있다. 읽기 설정과 태그라인이 그 예다. 플러그인 설정만 보면 안 된다.
    • 넷째, 설치는 해놨지만 한 번도 안 써본 플러그인 기능을 주기적으로 점검한다. AI Link Genius처럼, 있는 기능인지 모르고 넘어간 것들이 반드시 있다.

    이 네 가지는 순서대로 해야 빠르다. 첫째를 건너뛰고 셋째부터 보다가 시간을 날린 적이 있다. 순서를 지켜라.

    지금은 5개지만, 앞으로 비슷한 버그를 만날 때마다 이 글에 추가할 생각이다. 워드프레스 SEO 설정을 직접 만지다가 막히는 사람에게 이 페이지가 첫 번째 참고 지점이 됐으면 한다. 경험이 쌓일수록 이 목록도 길어질 거다.

    같은 워드프레스 주제로 이어서 읽으면 좋은 글: 대표 이미지가 잘리는 이유 , 템플릿 비율 3:2→16:9 차이, 이미지가 삐져나가는 버그, 원인 찾고 자동화까지 한 후기, 워드프레스 SEO 플러그인 충돌 피하기 , 켜야 할 것, 꺼야 할 것.

  • 메타 설명 오류로 색인됐는데 검색 안 되던 이유

    메타 설명 오류로 색인됐는데 검색 안 되던 이유

    구글 서치 콘솔(Google Search Console, 구글이 제공하는 사이트 검색 현황 분석 도구)을 열어서 색인(index, 구글이 내 페이지를 검색 후보 목록에 등록한 상태) 생성 현황을 보다가 이런 생각이 들었다. 색인이 다 된다는 건 다 노출되고 있다는 뜻 아닌가? 그리고 한 발 더 나아가서 — 색인이 됐다는 건 구글이 내 글을 좋다고 판단했다는 뜻 아닌가?

    둘 다 틀렸다. 그리고 이 착각의 끝에는 홈페이지 메타 설명이 몇 달째 방치돼 있던 진짜 문제가 있었다.

    색인된 글이 검색에 안 나오는 이유, 세 가지 다른 개념

    Site Kit(워드프레스에서 구글 서치 콘솔 데이터를 바로 볼 수 있게 해주는 플러그인)으로 실제 수치를 확인해봤다. 최근 28일 노출수(impressions, 검색 결과 화면에 내 링크가 등장한 횟수)가 4. 클릭이 1.

    색인은 분명히 되고 있었다. 그런데 실제로 검색에 걸리는 경우가 거의 없었다.

    색인이 됐다고 노출되는 게 아니었다 ,  홈페이지 메타 설명 방치했던 이유 스크린샷 1

    위 수치가 현실이다. 색인됐다고 노출되는 게 아니다.

    이 세 개념은 완전히 별개다.

    • 색인(Index) , 구글이 내 페이지를 검색 후보 명단에 올린 것. 스팸이 아니고, 중복이 아니고, 내용이 너무 빈약하지 않으면 통과한다. 낮은 문턱이다.
    • 노출(Impressions) , 실제 검색 결과 화면에 내 링크가 뜬 횟수. 색인됐다고 자동으로 노출되지 않는다. 검색어와의 관련도, 경쟁 페이지, 메타 설명 품질 등 여러 요소가 관여한다.
    • 품질 판단 , 구글이 내 글을 “좋다”고 판단했다는 뜻이 아니다. 색인은 그냥 최소한의 통과 기준을 넘겼다는 신호일 뿐이다.

    색인됐다는 알림에 안심하고 있었다면, 그 안심은 근거 없는 거다.

    내 홈페이지 메타 설명이 실제로 적용되지 않는 이유

    노출을 높일 방법을 찾으려고 fire-your-seo-agency라는 스킬을 실행했다. 이 스킬은 curl(터미널에서 웹페이지 내용을 직접 가져오는 명령어)로 사이트를 진단한다. noindex(검색엔진에 이 페이지를 색인하지 말라고 지시하는 태그) 오류, robots.txt(검색 로봇의 접근을 제어하는 파일) 차단, 사이트맵, 404 처리 같은 기본 항목들을 순서대로 훑는다.

    대부분 정상이었다. 딱 하나가 걸렸다.

    홈페이지 메타 설명(meta description, 검색 결과에서 제목 아래 나오는 짧은 소개 문구)이 19자짜리 태그라인으로만 채워져 있었다. 개별 글들은 전부 150자 안팎으로 잘 돼 있었다. 홈페이지만 방치돼 있었던 거다.

    색인이 됐다고 노출되는 게 아니었다 ,  홈페이지 메타 설명 방치했던 이유 스크린샷 2

    랭크매스 설정 화면에서 홈페이지 메타 설명을 확인했다. 값이 저장돼 있었다. 분명히 입력한 기억도 있었다.

    그런데 실제 라이브 페이지 HTML을 열어보면 엉뚱한 값이 나오고 있었다. 19자짜리 태그라인이.

    워드프레스 ‘최신 글’ 설정이 메타 설명을 방해하는 원리

    원인은 워드프레스 ‘읽기’ 설정에 있었다. 홈페이지 표시가 ‘최신 글’로 돼 있었던 거다.

    워드프레스는 홈페이지가 어떤 타입인지에 따라 메타 설명을 다른 소스에서 가져온다.

    홈페이지 설정 메타 설명 소스
    정적 페이지 랭크매스 홈페이지 탭에 입력한 값
    최신 글 워드프레스 기본 태그라인 필드

    ‘최신 글’ 상태에서는 랭크매스 홈페이지 탭에 아무리 공들여 메타 설명을 써도 실제 페이지에 적용이 안 된다. 워드프레스가 폴백으로 태그라인을 그냥 가져다 쓴다.

    설정 화면에는 분명히 값이 저장돼 있다. 그런데 그 값이 실제로 쓰이지 않는다. 이건 꽤 교묘한 함정이다 , 예전에 API로 값을 보내도 실제로 반영 안 됐던 경우랑 같은 종류의 함정이다.

    해결 방법은 두 가지다. 홈페이지를 정적 페이지로 바꾸거나, 태그라인 자체를 제대로 된 메타 설명 문구로 교체하거나. 이번엔 태그라인을 140자 안팎의 제대로 된 문구로 직접 고쳐서 해결했다.

    설정 화면에만 있고 라이브 페이지에는 없는 걸 찾는 법

    설정 화면을 믿지 마라. 라이브 페이지의 HTML을 직접 확인해야 한다.

    터미널에서 이 명령어 하나면 된다.

    curl -s https://내사이트주소.com | grep -i "meta name=\"description\""

    curl은 브라우저 없이 페이지 소스를 그대로 가져온다. 브라우저 캐시나 플러그인 미리보기가 보여주는 가짜 결과가 없다. 실제 서버가 내보내는 HTML이 그대로 나온다.

    출력 결과에서 content="" 안의 값을 확인한다. 내가 원하는 문구가 아니라 다른 게 나온다면 , 설정이 어딘가 어긋나 있는 거다.

    색인이 됐다고 노출되는 게 아니었다 ,  홈페이지 메타 설명 방치했던 이유 스크린샷 3

    수정 전후를 이렇게 직접 눈으로 비교할 수 있다. 설정 화면 저장 버튼만 누르고 끝냈다면 이 차이를 알 수 없었을 거다.

    확인 후에는 반드시 캐시를 퍼지해야 한다. 라이트스피드 캐시 같은 캐싱 플러그인을 쓰고 있다면, 캐시를 지우기 전까지는 curl 결과도 이전 버전을 보여줄 수 있다. 캐시 퍼지 → curl 재확인 순서로 해야 한다.

    그리고 llms.txt도 같이 점검했는데, 최근에 올린 글 3개가 빠진 구버전이었다. WPCode(워드프레스에 코드 스니펫을 추가하는 플러그인) 스니펫을 직접 열어서 누락된 글들을 추가했다. 이것도 설정 화면 어딘가에 자동으로 반영되는 게 아니라, 직접 파일을 열어서 고쳐야 한다.

    메타 설명 수정 후 검색 결과에 반영되는지 확인하기

    라이브 페이지 HTML에서 원하는 문구가 나오는 걸 확인했다. 그렇다고 구글 검색 결과에 바로 반영되지는 않는다.

    구글이 해당 페이지를 다시 크롤링해야 검색 결과의 설명 문구가 바뀐다. 빠르면 며칠, 늦으면 몇 주 걸린다.

    기다리는 동안 할 수 있는 건 두 가지다.

    • 구글 서치 콘솔에서 해당 URL을 직접 검사 요청해서 재크롤링을 요청한다.
    • site: 검색(site:내사이트주소.com을 구글 검색창에 입력)으로 현재 구글이 표시하는 설명 문구가 뭔지 주기적으로 확인한다.

    주의할 점이 하나 있다. 구글이 항상 내가 작성한 메타 설명을 그대로 쓰지 않는다. 검색어에 따라 페이지 본문에서 더 관련 있다고 판단한 문장을 가져다 쓰기도 한다. 메타 설명은 구글에 대한 ‘제안’이지 ‘강제’가 아니다.

    그래도 제대로 된 메타 설명을 써야 한다. 구글이 그걸 참고하는 건 맞고, 아무 설명도 없거나 19자짜리 태그라인이 들어가 있는 것보다는 확실히 낫다. 구글 공식 문서에도 메타 설명 작성 가이드가 따로 나와 있다.

    이번 점검을 하기 전까지 홈페이지 메타 설명이 이 상태인 줄 몰랐다. 설정 화면에 값이 있었으니까. 그 값이 실제로 쓰이고 있다고 당연히 생각했다. 앞으로는 뭔가 설정을 바꿀 때마다 curl로 라이브 확인을 습관으로 만들 생각이다. 설정 화면은 그냥 메모장이 될 수도 있다는 걸 이번에 다시 확인했으니까.

    이 문제는 워드프레스 SEO 버그 5개 총정리 글에도 다른 4개 사례와 함께 정리해뒀다.

    같은 랭크매스 주제로 이어서 읽으면 좋은 글: 랭크매스 포커스 키워드, wp.data로 직접 넣는 법, 랭크매스 무료 기능으로 고아 포스트 2개 찾아낸 이야기.

    노출과 색인 문제를 의심했던 또 다른 사례는 애드센스가 말한 ‘가치 없는 콘텐츠’의 진짜 원인을 진단한 글에도 있다.

  • WPCode로 보안 헤더 추가하다 코드가 깨진 이유

    WPCode로 보안 헤더 추가하다 코드가 깨진 이유

    SEO 감사 결과를 받아들고 액션 아이템 목록을 훑었다. 생각보다 할 게 많았다. 그중에서 오늘 WPCode로 건드린 건 두 가지다.

    SEO 감사에서 나온 보안 헤더를 추가하려 한 이유

    감사 리포트에 보안 헤더(HTTP Security Header, 브라우저에게 보안 정책을 알려주는 응답값)가 빠져 있다고 나왔다. 구체적으로는 세 가지였다. HSTS(HTTP Strict Transport Security, HTTPS 연결만 허용하도록 강제하는 헤더), X-Content-Type-Options(브라우저가 파일 형식을 멋대로 해석하지 못하게 막는 헤더), Referrer-Policy(다른 사이트로 이동할 때 내 사이트 주소를 얼마나 보낼지 제어하는 헤더). 검색엔진 점수에 직접 영향을 주는 항목은 아니지만, 빠져 있으면 감사 점수가 깎인다.

    여기에 하나 더 추가하고 싶은 게 있었다. llms.txt다. llms.txt는 AI 크롤러(ChatGPT, Claude 같은 AI가 사이트 정보를 수집할 때 읽어가는 파일)가 내 사이트 구조를 파악할 수 있도록 만들어두는 텍스트 파일이다. robots.txt(검색엔진 크롤러에게 크롤링 규칙을 알려주는 파일)의 AI 버전이라고 보면 된다.

    문제는 서버 접근 방법이었다. 예전에 랭크매스 SEO 점수를 16점에서 76점까지 올릴 때도 비슷하게 REST API만으로는 한계가 있었는데, 이번에도 그랬다. FTP(File Transfer Protocol, 서버에 파일을 올리고 내리는 방식)도 없고 SSH(Secure Shell, 서버에 원격으로 접속하는 방식)도 없었다. 서버에 직접 파일을 올릴 수 있는 방법이 아예 없는 환경이었다. 그래서 선택한 게 WPCode다. WPCode는 워드프레스 관리자 화면에서 PHP 스니펫(snippet, 짧은 코드 조각)을 직접 추가하고 실행할 수 있는 플러그인(plugin, 워드프레스에 기능을 추가하는 확장 프로그램)이다.

    WPCode로 보안 헤더·llms.txt 추가하다 겪은 삽질기 스크린샷 1

    위는 WPCode 플러그인 편집 화면이다. PHP 코드를 여기에 붙여넣고 활성화하면 워드프레스가 코드를 실행한다.

    WPCode 에디터의 CodeMirror 자동완성이 PHP 코드를 깨뜨린 문제

    WPCode의 코드 에디터(code editor, 코드를 입력하고 수정하는 편집 창)는 CodeMirror라는 라이브러리로 만들어져 있다. 편집기 기능이 꽤 풍부한데, 그중에 자동 괄호 완성 기능이 있다. 괄호를 하나 열면 닫는 괄호를 자동으로 붙여주는 기능이다.

    이게 문제였다. Claude Code로 에디터에 타이핑을 시켰더니, 자동완성이 끼어들면서 코드 중간에 괄호가 두 개씩 들어가거나 엉뚱한 위치에 삽입되는 일이 계속 생겼다. PHP 코드는 괄호 하나만 틀려도 에러가 난다. 별로였다.

    그러다가 예상치 못한 확인창이 떴다. 뭘 클릭한 건지도 모르겠는 상태에서 페이지가 about:blank로 넘어갔다. about:blank는 아무것도 없는 빈 페이지다. 입력하던 코드가 전부 날아갔다. 저장도 안 된 상태로.

    타이핑 대신 setValue()로 코드를 통째로 밀어넣다

    다시 페이지를 열었다. 이번엔 방식을 바꿨다.

    CodeMirror는 자바스크립트로 제어할 수 있다. 에디터 인스턴스에 setValue()라는 메서드를 호출하면, 타이핑 없이 코드를 통째로 집어넣을 수 있다. 자동완성이 개입할 여지가 없다. 한 번에 전체 내용이 들어가니까.

    브라우저 콘솔에서 아래처럼 실행했다.

    document.querySelector('.CodeMirror').CodeMirror.setValue(`여기에 PHP 코드 전체`)

    코드가 깨끗하게 들어갔다. 자동완성 간섭 없이. 저장하고 활성화한 뒤 curl로 확인했더니 세 헤더가 전부 응답에 포함돼 있었다. HSTS, X-Content-Type-Options, Referrer-Policy. 다 떴다.

    WPCode로 보안 헤더·llms.txt 추가하다 겪은 삽질기 스크린샷 2

    curl 응답에서 세 보안 헤더가 실제로 찍힌 결과다. 헤더가 응답에 없으면 아무리 코드를 넣어도 동작하지 않은 것이니, 이 확인 단계는 건너뛰면 안 된다.

    보안 헤더는 성공했는데 llms.txt는 404가 뜬 이유

    같은 방식으로 llms.txt도 만들었다. WPCode에 스니펫을 하나 더 추가해서, 특정 URL로 접근하면 llms.txt 내용을 텍스트로 응답하도록 했다. setValue()로 코드를 넣었으니 입력 과정은 문제없었다.

    그런데 curl로 확인하니 이상했다. 본문 내용은 정확하게 나왔다. llms.txt에 넣으려던 텍스트가 그대로 출력됐다. 그런데 HTTP 상태 코드(HTTP Status Code, 서버가 요청에 대해 응답할 때 같이 보내는 숫자 코드)가 404였다.

    404는 “없는 페이지”라는 뜻이다. 내용은 있는데 없는 페이지라고 응답하는 이상한 상태였다.

    상태 코드를 명시적으로 지정해야 했던 워드프레스의 특성

    워드프레스는 URL을 처리하는 방식이 독특하다. 등록된 페이지나 포스트가 아닌 URL로 요청이 들어오면, 워드프레스는 그 URL을 404로 먼저 처리해버린다. llms.txt는 워드프레스에 등록된 페이지가 아니다. 그러니까 워드프레스 입장에서는 없는 URL이다.

    PHP 코드로 본문 내용을 echo해도, 워드프레스가 이미 404로 결정한 상태 코드는 바뀌지 않는다. 내용은 출력되지만 상태 코드는 404 그대로 남는 거다. 검색엔진이나 AI 크롤러는 상태 코드를 보고 판단한다. 404면 없는 페이지다. 내용이 아무리 정확해도 무시된다.

    해결 방법은 status_header(200)을 코드에 추가하는 거였다. status_header()는 워드프레스에서 HTTP 상태 코드를 강제로 지정하는 함수다. 이걸 echo 앞에 넣어서 200으로 바꿔줬다.

    그래도 처음엔 안 됐다. 라이트스피드 캐시(LiteSpeed Cache, 웹사이트 속도를 높이기 위해 페이지를 미리 저장해두는 플러그인)가 이전 404 응답을 저장해두고 있었다. 캐시 퍼지를 하고 나서야 curl에서 200이 확인됐다.

    WPCode로 보안 헤더·llms.txt 추가하다 겪은 삽질기 스크린샷 3

    캐시 퍼지 후 curl로 다시 확인한 결과다. 상태 코드가 200으로 바뀐 걸 확인할 수 있다. 이 단계 없이는 제대로 됐는지 알 수 없다.

    코드 에디터 자동화와 HTTP 헤더를 다루면서 배운 두 가지

    이번 작업에서 정리된 게 두 가지다.

    첫 번째. 자동화 도구로 코드 에디터를 다룰 땐 타이핑을 시키면 안 된다. 자동완성, 자동 들여쓰기, 단축키 처리 같은 에디터 기능이 전부 방해 요소가 된다. 에디터 인스턴스에 직접 값을 주입하는 방식을 써야 한다. CodeMirror라면 setValue()가 그 방법이다. 타이핑은 사람이 할 때만 자연스럽다.

    두 번째. 워드프레스에서 커스텀 URL을 서빙할 땐 본문 내용만 맞춰선 끝이 아니다. HTTP 상태 코드를 직접 200으로 지정해야 한다. 안 하면 워드프레스가 404를 내보낸다. 크롤러는 그 페이지를 없는 페이지로 처리한다. llms.txt를 만들어도 아무도 읽지 않는 상황이 된다.

    다음엔 llms.txt 내용을 실제로 AI 크롤러가 제대로 읽어가는지 확인해볼 생각이다. 200이 뜨는 건 확인했는데, 실제로 색인(index, 검색엔진이나 AI가 페이지 내용을 자신의 데이터베이스에 등록하는 것)이 되는지는 별개 문제다. 아직 모른다.

    이 문제는 워드프레스 SEO 버그 5개 총정리 글에도 다른 4개 사례와 함께 정리해뒀다.

    같은 워드프레스 주제로 이어서 읽으면 좋은 글: 대표 이미지가 잘리는 이유 — 템플릿 비율 3:2→16:9 차이, 워드프레스 SEO 플러그인 충돌 피하기 , 켜야 할 것, 꺼야 할 것.

  • 랭크매스 SEO 16점→76점, API 함정 피하고 올린 과정

    랭크매스 SEO 16점→76점, API 함정 피하고 올린 과정

    처음 랭크매스 점수를 확인했을 때 16점이 떴다. 대표 이미지도 넣었고, 카테고리도 설정했다. 뭘 더 해야 하는지 몰랐다.

    다 설정했는데도 랭크매스 점수가 16점에서 안 움직인 이유

    이상했다. 분명히 다 채웠는데 점수가 꼼짝을 안 했다. 처음엔 랭크매스 플러그인(워드프레스에 설치해서 SEO를 관리하는 도구) 자체 문제인가 싶었다.

    원인은 다른 데 있었다. API(Application Programming Interface, 프로그램끼리 데이터를 주고받는 통로)로 포커스 키워드(검색엔진에 “이 글은 이 단어에 집중합니다”라고 알려주는 핵심 단어)를 설정했는데, 그게 실제 랭크매스 에디터(글을 작성하고 편집하는 화면) 화면에는 반영이 안 되고 있었다. 코드로는 값을 넣었다. 근데 랭크매스는 그걸 모르는 상태였다.

    겉으로는 다 설정된 것처럼 보였다. 실제 점수는 그대로였다. 이 두 가지가 동시에 사실이었다.

    API로 설정한 SEO 정보, 실제로는 먹히지 않는다?

    먹히지 않는다. 적어도 랭크매스 점수 계산에는.

    Claude Code 같은 AI 도구로 워드프레스 API를 통해 글을 발행할 때, SEO 관련 메타(meta, 글의 제목·설명·키워드 같은 부가 정보) 값을 함께 넣을 수 있다. 기술적으로는 데이터가 전달된다. 문제는 랭크매스가 점수를 다시 계산하지 않는다는 거다.

    wp-admin(워드프레스 관리자 페이지) 에디터를 직접 열어보지 않으면 이걸 알 방법이 없다. 포커스 키워드 입력란이 비어 있다. 점수는 16점. API로 아무리 잘 넣어도 랭크매스 입장에선 설정 안 된 상태다.

    이거 모르고 그냥 발행했으면 SEO 점수가 낮은 채로 글이 올라갈 뻔했다. 실제로 그럴 뻔했다.

    랭크매스 점수 16점에서 76점까지 끌어올린 실제 화면

    위 화면이 그 상태다. API로 다 넣었다고 생각했는데, 에디터에서 확인하면 포커스 키워드 칸이 비어 있고 점수는 16점 그대로다.

    에디터에서 포커스 키워드를 직접 입력했을 때 점수가 폭발한 이유

    wp-admin에서 해당 글을 열었다. 랭크매스 패널(화면 한쪽에 붙어 있는 설정 영역)을 찾아서 포커스 키워드를 직접 손으로 입력했다. 저장했다.

    16점에서 57점이 됐다.

    한 단어 입력이 41점을 올렸다. 이게 왜 가능하냐면, 랭크매스는 포커스 키워드를 기준으로 점수를 계산하기 때문이다. 키워드가 없으면 제목에 키워드가 있는지, 본문에 키워드가 있는지 아무것도 판단을 못 한다. 기준이 생기자마자 이미 작성된 글의 내용들이 한꺼번에 점수에 반영된 거다.

    API 설정이 쓸모없다는 게 아니다. 랭크매스 점수 계산만큼은 에디터 직접 입력이 기준이라는 거다. 이 차이를 모르면 계속 헤맨다.

    57점에서 76점까지, 하나씩 고쳐가며 올린 체크리스트

    57점에서 멈추지 않았다. 뭘 더 고쳐야 하는지 랭크매스가 항목별로 알려준다. 하나씩 고쳤다. 찔끔찔끔 올랐다. 이 과정이 은근히 나쁘지 않았다. 뭘 고쳤을 때 점수가 오르는지 직접 눈으로 보니까.

    • SEO 제목(검색 결과에 표시되는 글 제목)에 포커스 키워드 포함 — 제목 앞쪽에 키워드가 있어야 한다.
    • 메타 설명(검색 결과에서 제목 아래 뜨는 짧은 소개글)에 키워드 포함 , 키워드가 자연스럽게 들어가야 한다. 억지로 끼워 넣는 느낌이면 별로다.
    • 본문 시작 부분에 키워드 포함 , 글 앞쪽 한두 문단 안에 키워드가 나와야 한다.
    • 소제목(h2, h3 태그로 표시되는 중간 제목)에 키워드 포함 , 모든 소제목에 다 넣을 필요는 없다. 한두 군데면 된다.
    • 내부 링크(같은 사이트 안의 다른 글로 연결하는 링크) 1개 추가
    • 외부 링크(다른 사이트로 연결하는 링크) 1개 추가

    이 여섯 가지를 순서대로 적용했다. 76점까지 올랐다. 한 번에 다 한 게 아니라, 하나 고치고 저장하고 점수 확인하고, 다시 고치는 식으로 진행했다.

    완벽한 100점을 목표로 하지 않아도 된다. 랭크매스 기준으로 70점 이상이면 초록색으로 바뀐다. 76점이면 충분하다.

    API vs 에디터 직접 설정의 차이와 확인 방법

    정리하면 이렇다.

    구분 API 설정 에디터 직접 설정
    데이터 저장 된다 된다
    랭크매스 점수 반영 안 된다 된다
    포커스 키워드 인식 안 된다 된다
    확인 방법 wp-admin 에디터 열어봐야 앎 저장하면 바로 점수 업데이트

    확인 방법은 하나다. wp-admin에서 해당 글의 편집 화면을 직접 열어라. 랭크매스 패널이 보이면 포커스 키워드 칸이 채워져 있는지 확인해라. 비어 있으면 API 설정은 점수에 아무 영향이 없는 상태다.

    API로 글을 자동 발행하는 워크플로(작업 흐름)를 쓰고 있다면, 발행 후에 반드시 wp-admin에서 한 번 더 열어서 SEO 설정을 수동으로 확인해야 한다. 귀찮다. 근데 안 하면 낮은 점수로 그냥 올라간다.

    자동화가 전부를 해결해주지는 않는다. 이번에 그걸 배웠다. 다음엔 발행 체크리스트에 “wp-admin SEO 확인” 항목을 아예 넣어둘 생각이다. 결국 랭크매스 점수 하나 때문에 발행 프로세스 자체를 다시 점검하게 됐다.

    이 문제는 워드프레스 SEO 버그 5개 총정리 글에도 다른 4개 사례와 함께 정리해뒀다.

    같은 랭크매스 주제로 이어서 읽으면 좋은 글: 랭크매스 포커스 키워드, wp.data로 직접 넣는 법, 랭크매스 무료 기능으로 고아 포스트 2개 찾아낸 이야기, 메타 설명 오류 , 색인됐는데 검색 안 되던 이유.

  • 이미지가 삐져나가는 버그, 원인 찾고 자동화까지 한 후기

    이미지가 삐져나가는 버그, 원인 찾고 자동화까지 한 후기

    이미지가 삐져나가는 버그, 처음엔 그냥 넘어갈 뻔했다. 블로그 글을 올리고 나서 멀쩡히 보이는지 확인하는 건 습관이다. 그날도 그냥 훑어보고 있었다.

    이미지가 삐져나가는 버그, 눈에 띄는 이상함: 스크린샷 하나가 삐져나가 보였던 이유

    본문을 읽다가 뭔가 이상했다. 스크린샷 하나가 오른쪽으로 쏠려 있었다. 다른 이미지들은 멀쩡한데 그것만.

    이유는 몰랐다. 그냥 딱 봐도 어색했다. 바로 Claude Code(AI 기반 코딩 보조 도구)에 말했다. “지금 본문에서 이 이미지만 오른쪽으로 쏠려있어. 사이즈 조절해서 중앙으로 보기 좋게 다시 작성해줘.” 원인 분석보다 고치는 게 먼저였다.

    아래가 당시 상태다. 텍스트 컬럼(column, 본문이 들어가는 세로 영역) 오른쪽으로 이미지가 넘쳐 있다.

    이미지가 삐져나가는 버그 — 텍스트 컬럼 밖으로 삐져나온 스크린샷

    이렇게 이미지가 본문 영역 밖으로 삐져나오면 레이아웃(layout, 화면 배치 구조) 전체가 깨진 것처럼 보인다. 작은 것 같지만 실제로 읽는 사람 입장에서는 바로 티가 난다.

    원인은 간단했다: 업로드 스크립트가 이미지를 줄이지 않고 있었네

    원인은 허무했다. 업로드 스크립트(script, 특정 작업을 자동으로 처리하는 코드 파일)가 이미지를 그대로 박아넣고 있었다. 리사이즈(resize, 이미지 크기를 줄이거나 늘리는 작업) 없이. 원본 그대로.

    원본 이미지의 가로 크기가 본문 컬럼 폭보다 훨씬 넓었다. 그러니 오른쪽으로 넘칠 수밖에 없다. 알고 나니 별거 아니었다. 근데 이게 지금까지 계속 이렇게 올라가고 있었다는 게 더 문제였다.

    이 버그(bug, 코드나 프로그램에서 발생하는 오류) 자체는 금방 고칠 수 있다. 문제는 따로 있다.

    버그 수정만으로는 부족한 이유: 같은 실수가 반복되면?

    지금 이 이미지만 고치고 끝내면 어떻게 될까. 다음에 글 올릴 때 또 같은 일이 생긴다. 스크립트가 그대로니까.

    버그를 발견했을 때 그 버그만 패치하고 넘어가는 건 임시방편이다. 원인이 코드 안에 남아 있으면 같은 실수는 반드시 다시 나온다. 타이밍만 다를 뿐이다.

    그래서 바로 한 마디 더 붙였다. “처음부터 작성할 때 이런 것 체크해서 최종 마무리해줘.” 재발 방지까지 해야 진짜 끝난 거라고 생각했다.

    자동화로 근본 해결하기: 스크립트에 리사이즈 기능 추가하기

    수정 방향은 하나였다. 업로드 스크립트 자체를 고치는 것.

    이미지를 올릴 때마다 수동으로 크기를 확인하는 건 지속 가능하지 않다. 귀찮으면 빠뜨리게 돼 있다. 그러니 스크립트가 알아서 처리하게 만드는 게 맞다.

    Claude Code에 요청해서 업로드 스크립트를 수정했다. 핵심은 두 가지다.

    • 새 글을 올릴 때 이미지가 자동으로 본문 폭에 맞게 리사이즈된다.
    • 리사이즈된 이미지는 중앙 정렬로 삽입된다.

    이제 이미지 크기를 신경 쓰지 않아도 된다. 스크립트가 처리한다. 이게 자동화(automation, 사람이 직접 하던 작업을 코드가 대신 처리하도록 만드는 것)의 의미다. 한 번 제대로 만들어두면 그 다음부터는 신경 끄면 된다.

    재발 방지까지: 업로드 후 최종 확인 프로세스 정하기

    스크립트를 고치는 것만으로는 완전하지 않다고 봤다. 코드가 제대로 동작하는지 눈으로 확인하는 단계가 없으면 또 다른 문제가 조용히 지나갈 수 있다.

    그래서 규칙을 명확히 정했다. Claude Code에 이렇게 못 박았다.

    • 이미지는 본문 폭 안에 딱 맞게, 중앙 정렬로 들어가야 한다.
    • 업로드 후에는 Claude Code가 직접 최종 확인을 하고, 그 결과를 나한테 컨펌받아야 한다.
    • 스크린샷으로 실제 화면을 직접 확인하는 것을 기본으로 한다.

    코드만 고치고 “됐겠지” 하고 넘어가지 않는다. 반드시 눈으로 확인한다. 이게 기준이다.

    이 사례에서 배울 점: 코드만 고치지 말고 프로세스도 함께

    이번 건 작은 버그였다. 이미지 하나가 삐져나간 것. 근데 거기서 멈추지 않은 게 핵심이다.

    버그를 고치는 건 시작이다. 왜 생겼는지 파악하고, 같은 일이 반복되지 않도록 구조를 바꾸고, 확인 단계까지 만드는 것이 진짜 마무리다.

    AI 도구를 쓸 때 “고쳐줘”만 하고 끝내는 사람이 많다. 그러면 똑같은 질문을 다음 달에 또 하게 된다. “왜 또 이러지?” 하면서.

    물어봐야 할 건 두 가지다.

    • 지금 이걸 어떻게 고치냐.
    • 앞으로 이게 안 생기려면 뭘 바꿔야 하냐.

    두 번째 질문을 안 하면 첫 번째 질문을 계속 반복한다.

    다음에는 업로드 스크립트 전체를 한 번 훑어볼 생각이다. 이미지 말고 다른 곳에서도 비슷한 게 조용히 지나가고 있을 수 있다. 결국 이미지가 삐져나가는 버그 하나가 전체 업로드 파이프라인을 점검하게 만든 셈이다.

    비슷한 패턴은 다른 데서도 반복됐다. WPCode로 보안 헤더 추가하다 코드가 깨진 사례도 결국 같은 교훈이었다 , 자동화 도구를 만들 땐 “일단 되는 것”과 “제대로 확인된 것”은 다르다.

    같은 워드프레스 주제로 이어서 읽으면 좋은 글: 대표 이미지가 잘리는 이유 , 템플릿 비율 3:2→16:9 차이, 워드프레스 SEO 버그 5개, curl로 찾은 공통 원인.

    좌표 값 하나를 잘못 잡아서 생긴 다른 버그는 자막이 카드 텍스트와 겹쳤다, y=h*0.8로 좌표 하나 바꿔 고친 이야기에도 정리했다.