본문으로 건너뛰기
이미지 & 미디어

워드프레스가 이미지를 82% 품질로 압축하지 못하게 막기

워드프레스는 생성하는 모든 JPEG를 0~100 척도에서 품질 82로 다시 인코딩합니다. 이 기본값은 WP_Image_Editor::get_default_quality()에 들어 있으며, 다음에 적용됩니다

게시됨

워드프레스는 생성하는 모든 JPEG를 0~100 척도에서 품질 82로 다시 인코딩합니다. 이 기본값은 WP_Image_Editor::get_default_quality()에 들어 있으며, 업로드한 원본에서 워드프레스가 잘라내는 모든 파생 이미지 — thumbnail, medium, medium_large, large, 그리고 테마가 등록한 추가 사이즈 전부 — 에 적용됩니다. 사진의 경우 82는 파일 용량과 아티팩트 사이의 합리적인 절충점입니다. 하지만 스크린샷, UI 캡처, 차트, 로고, 그리고 선명한 텍스트나 단색면이 들어간 이미지에서는 82가 눈에 띄게 화질을 망가뜨립니다. 글자마다 주변을 기어다니는 모기 노이즈(mosquito noise)가 생기고, 매끄러운 그라데이션에는 밴딩이 나타납니다.

이 값을 바꾸려면 필터 하나를 추가하고 썸네일을 다시 생성하면 됩니다. 스크린샷을 제대로 고치려면, 애초에 워드프레스에 JPEG를 넘기지 않는 것이 대개 더 나은 해법입니다.

82라는 숫자는 어디서 나온 걸까

워드프레스는 4.5 버전(2016년)에서 페이지 용량 최적화를 위해 JPEG 기본값을 90에서 82로 낮췄습니다. 이 값은 wp-includes/class-wp-image-editor.phpget_default_quality()가 반환하며, 활성 편집기 — 호스트에 Imagick가 있으면 WP_Image_Editor_Imagick, 없으면 WP_Image_Editor_GD — 가 리사이즈된 파일을 쓸 때마다 읽힙니다.

중요한 점은 이겁니다. 82는 파생 사이즈마다 적용되지, 한 번만 적용되는 게 아닙니다. 이미지 하나를 업로드하면 워드프레스는 그것을 인코더에 여러 번 통과시키며, 매번 품질 82로 다시 양자화합니다. 업로드한 원본 파일 자체는 빅 이미지 임계값(긴 변 기준 2560px) 미만이라면 건드리지 않습니다. 이 임계값을 넘으면 워드프레스는 품질 82로 다시 인코딩한 -scaled.jpg를 만들어 그것을 “full” 사이즈로 제공합니다. 그래서 “원본 해상도 이미지는 멀쩡한데 페이지에 뜨는 버전은 뭉개져 보인다”는 증상은 거의 항상 srcset이 품질 82짜리 하위 사이즈나 -scaled 파일을 고르고 있는 경우입니다.

품질을 바꾸는 방법

후킹할 필터는 하나입니다. wp_editor_set_quality가 최신의 표준 필터입니다. JPEG와 WebP 모두에서 실행되며 MIME 타입을 인자로 받으므로 분기 처리를 할 수 있습니다.

add_filter( 'wp_editor_set_quality', function ( $quality, $mime_type ) {
    if ( 'image/jpeg' === $mime_type ) {
        return 92; // up from 82
    }
    return $quality;
}, 10, 2 );

이 코드는 작은 mu-plugin(wp-content/mu-plugins/)이나 사이트 전용 플러그인에 넣으세요. functions.php에도 넣을 수 있지만, 그러면 테마를 바꾸는 순간 설정이 사라집니다.

예전 jpeg_quality 필터를 추천하는 글도 보게 될 겁니다. 이 필터는 여전히 실행되지만(워드프레스가 wp_editor_set_quality 직후에 JPEG 전용으로 적용합니다), 둘 다 후킹할 이유는 없습니다. wp_editor_set_quality가 예전 필터가 하던 일을 전부, 그 이상으로 처리합니다.

모두가 잊는 한 가지: 이 필터는 활성화된 이후에 인코딩되는 이미지에만 영향을 줍니다. 이미 wp-content/uploads에 들어 있는 썸네일은 전부 82로 저장됐고 그대로 82로 남습니다. 다시 생성하세요.

wp media regenerate --yes

WP-CLI를 쓰지 않는다면 Regenerate Thumbnails 플러그인이 관리자 화면에서 같은 작업을 해줍니다.

