프론트엔드 SEO 기초: HTML 구조와 이미지 성능 진단하기

··설명 약 9분·작성: 해비·블로그 소개

프론트엔드 SEO에서 HTML 구조와 이미지 성능을 어떻게 점검하나요?

SEO는 title·description·제목 계층·영역·링크 문구로 페이지 주제를 분명히 하는 작업입니다. 이미지 대체 텍스트·크기·로딩도 함께 점검해 사용자와 검색 엔진이 읽을 구조를 만듭니다.

적용 조건·범위: 첫 화면의 주요 hero/LCP 이미지까지 무조건 lazy 처리하지 않습니다.

공식 문서 참고: Google 검색 센터: 제목·설명·링크·이미지 SEO 기초 · MDN: img의 대체 텍스트·크기·지연 로딩

독립 실습: 직접 만들고 확인하기

프론트엔드 SEO 기초: HTML 구조와 이미지 성능 진단하기 · 독립 실습

주요 기능 링크로 이동하고 소스의 title·description·이미지 alt를 확인하세요. 검색엔진 순위 측정 예제는 아닙니다.

예제 크게 보기 (새 탭)
img { display: block; max-width: 100%; height: auto; }
직접 실행: 환경 준비와 전체 파일

독자 질문

완성한 정적 서비스 페이지에서 검색 엔진과 사용자가 모두 이해하기 쉬운 구조를 어떻게 확인할까요?

직접 만들 화면

TaskFlow 최종 페이지의 head·제목 계층·이미지 속성·링크 문구를 한 장의 점검표로 확인한 결과

새 폴더에 index.html과 style.css를 만들고 아래 전체 파일을 각각 저장하세요. 브라우저에서 index.html을 엽니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>TaskFlow | 작업 관리 서비스</title>
  <meta name="description" content="TaskFlow의 기능, 요금제와 문의 방법을 확인하세요.">
<link rel="stylesheet" href="./style.css"></head>
<body>
  <header><nav aria-label="주요 메뉴"><a href="#features">주요 기능 보기</a></nav></header>
  <main><h1>TaskFlow 작업 관리</h1>
    <section id="features"><h2>주요 기능</h2><img src="https://blogflow.kr/wp-content/uploads/2026/09/html-css-image-checklist-cover-20260914.webp" alt="이미지 비율 학습용 표지" width="900" height="600"></section>
  </main>
</body>
</html>

확인할 결과와 실제 검증 상태

완성 페이지에 title 1개, 내용에 맞는 meta description, h1 1개와 건너뛰지 않는 제목 계층, 의미 있는 링크 문구가 있는지 소스에서 확인하세요. 실제 이미지가 있다면 Network 상태와 원본 비율을 확인하고 초기 화면의 중요한 이미지에 일괄 lazy loading을 적용하지 마세요. CLS 수치와 색인은 실제 측정 전까지 미확인입니다.

실제 브라우저·DevTools 조작 결과: 미확인. 위 내용은 코드에서 예상되는 결과와 독자가 수행할 확인 절차입니다.

다음 학습 연결

웹 퍼블리싱 최종 체크포인트 publishing-step-15-final을 JavaScript 과정의 정적 출발 화면으로 연결합니다.

title

문서 head에 페이지 주제를 명확하게 작성합니다.

<title>
  TaskFlow - 간단한 작업 정리 서비스
</title>

검색 키워드를 반복해서 나열하지 않습니다.

사용자가 탭과 검색 결과에서 페이지를 이해할 수 있는 제목을 만듭니다.

meta description

<meta
  name="description"
  content="TaskFlow의 주요 기능과 요금제, 문의 방법을 확인할 수 있는 작업 관리 서비스 소개 페이지입니다."
/>

description이 검색 결과에 항상 그대로 표시되는 것은 아니지만 페이지 요약 정보를 제공합니다.

heading 구조

페이지의 h1은 핵심 주제를 설명합니다.

