홈·글 목록·글 페이지에서 내 도메인이 보내는 요청과 전송량을 세어본 결과. 홈은 5건 190KB, 글 목록은 9건 968KB, 글 페이지는 7건 482KB이고 이미지 비중이 각각 69퍼센트, 91퍼센트, 82퍼센트다.

·8분 읽기·업데이트:

제 블로그에서 제일 무거운 건 글이 아니라 그림이었습니다


여섯번째 글에서 댓글 기능의 무게를 쟀습니다. 그때는 댓글만 봤습니다.

이번에는 페이지 하나를 여는 데 뭐가 내려오는지 전부 세어봤습니다.

재는 법

빌드한 사이트를 로컬에 띄워놓고, 브라우저를 열어 응답을 하나씩 받아 적습니다.

const reqs = [];
p.on('response', async r => {
  let size = 0;
  try { size = (await r.body()).length; } catch {}
  reqs.push({
    url: r.url(),
    type: r.request().resourceType(),
    size,
  });
});

await p.goto(url, { waitUntil: 'networkidle' });

resourceType으로 묶으면 뭐가 얼마나 차지하는지 바로 나옵니다.

하나 밝혀둘 게 있습니다. body()는 받은 응답을 압축을 푼 크기로 돌려줍니다. 배포된 사이트에서는 HTML과 CSS가 압축돼서 이보다 작게 오가고, PNG와 폰트는 원래 압축된 형식이라 거의 그대로입니다. 그러니 아래 표의 이미지 비중은 실제 전송 기준으로 보면 조금 더 올라갑니다.

결과

홈·글 목록·글 페이지에서 내 도메인이 보내는 요청 수와 전송량. 홈 5건 190KB, 글 목록 9건 968KB, 글 페이지 7건 482KB이며 이미지 비중이 69, 91, 82퍼센트다.

페이지요청전송량이미지 비중
홈5건190 KB69%
글 목록9건968 KB91%
글 페이지7건482 KB82%

글 목록이 제일 무겁습니다. 카드마다 그림이 하나씩 붙으니까요.

글 페이지를 뜯어보면 이렇습니다.

27.9 KB   HTML
11.0 KB   CSS 2개
45.5 KB   폰트 2개
397.3 KB  이미지 2장   ← 82%

글자는 39KB인데 그림이 397KB입니다. 열 배입니다.

18번 글의 청구서

이 숫자를 보고 바로 떠오른 게 있었습니다. 열여덟번째 글에서 제가 이렇게 썼거든요.

deviceScaleFactor: 2가 중요합니다. 1600×640짜리 화면을 2배로 찍어 3200×1280 PNG가 나옵니다. 고해상도 화면에서 글자가 흐려지지 않습니다.

맞는 얘기입니다. 그리고 그 대가가 여기 있습니다. 도식 한 장이 200KB쯤 나가고, 글마다 두 장씩 들어갑니다.

지금까지 만든 도식이 41장, 합쳐서 6.2MB입니다.

줄일 수 있나

같은 그림을 형식만 바꿔 저장해봤습니다.

read-the-source.png   (3200폭 그대로)
  PNG                 191.7 KB
  WebP 무손실          75.2 KB   (39%)
  WebP 손실 (q80)      86.2 KB   (45%)

WebP로 바꾸기만 해도 절반 아래입니다. 무손실로 저장해도 그렇습니다. 픽셀 하나 안 바뀌는데 크기만 줄어듭니다. 이런 도식은 색이 몇 가지 안 되고 같은 색 면이 넓어서 무손실 압축이 잘 먹힙니다. 폭을 1600으로 줄이는 방법도 있지만, 그건 18번 글에서 일부러 2배로 찍은 이유를 버리는 거라 좀 아깝습니다.

그래서 형식만, 무손실로 바꾸는 쪽이 맞아 보입니다. 41장이면 3MB 넘게 줄어듭니다.

그런데 아직 안 했습니다. 이유가 있습니다.

제 이미지는 public/media/에 있고, 본문에서 주소를 그대로 적어 씁니다.

![설명](/media/read-the-source.png)

Astro에는 이미지를 자동으로 최적화해주는 기능이 있는데, 그걸 쓰려면 이미지가 src/ 아래 있어야 합니다. 제가 public/을 고른 이유는 설정 파일에 그대로 적어뒀습니다.

// Note: heroImage is a plain public URL string
// rather than an Astro-optimized image() import,
// so posts written through the Sveltia CMS admin
// UI work without needing files under src/assets.

CMS로 쓴 글이 별도 작업 없이 동작하게 하려고 최적화를 포기했다는 뜻입니다.

휴대폰에서 글을 쓰려고 이미지 최적화를 포기한 겁니다. 그때는 그게 맞는 거래였고, 지금 보니 그 값이 3MB였습니다.

거래 자체를 무르진 않을 생각입니다. 대신 도식을 만드는 쪽에서 WebP로 뽑으면 되니까, 그건 다음에 손보겠습니다.