숫자를 확정하기 전에, 특정 품질이 당신의 이미지에 실제로 어떤 영향을 주는지 추측하지 말고 직접 확인해 보는 게 좋습니다. 저희 워드프레스 JPEG 품질 도구는 샘플 이미지를 브라우저에서 모든 품질 레벨로 다시 인코딩해 아티팩트가 나타나는 모습을 눈으로 볼 수 있게 해줍니다. 설정 파일 속 숫자로는 결코 알 수 없는, 82와 90과 100의 차이를 스크린샷에서 확연히 보여줍니다.

스크린샷과 단색 그래픽을 위한 더 나은 해법

JPEG 숫자를 올리는 건 증상만 다루는 것입니다. 스크린샷의 진짜 문제는 JPEG가 스크린샷에 맞지 않는 코덱이라는 점입니다. JPEG의 DCT 압축은 사진의 그라데이션에 맞춰 설계돼 있어, 텍스트와 UI 요소의 흑백 대비가 뚜렷한 가장자리에서 무너집니다. 바로 그래서 품질 82가 사진보다 스크린샷에서 훨씬 더 나쁘게 보이는 겁니다.

대신 PNG를 업로드하세요. 워드프레스는 PNG 하위 사이즈를 PNG로 유지하며, PNG는 무손실입니다. 품질 필터가 건드리지 않으므로 어떤 사이즈에서도 아티팩트 없이 깔끔하게 리샘플링만 됩니다. 스크린샷의 경우, 잘 최적화된 PNG는 같은 이미지의 고품질 JPEG보다 오히려 더 작은 경우가 많습니다. 단색면은 PNG에서 잘 압축되고 JPEG에서는 형편없이 압축되기 때문입니다.

손실 포맷의 작은 파일 용량을 원하면서 JPEG의 가장자리 손상은 피하고 싶다면 WebP가 중간 지점입니다. 다만 그 품질도 위에 나온 것과 같은 wp_editor_set_quality 필터에서 image/webp로 분기해 제어합니다.

하지 말아야 할 것

품질을 전역으로 100으로 설정하지 마세요. 절반쯤 되는 포럼 스레드에서 가장 많은 추천을 받은 답이지만 틀린 답입니다. 품질 100 JPEG는 무손실이 아닙니다 — 여전히 양자화합니다 — 게다가 사이트의 모든 사진 용량을 눈에 보이는 이득도 없이 크게 부풀려 LCP와 코어 웹 바이탈을 끌어내립니다. 필요한 포맷에 대해서만 숫자를 올리거나, 그래픽은 포맷을 바꾸세요. 사이트 전체의 압축을 날려버리지 마세요.

class-wp-image-editor.php를 직접 수정하지 마세요. 코어의 get_default_quality() 반환값을 바꾸는 방식은 다음 wp core update 때 조용히 덮어써질 때까지만 유효합니다. 필터를 쓰세요.

“압축을 피하려고” 이미지 사이즈를 비활성화하지 마세요. 썸네일 생성을 끈다고 다시 인코딩이 멈추지는 않습니다. 반응형 srcset이 깨져서 브라우저가 휴대폰에서도 원본 크기 이미지를 내려받게 됩니다. 다른 문제이면서, 결과는 더 나쁩니다.

다시 업로드하면 기존 이미지가 고쳐진다고 가정하지 마세요. 필터만 설정하고 다시 생성하는 단계를 건너뛰면 예전 파생 이미지는 전부 여전히 품질 82입니다. 필터는 앞으로 생성될 것에만 적용됩니다.

이미지가 2560px 미만인데 -scaled 파일을 탓하지 마세요 — 그 경로는 그런 이미지에는 절대 실행되지 않습니다. 만약 실제로 그 경로에 걸려서 건드리지 않은 원본이 제공되기를 원한다면, 그건 별개의 설정입니다. scaled 이미지 비활성화를 참고하세요.

그래도 막혔다면?

다시 생성한 뒤에도 특정 사이즈가 여전히 이상해 보인다면, 페이지가 실제로 어떤 파일을 제공하고 있는지 확인하세요. 이미지를 새 탭에서 열어 파일명이 크기 접미사(-1024x768.jpg)나 -scaled.jpg로 끝나는지 살펴보면 됩니다. 이미지 사이즈 검사기는 하나의 업로드에서 워드프레스가 생성하는 모든 파생 이미지를 보여줍니다. 그러면 srcset이 브라우저에 어떤 사이즈를 넘기고 있는지 정확히 확인하고, 엉뚱한 파일을 디버깅하는 일을 멈출 수 있습니다.