h1 TaskFlow 소개
├─ h2 주요 기능
│  ├─ h3 빠른 작업 추가
│  ├─ h3 상태 확인
│  └─ h3 간단한 정리
├─ h2 요금제
├─ h2 문의하기
└─ h2 자주 묻는 질문

글자 크기가 아니라 문서 구조를 기준으로 사용합니다.

landmark

header
nav
main
footer

시맨틱 요소가 페이지 영역을 이해하는 데 도움을 줍니다.

불필요한 role을 중복 추가하지 않습니다.

예를 들어 <main role="main">처럼 native semantics와 같은 role을 반복할 필요는 없습니다.

link text

다음처럼 문맥이 없는 링크를 반복하지 않습니다.

<a href="/pricing">
  자세히 보기
</a>

가능하면 목적을 포함합니다.

<a href="#pricing">
  TaskFlow 요금제 보기
</a>

이미지 alt

<img
  src="./images/hero.webp"
  alt="TaskFlow 작업 목록 화면 예시"
  width="1200"
  height="800"
/>

alt에 키워드를 나열하지 않습니다.

이미지가 실제로 전달하는 정보를 설명합니다.

주변 텍스트와 완전히 중복되는 장식 이미지는 빈 alt를 검토합니다.

width와 height

이미지의 intrinsic ratio를 브라우저가 미리 알 수 있게 합니다.

width="1200"
height="800"

CSS로 반응형 크기를 적용해도 HTML 크기 정보는 CLS 감소에 도움이 됩니다.

img {
  max-width: 100%;
  height: auto;
}
문서의 제목·영역 구조를 확인하고, 이미지의 width와 height로 공간을 예약해 레이아웃 이동을 줄입니다.
개념 설명용 일러스트. 문서의 제목·영역 구조를 확인하고, 이미지의 width와 height로 공간을 예약해 레이아웃 이동을 줄입니다. 이미지 원본 열기

lazy loading

첫 화면 아래쪽 이미지처럼 초기 렌더에 즉시 필요하지 않은 이미지에는 lazy loading을 검토할 수 있습니다.

<img
  src="./images/feature.webp"
  alt="TaskFlow 기능 화면"
  width="800"
  height="450"
  loading="lazy"
/>

첫 화면의 주요 hero/LCP 이미지까지 무조건 lazy 처리하지 않습니다.

초기 렌더 중요도에 따라 선택합니다.

CLS

이미지, 광고, 비동기 콘텐츠가 뒤늦게 공간을 만들면 layout shift가 생길 수 있습니다.

현재 TaskFlow에서는 다음을 확인합니다.

  • img width/height
  • fixed help button이 layout을 밀지 않는지
  • web font가 있다면 fallback 변화
  • dynamic content는 다음 JavaScript 과정에서 별도 고려

시맨틱 HTML과 SEO

검색 엔진을 위해 모든 영역에 schema markup을 억지로 추가하기보다 먼저 문서 구조를 명확하게 만드는 것이 기본입니다.

명확한 title
논리적인 heading
semantic section
설명적인 link
실제 image alt
빠른 안정적 layout

사용자에게 좋은 기본 구조가 검색 이해에도 도움이 됩니다.

SEO 점검 체크리스트

[ ] title이 페이지 목적 설명
[ ] meta description 존재
[ ] h1 하나의 핵심 주제
[ ] h2/h3 구조 자연스러움
[ ] nav/main/footer semantics
[ ] link text가 목적 설명
[ ] image alt 확인
[ ] image width/height 확인
[ ] hero 과도한 lazy loading 없음
[ ] below-fold 이미지 lazy 여부 검토
[ ] 404 image 없음
[ ] mobile horizontal overflow 없음
[ ] CLS 원인 점검

자주 발생하는 오류와 해결

title과 description에 키워드를 반복합니다