폰트 45KB를 줄여보려다 두 번 실패했습니다

이미지 다음으로 큰 게 폰트였습니다. 파일 두 개, 45.5KB.

폰트 45KB 를 줄이려고 한 실험 두 가지와 결과. preload 를 빼도 45.5KB 그대로 내려왔고, 글꼴 스택에서 빼자 0KB 가 됐지만 그건 CDN 이 막혔을 때의 대비를 버리는 것이라 되돌렸다.

제 글꼴 스택은 이렇습니다.

font-family:
  'Pretendard Variable',
  Pretendard,
  var(--font-atkinson),   /* ← 세 번째 */
  system-ui, ...;

Atkinson은 세 번째입니다. 앞의 Pretendard가 정상적으로 오면 화면에 한 글자도 안 그립니다. 그런데 파일은 매번 내려옵니다.

첫 번째 시도. 페이지에 이런 태그가 박혀 있었습니다.

<link rel="preload" as="font"
      href="/_astro/fonts/….woff" ...>

preload. 쓰든 안 쓰든 미리 받아두라는 뜻입니다. 이걸 뺐습니다.

그대로 45.5KB가 내려왔습니다.

두 번째 시도. 글꼴 스택에서 Atkinson을 아예 뺐습니다.

0KB가 됐습니다.

그러니까 원인은 preload가 아니라 스택에 이름이 올라가 있다는 것 자체였습니다. 브라우저는 스택에 있는 글꼴이 필요해질 가능성이 있으면 받아둡니다.

그럼 빼면 되지 않느냐. 그런데 Atkinson이 거기 있는 이유가 있습니다. Pretendard는 외부 CDN에서 옵니다. 그게 막히거나 느린 환경에서 라틴 문자를 받쳐주는 게 Atkinson 역할입니다. 빼면 그 대비가 사라집니다.

그래서 둘 다 되돌렸습니다. 45KB를 내고 CDN 실패 대비를 사는 거래입니다.

달라진 건 하나입니다. 전에는 그 45KB가 뭔지도 몰랐고, 지금은 뭘 사는 값인지 알고 냅니다. 나중에 Pretendard를 직접 호스팅하게 되면 그때 Atkinson을 뺄 겁니다.

바깥으로 나가는 요청 넷

여기까지는 제 도메인에서 오는 것만 센 겁니다. 다른 곳으로 나가는 요청도 있었습니다.

cdn.jsdelivr.net          Pretendard 글꼴
gc.zgo.at                 방문 통계 스크립트
ryumaspace.goatcounter…   조회수 조회
pagead2.googlesyndica…    애드센스

넷입니다. 여기서 여섯번째 글을 다시 봐야 했습니다. 그때 저는 이렇게 썼습니다.

저 파일들은 전부 제 도메인에서 옵니다. 서드파티 도메인이 0개입니다.

댓글에 한해서는 맞는 말이었습니다. 그런데 문장만 보면 사이트 전체가 그런 것처럼 읽힙니다. 실제로는 그때도 글꼴과 통계가 밖에서 오고 있었습니다. 범위를 안 적은 제 잘못입니다.

정리

전부 세어보기 전에는 어디가 무거운지 모릅니다. 저는 막연히 “댓글 스크립트가 제일 무겁겠지” 하고 있었는데, 실제로는 제가 직접 만든 그림이 82~91%였습니다.

“선명하게”에는 청구서가 따라옵니다. 2배 해상도로 찍기로 한 결정이 장당 200KB였습니다. 나쁜 결정이었다는 게 아니라, 얼마짜리 결정인지 몰랐다는 겁니다.

고쳤다고 생각하면 다시 재봐야 합니다. preload를 뺐을 때 저는 45KB가 줄었다고 생각하고 넘어갈 뻔했습니다. 다시 재보니 한 바이트도 안 줄어 있었습니다.

줄이지 않기로 한 것도 결론입니다. 45KB를 그대로 두기로 했지만, 이제는 그게 뭘 사는 값인지 압니다. 모르고 내던 값이 알고 내는 값이 됐으면 그날 한 일로는 충분한 것 같습니다.

고친 곳

2026년 9월 29일, 글에 붙일 참고 문서를 하나씩 다시 열어보다가 본문과 어긋나는 곳을 찾아 고쳤습니다.

  • 측정값이 압축을 푼 응답 크기라는 걸 밝혔습니다. 실제 전송량은 HTML·CSS 쪽이 더 작습니다. 그림의 설명 문구도 같이 고쳤습니다.
  • WebP 비교를 다시 쟀습니다. 처음 숫자는 손실 압축이었고, 무손실로 저장하면 더 작아서(191.7→75.2KB) “선명함도 그대로”라는 말이 이제 정확합니다.

참고한 문서


댓글

로그인도 이메일도 필요 없습니다. 이름만 적고 편하게 남겨주세요.