이미지 최적화

  • 대표 이미지가 잘리는 이유, 템플릿 비율 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 플러그인 충돌 피하기 , 켜야 할 것, 꺼야 할 것.

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

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

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

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

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

    이유는 몰랐다. 그냥 딱 봐도 어색했다. 바로 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로 좌표 하나 바꿔 고친 이야기에도 정리했다.