검색어 나열보다 페이지 목적을 사람이 이해할 수 있게 설명하는 것이 우선입니다.

모든 이미지를 loading=lazy로 설정합니다

첫 화면의 주요 hero/LCP 이미지를 늦게 불러오면 초기 표시 성능이 나빠질 수 있습니다. 아래쪽 비핵심 이미지에 선택적으로 적용합니다.

heading level을 글자 크기 때문에 바꿉니다

문서 구조는 HTML heading이 담당하고 시각 크기는 CSS가 담당합니다.

alt에 검색 키워드를 길게 나열합니다

이미지가 전달하는 실제 정보와 역할을 간결하게 설명합니다. 장식 이미지는 빈 alt를 검토합니다.

학습 완료 체크리스트

  • title과 description을 작성할 수 있습니다.
  • heading 구조를 SEO 키워드가 아니라 문서 구조 기준으로 만들 수 있습니다.
  • landmark를 의미에 맞게 사용할 수 있습니다.
  • 설명적인 link text를 작성할 수 있습니다.
  • image alt와 width/height를 점검할 수 있습니다.
  • lazy loading을 이미지 위치에 따라 선택할 수 있습니다.
  • CLS와 이미지 성능의 관계를 이해했습니다.

독립 실습은 여기서 마칠 수 있습니다. 아래 선택 실습은 TaskFlow 프로젝트 파일로 진행합니다.

선택 실습: 할 일 앱에 적용하기

TaskFlow는 간단한 서비스 화면에서 시작해 할 일 앱으로 이어 만드는 예제입니다. 이 선택 실습에서는 HTML과 CSS로 이번 화면을 만듭니다.

완성된 정적 TaskFlow를 JavaScript 과정에 넘길 수 있는 최종 상태로 확정합니다.

선택: 연재 프로젝트와 전체 자료

연재 프로젝트를 이어 만드는 분을 위한 자료입니다. 이 글의 개념과 예제만 찾으셨다면 필요한 파일과 실행 방법만 펼쳐보세요.

TaskFlow 프로젝트 최종 적용

프론트엔드 SEO 기초: HTML 구조와 이미지 성능 진단하기 · 단계별 TaskFlow

TaskFlow 누적 15단계입니다. 주요 기능 링크로 이동하고 소스의 title·description·이미지 alt를 확인하세요. 검색엔진 순위 측정 예제는 아닙니다.

예제 크게 보기 (새 탭)

실행 가능한 시작본과 이번 단계

이번 단계 시작 ZIP을 새 폴더에 압축 해제합니다. 이 ZIP은 직전 단계의 완료 파일과 같으며 앞 글의 코드를 따로 모을 필요가 없습니다. 이번 단계 완료 ZIP은 다른 폴더에 풀어 비교합니다.

head의 title·description을 최종 문구로 교체하고 첫 hero 이미지는 즉시, 하단 카드 이미지는 lazy로 로드합니다.

  1. index.html: 이 파일의 기존 내용을 아래 완료 파일 전체와 대조하여 교체합니다. 다른 파일은 유지합니다.

짧은 코드 예제는 변경 위치를 설명합니다. 파일 전체를 작성하거나 교체할 때는 완료 파일 전체를 사용하세요. 생략 표시가 있는 부분 코드를 파일 전체로 저장하지 않습니다.

실행: ZIP의 index.html을 브라우저에서 엽니다. 외부 서버나 npm 설치 없이 로컬 HTML·CSS·이미지를 사용합니다. 문의 폼은 서버 전송을 연결하지 않은 문서 예제입니다. 연습 값만 사용하고 입력 형식을 확인합니다.

직접 확인할 결과: title·description·alt·width/height가 있으며 첫 화면 이미지를 lazy 처리하지 않습니다. 검색 색인·CLS 수치를 측정한 것으로 기록하지 않습니다.

전체 파일·코드 보기

완료 파일 전체

index.html 전체 파일

