GIF보다 가볍고 화질은 뛰어난 WebP 애니메이션은 이제 선택이 아닌 필수입니다. 하지만 정성껏 만든 움짤을 워드프레스에 올리는 순간, 생동감 있게 움직여야 할 이미지가 첫 프레임에 멈춰버리는 당혹스러운 상황을 자주 마주하게 됩니다.
결론부터 말씀드리면, 이는 플러그인의 과잉 친절 때문입니다. EWWW Optimizer나 지연 로딩(Lazy Load) 기능들이 모든 WebP 파일을 ‘일반 정지 이미지’로 간주하여 리사이징하거나 로딩을 뒤로 미루면서 발생하는 문제입니다.
1. 멈춰버린 WebP 애니메이션: “움짤이 아니라 그냥 ‘짤’이 되는 이유”
보통의 성능 최적화 플러그인은 페이지 로딩 속도를 높이기 위해 두 가지 마법을 부립니다. 하지만 이 마법이 WebP 애니메이션에게는 독이 됩니다.
- 지연 로딩(Lazy Load): 사용자가 스크롤을 내리기 전까지 이미지 로딩을 멈춥니다. 이 과정에서 브라우저가 애니메이션 데이터를 즉시 읽지 못해 첫 장면에서 멈추는 현상이 생깁니다.
- 리사이징(srcset): 기기 크기에 맞춰 작은 썸네일을 생성합니다. 안타깝게도 이 과정에서 대부분의 서버 라이브러리는 애니메이션 프레임을 다 날려버리고 정지 영상으로 압축해 버립니다.
결국 운영자는 움짤을 올릴 때마다 지연 로드 제외 클래스를 수동으로 입력하거나, 리사이징을 피하기 위해 파일명을 수정하는 ‘최적화 노가다’를 반복하게 됩니다.
2. 해결책: 바이너리 분석을 통한 “지능형 자동 감지”
매번 수동으로 설정하는 것은 진정한 최적화가 아닙니다. 그래서 저는 서버(PHP)가 이미지를 뿌려주기 직전에 “이 WebP가 움직이는 놈인가?”를 스스로 판단하게 만드는 자동화 방식을 도입했습니다.
애니메이션이 포함된 WebP 애니메이션 파일은 내부 헤더 데이터에 ANIM이라는 고유한 문자열을 가지고 있습니다. 이를 체크하여 움짤일 경우에만 최적화 대상에서 강제로 제외하는 것이 핵심입니다.
[코드 스니펫: WebP 애니메이션 자동 예외 처리]
아래 코드를 테마의 functions.php에 추가하거나 Code Snippets 플러그인을 사용해 적용하세요.
/**
* WebP 애니메이션 자동 감지 및 최적화(지연로드/리사이징) 완벽 예외 처리
*/
// 1. 이미지 속성 필터링 (원본 주소 고정 및 지연로드 해제)
add_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment ) {
$attachment_id = is_object($attachment) ? $attachment->ID : $attachment;
$file = get_attached_file( $attachment_id );
// WebP 파일인 경우에만 내부 데이터(바이너리) 검사
if ( $file && pathinfo($file, PATHINFO_EXTENSION) === 'webp' && file_exists( $file ) ) {
$content = file_get_contents( $file, false, null, 0, 1000 );
// 애니메이션 식별자 'ANIM'이 감지되면 예외 처리 실행
if ( strpos( $content, 'ANIM' ) !== false ) {
$attr['class'] .= ' is-animated-webp';
$attr['data-eio'] = 'skip'; // EWWW Optimizer 제외 속성
$attr['loading'] = 'eager'; // 즉시 로딩 강제
// 리사이징된 썸네일 대신 원본(full) 주소 강제 할당 및 srcset 제거
$full_src = wp_get_attachment_image_src( $attachment_id, 'full' );
if ( $full_src ) {
$attr['src'] = $full_src[0];
unset( $attr['srcset'] );
unset( $attr['sizes'] );
}
}
}
return $attr;
}, 99, 2 );
// 2. 애니메이션 WebP의 경우 srcset 생성을 원천 차단
add_filter( 'wp_calculate_image_srcset', function( $sources, $size_array, $image_src, $image_meta, $attachment_id ) {
$file = get_attached_file( $attachment_id );
if ( $file && pathinfo($file, PATHINFO_EXTENSION) === 'webp' && file_exists( $file ) ) {
$content = file_get_contents( $file, false, null, 0, 1000 );
if ( strpos( $content, 'ANIM' ) !== false ) return false;
}
return $sources;
}, 10, 5 );
// 3. EWWW Optimizer 내부 필터에서도 강제 제외
add_filter( 'eio_do_lazyload', function( $do_lazy, $tag ) {
if ( strpos( $tag, 'is-animated-webp' ) !== false ) return false;
return $do_lazy;
}, 99, 2 );
3. 결과: “F12로 확인하는 코드의 변화”
코드를 적용한 후 개발자 도구(F12)의 요소(Elements) 탭을 열어보면 그 차이가 극명하게 드러납니다.
[적용 전 – 리사이징과 지연 로드의 간섭]

적용 전:
srcset에 수많은 썸네일 주소가 얽혀 있고,loading="lazy"로 인해 애니메이션 로딩이 지연됩니다.
[적용 후 – 군더더기 없는 원본 출력]

적용 후:
srcset이 완전히 사라져 브라우저가 원본만 바라보며,loading="eager"덕분에 페이지 접속과 동시에 부드럽게 재생됩니다.
4. 결론: 자동화가 주는 진정한 최적화
웹사이트 운영에서 가장 경계해야 할 것은 ‘반복되는 수동 작업’입니다. 단순히 보이는 문제를 고치는 것에 그치지 않고, 시스템이 파일의 성격(WebP 애니메이션 여부)을 스스로 파악하여 대응하게 했을 때 비로소 운영의 평화가 찾아옵니다.
이제 어떤 움짤을 올려도 당당하게 포스팅 상단에 배치하세요. 서버가 알아서 전용 예약석을 마련해 줄 테니까요. 저처럼 CSS 수치 입력과 플러그인 설정 사이에서 지치셨던 분들이라면 이 ‘바이너리 체크 방식’을 꼭 도입해 보시길 적극 추천합니다.