<!DOCTYPE html>
<html lang="ko">
 <head>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
  <title>
   TaskFlow - 간단한 작업 정리 서비스
  </title>
  <link href="./style.css" rel="stylesheet"/>
  <meta content="TaskFlow의 주요 기능과 요금제, 문의 방법을 확인할 수 있는 작업 관리 서비스 소개 페이지입니다." name="description"/>
 </head>
 <body>
  <a class="skip-link" href="#main">
   본문으로 바로가기
  </a>
  <header class="site-header">
   <div class="page site-header__inner">
    <a class="brand" href="#home">
     TaskFlow
    </a>
    <nav aria-label="주요 메뉴" class="nav">
     <a href="#features">
      기능
     </a>
     <a href="#pricing">
      요금제
     </a>
     <a href="#contact">
      문의
     </a>
     <a href="#faq">
      FAQ
     </a>
    </nav>
   </div>
  </header>
  <main class="page" id="main" tabindex="-1">
   <div class="service-layout">
    <div>
     <section class="hero" id="home">
      <div>
       <h1>
        해야 할 일을 한눈에 정리하세요
       </h1>
       <p>
        TaskFlow는 오늘의 작업을 빠르게 정리하는 서비스입니다.
       </p>
       <a class="button-link" href="#contact">
        시작 문의하기
       </a>
      </div>
      <img alt="TaskFlow 서비스 소개 페이지의 기능·문의 화면" class="hero__image" height="800" src="./images/hero.webp" width="1200"/>
     </section>
     <section id="features">
      <h2>
       주요 기능
      </h2>
      <div class="feature-grid">
       <article class="card feature-card">
        <span class="feature-card__badge">
         NEW
        </span>
        <h3>
         빠른 작업 추가
        </h3>
        <p>
         해야 할 일을 바로 기록할 수 있습니다.
        </p>
        <img alt="TaskFlow 기능 카드 세 개" class="feature-card__image" height="450" loading="lazy" src="./images/feature-board.webp" width="800"/>
       </article>
       <article class="card">
        <h3>
         간단한 분류
        </h3>
        <p>
         해야 할 일을 구분합니다.
        </p>
       </article>
       <article class="card">
        <h3>
         진행 확인
        </h3>
        <p>
         완료 여부를 확인합니다.
        </p>
       </article>
       <article class="card task-preview">
        <div class="task-preview__content">
         <h3>
          아주 긴 작업 제목과 URL
         </h3>
         <p>
          https://example.com/very-long-task-url-without-normal-break-points-123456789
         </p>
        </div>
        <a href="#contact">
         문의
        </a>
       </article>
      </div>
     </section>
     <section class="faq" id="faq">
      <h2>
       자주 묻는 질문
      </h2>
      <details>
       <summary>
        TaskFlow는 어떤 서비스인가요?
       </summary>
       <p>
        해야 할 일을 빠르게 정리하는 작업 관리 서비스 예제입니다.
       </p>
      </details>
      <details>
       <summary>
        모바일에서도 볼 수 있나요?
       </summary>
       <p>
        작은 화면부터 설계한 반응형 레이아웃을 사용합니다.
       </p>
      </details>
      <details>
       <summary>
        문의는 어디서 하나요?
       </summary>
       <p>
        아래 문의 폼을 이용할 수 있습니다.
       </p>
      </details>
     </section>
     <section id="pricing">
      <h2>
       요금제
      </h2>
      <div class="pricing-grid">
       <article class="card">
        <h3>
         Basic
        </h3>
        <p>
         개인 학습용
        </p>
       </article>
       <article class="card">
        <h3>
         Pro
        </h3>
        <p>
         더 많은 프로젝트
        </p>
       </article>
      </div>
      <div aria-label="요금제 비교표 가로 스크롤" class="table-scroll" role="region" tabindex="0">
       <table class="pricing-table">
        <caption>
         TaskFlow 요금제 기능 비교
        </caption>
        <thead>
         <tr>
          <th scope="col">
           항목
          </th>
          <th scope="col">
           Basic
          </th>
          <th scope="col">
           Pro
          </th>
         </tr>
        </thead>
        <tbody>
         <tr>
          <th scope="row">
           프로젝트
          </th>
          <td>
           3개
          </td>
          <td>
           무제한
          </td>
         </tr>
         <tr>
          <th scope="row">
           작업 보관
          </th>
          <td>
           30일
          </td>
          <td>
           무제한
          </td>
         </tr>
         <tr>
          <th scope="row">
           팀 공유
          </th>
          <td>
           없음
          </td>
          <td>
           지원
          </td>
         </tr>
        </tbody>
       </table>
      </div>
     </section>
     <section id="contact">
      <h2>
       문의하기
      </h2>
      <form>
       <div class="form-field">
        <label for="name">
         이름
        </label>
        <input autocomplete="name" id="name" name="name" type="text"/>
       </div>
       <div class="form-field">
        <label for="email">
         이메일
        </label>
        <input autocomplete="email" id="email" name="email" type="email"/>
       </div>
       <div class="form-field">
        <label for="message">
         문의 내용
        </label>
        <textarea id="message" name="message" rows="5"></textarea>
       </div>
       <button type="submit">
        문의 보내기
       </button>
      </form>
     </section>
     <div class="feature-slot">
      <article class="card feature-card">
       <img alt="TaskFlow 기능 카드 세 개" class="feature-card__image" height="450" loading="lazy" src="./images/feature-board.webp" width="800"/>
       <div>
        <h3>
         작업 카드
        </h3>
        <p>
         넓은 공간에서는 이미지와 설명을 나란히 배치합니다.
        </p>
       </div>
      </article>
     </div>
    </div>
    <aside aria-label="기능 미리보기">
     <div class="feature-slot">
      <article class="card feature-card">
       <img alt="TaskFlow 기능 카드 세 개" class="feature-card__image" height="450" loading="lazy" src="./images/feature-board.webp" width="800"/>
       <div>
        <h3>
         작업 카드
        </h3>
        <p>
         넓은 공간에서는 이미지와 설명을 나란히 배치합니다.
        </p>
       </div>
      </article>
     </div>
    </aside>
   </div>
  </main>
  <footer class="site-footer">
   <div class="page">
    <p>
     © TaskFlow
    </p>
   </div>
  </footer>
  <a class="help-button" href="#contact">
   문의
  </a>
 </body>
</html>

style.css 전체 파일

:root {
  color: #171717;
  background: #f5f5f5;
}


*,
*::before,
*::after {
  box-sizing: border-box;
}


body {
  margin: 0;
  font-family:
    Arial,
    sans-serif;
  line-height: 1.6;
  color: #171717;
  background: #f5f5f5;
}


.page {
  width: min(
    100% - 32px,
    960px
  );
  margin-inline: auto;
}


.site-header,
.site-footer {
  padding-block: 20px;
}


main {
  padding-block: 48px;
}


section + section {
  margin-top: 64px;
}


.card {
  padding: 24px;
  border: 1px solid #d7d7d7;
  background: #fff;
}


form {
  display: grid;
  gap: 16px;
}


.form-field {
  display: grid;
  gap: 8px;
}


input,
textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid #b8b8b8;
  background: #fff;
}


button {
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid #171717;
  background: #171717;
  color: #fff;
}

a { color: inherit; }
input, textarea, button { font: inherit; }
h1 { font-size: 32px; font-weight: 700; }
h2 { font-size: 24px; }
h3 { font-size: 20px; }

.site-header__inner {
  display: flex;
  flex-direction: column;
  gap: 12px;
}


.nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
}


.feature-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}


@media (min-width: 48rem) {
  .site-header__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }


  .feature-list {
    flex-direction: row;
  }


  .feature-list > * {
    flex: 1;
  }
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: #f5f5f5;
  border: 1px solid #ddd;
}


.feature-card {
  position: relative;
}


.feature-card__badge {
  position: absolute;
  top: 12px;
  right: 12px;
  padding: 4px 8px;
  border: 1px solid #171717;
  background: #fff;
  font-size: 12px;
}


.help-button {
  position: fixed;
  right: 16px;
  bottom: 16px;
  min-width: 44px;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid #171717;
  background: #171717;
  color: #fff;
  text-decoration: none;
}

.faq {
  display: grid;
  gap: 12px;
}


.faq details {
  border: 1px solid #d7d7d7;
  background: #fff;
}


.faq summary {
  padding: 16px;
  cursor: pointer;
  font-weight: 700;
}


.faq details p {
  margin: 0;
  padding: 0 16px 16px;
}


.faq summary:focus-visible {
  outline: 2px solid #171717;
  outline-offset: 2px;
}

.feature-grid,
.pricing-grid {
  display: grid;
  grid-template-columns:
    repeat(
      auto-fit,
      minmax(
        min(100%, 220px),
        1fr
      )
    );
  gap: 16px;
}

.task-preview {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}


.task-preview__content {
  min-width: 0;
  flex: 1;
}


.task-preview__content p {
  overflow-wrap: anywhere;
}

.settings-layout {
  display: grid;
  grid-template-columns:
    180px
    minmax(0, 1fr);
  gap: 24px;
}

.table-scroll {
  overflow-x: auto;
}


.pricing-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  background: #fff;
}


.pricing-table caption {
  margin-bottom: 12px;
  text-align: left;
  font-weight: 700;
}


.pricing-table th,
.pricing-table td {
  padding: 12px;
  border: 1px solid #d7d7d7;
  text-align: left;
}

img {
  display: block;
  max-width: 100%;
}


.hero__image {
  width: 100%;
  height: auto;
}


.feature-card__image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.service-layout {
  display: grid;
  gap: 24px;
}


@media (
  min-width: 64rem
) {
  .service-layout {
    grid-template-columns:
      minmax(0, 1fr)
      280px;
  }
}

.feature-slot {
  container-type:
    inline-size;
}


.feature-card {
  display: grid;
  gap: 16px;
}


@container (
  min-width: 30rem
) {
  .feature-card {
    grid-template-columns:
      180px
      minmax(0, 1fr);
    align-items: center;
  }
}

.service-layout > * { min-width: 0; }

:root {
  --z-header: 10;
  --z-floating: 20;
}


.site-header {
  position: sticky;
  top: 0;
  z-index:
    var(--z-header);
}


.help-button {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index:
    var(--z-floating);
}

:focus-visible {
  outline: 2px solid #171717;
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 100;
  padding: 10px 12px;
  background: #171717;
  color: #fff;
}


.skip-link:focus {
  top: 16px;
}

section[id], main[id] { scroll-margin-top: 8rem; }
body { padding-bottom: 5rem; }

.hero { display: grid; gap: 24px; }
@media (min-width: 48rem) { .hero { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; } }
.button-link { display: inline-block; padding: 10px 16px; border: 1px solid #171717; background: #171717; color: #fff; }

위 파일과 ZIP의 동명 파일은 동일합니다. 회차별 README·CHANGES 문서는 ZIP에 포함합니다. 생성 산출물·node_modules·실제 환경 변수 파일은 포함하지 않습니다.

시작본과 이번 변경

HTML CSS 종합 실습: 소개·카드·이미지·요금표·문의 폼·FAQ가 있는 반응형 서비스 페이지의 완료 체크포인트를 시작본으로 사용합니다.

14회차 index.html의 head를 비교해 title·description을 정리하고 실제 이미지의 alt/width/height/lazy 여부를 확인합니다. style.css의 반응형과 기존 폼/표/FAQ를 최종 점검합니다. 측정 전 CLS 수치나 실제 검색 색인을 통과로 쓰지 않습니다.

연속 프로젝트 선수 조건

  • 14회차의 TaskFlow 정적 서비스 페이지가 완성되어 있어야 합니다.
  • SEO를 키워드 삽입이 아니라 문서 구조·성능·검색 이해 가능성의 최종 점검으로 다룹니다.

이전 체크포인트

publishing-step-14-service-page

이번 목표

완성된 정적 TaskFlow를 JavaScript 과정에 넘길 수 있는 최종 상태로 확정합니다.

head 최종 예시

<head>
  <meta charset="UTF-8" />
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1.0"
  />


  <title>
    TaskFlow - 간단한 작업 정리 서비스
  </title>


  <meta
    name="description"
    content="TaskFlow의 주요 기능과 요금제, 문의 방법을 확인할 수 있는 작업 관리 서비스 소개 페이지입니다."
  />


  <link
    rel="stylesheet"
    href="./style.css"
  />
</head>

최종 검증

구조

  • header / nav / main / footer
  • h1 → h2 → h3
  • form label
  • table caption/scope
  • details/summary

반응형

  • 320~360px
  • 768px
  • 1024px 이상
  • 200% zoom
  • page 전체 horizontal overflow 없음

이미지

  • Network 404 없음
  • width/height
  • alt
  • object-fit
  • CLS
  • lazy loading 대상 구분

접근성

  • keyboard Tab
  • focus indicator
  • skip link
  • link/button 의미
  • source order

CSS

  • Flex/Grid 역할 적절
  • Container Query fallback
  • z-index layer 정리
  • 불필요한 overflow 숨김 없음

최종 Before / After

Before
빈 HTML/CSS 파일


After
TaskFlow 정적 서비스 화면
+ 시맨틱 HTML
+ 접근 가능한 폼
+ 반응형 Flex/Grid
+ FAQ
+ pricing table
+ 이미지
+ Container Query
+ 접근성 점검
+ SEO/성능 기본 점검

완료 체크포인트

publishing-step-15-final

이 체크포인트가 웹 퍼블리싱 과정의 최종 결과입니다.

다음 학습

JavaScript 과정은 이 정적 화면을 그대로 이어받습니다.

publishing-step-15-final
→ JavaScript
→ DOM 선택
→ event
→ 상태
→ 폼 동작
→ fetch / async
→ TaskFlow Vanilla JS

웹 퍼블리싱에서 만든 HTML 구조를 JavaScript 편의를 위해 불필요하게 다시 작성하지 않습니다.

공식 참고

  • MDN HTML accessibility
  • MDN responsive images
  • web.dev CLS
글 소개·학습 준비·전체 목차
프론트엔드 SEO 기초: HTML 구조와 이미지 성능 진단하기 대표 일러스트

웹 퍼블리싱 · 15 / 15 · 최종 점검 · HTML 구조와 이미지 성능 SEO

SEO는 meta tag 몇 개를 추가하는 작업으로 끝나지 않습니다.

검색 엔진과 사용자가 페이지의 주제와 구조를 이해할 수 있도록 title, description, heading, landmark, link text, 이미지 alt와 성능을 함께 정리해야 합니다.

이번 글에서는 14회차에서 완성한 TaskFlow 정적 서비스 페이지를 최종 진단합니다.

이번 글에서 배우는 내용

  • title
  • meta description
  • heading 구조
  • semantic landmark
  • link text
  • image alt
  • width/height
  • lazy loading
  • CLS
  • 정적 서비스 페이지 SEO 기본 점검

먼저 알아야 할 내용

HTML head·heading·landmark·img 속성을 알면 됩니다. 독립 작은 문서에서 제목·설명·이미지 비율을 점검합니다.

목차

이 글이 도움이 되었나요?

조회 중

읽음 기록

읽음 — / 전체 15개 · 필수 13개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기