Content-Type: text/html; charset=utf-8를 사용하는 HTML 문서 하나를 제공하고, 문서 head에 제목과 설명을, body에 읽을 수 있는 콘텐츠를 넣습니다. 이 Mac 실습에서는 테스트용 페이지를 만들고 하나의 응답에 세 가지가 모두 담겼는지 확인합니다.
이 작업의 목표는 브라우저에서 읽을 수 있는 공개 문서를 준비하고, 동일한 구조를 게시 시스템으로 옮기기 전에 로컬 미리보기로 확인하는 것입니다. 예시에는 종이 모양에 관한 지어낸 텍스트만 포함되며 외부 자산은 필요하지 않습니다.
하나의 유형 지정 HTTP 응답에는 무엇이 들어가나요?
“유형 지정”이란 응답에 미디어 유형이 선언되어 있음을 뜻합니다. Content-Type 필드는 수신자에게 표현의 형식과 처리 목적을 알려 줍니다. 여기서 형식은 HTML입니다. 필드별 애플리케이션 스키마를 제공하는 것은 아닙니다. RFC 9110, section 8.3
HTTP/1.1 응답은 상태 표시줄, 헤더 필드, 빈 줄, 선택적 본문으로 구성됩니다. 따라서 별도의 메타데이터 요청을 만들지 않고도 헤더에 전송 메타데이터를, 본문에 완전한 문서를 보낼 수 있습니다. RFC 9112, section 2.1
이 게시 작업에는 다음 배치 안내를 사용하세요. HTTP 표현을 설명하는 정보와 페이지를 설명하는 정보를 구분합니다.
| 정보 | 위치 | 예시 |
|---|---|---|
| 표현 형식 및 인코딩 | HTTP 헤더 | Content-Type: text/html; charset=utf-8 |
| 문서 제목 | HTML head | <title>종이 모양: 원과 정사각형</title> |
| 페이지 요약 | HTML head | <meta name="description" content="A short guide to arranging paper circles and squares."> |
| 독자에게 보여 주는 콘텐츠 | HTML body | 제목, 소개, 배치 안내 |
WHATWG는 title 요소를 문서의 제목 또는 이름으로 정의하고, description 메타데이터 값을 페이지에 대한 설명으로 정의합니다. 제목은 하나만, 설명 선언은 최대 하나만 사용하세요. HTML 문서 안에 배치하면 콘텐츠와 설명 메타데이터가 함께 전달됩니다. HTML Standard: Document metadata
Mac에서 작동하는 미리보기를 어떻게 만드나요?
Terminal을 열고 사용할 수 있는 명령을 확인하세요.
python3 --version
curl --version
아래 프로그램에는 Python 3.7 이상이 필요하며 표준 라이브러리만 사용합니다. python3을 사용할 수 없다면 공식 macOS 설치 안내를 따르고 Terminal을 다시 여세요. Python 문서에는 설치 프로그램과 터미널에서 python3을 실행하는 방법이 설명되어 있습니다. Using Python on macOS
아래 블록 전체를 여는 명령과 마지막 PY 줄까지 포함해 Terminal에 붙여 넣으세요. 그러면 프로그램이 직접 실행되며 파일을 만들거나 덮어쓰지 않습니다. 페이지를 확인하는 동안 이 터미널 창을 계속 열어 두세요.
python3 - <<'PY'
from html import escape
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
TITLE = "Paper Shapes: Circle and Square"
SUMMARY = "A short guide to arranging paper circles and squares."
PAGE = f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{escape(TITLE)}</title>
<meta name="description" content="{escape(SUMMARY, quote=True)}">
</head>
<body>
<main>
<h1>{escape(TITLE)}</h1>
<p>{escape(SUMMARY)}</p>
<h2>Try a simple arrangement</h2>
<p>Place one paper circle beside one paper square.</p>
<p>Switch their positions — then compare the two arrangements.</p>
</main>
</body>
</html>
""".encode("utf-8")
class Handler(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"
def respond(self, include_body):
if self.path != "/paper-shapes":
self.send_error(404, "Page not found")
return
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(PAGE)))
self.end_headers()
if include_body:
self.wfile.write(PAGE)
def do_GET(self):
self.respond(True)
def do_HEAD(self):
self.respond(False)
if __name__ == "__main__":
with ThreadingHTTPServer(("127.0.0.1", 8000), Handler) as server:
print("Preview: http://127.0.0.1:8000/paper-shapes", flush=True)
try:
server.serve_forever()
except KeyboardInterrupt:
pass
PY
이 핸들러는 Python의 문서화된 응답 메서드를 사용합니다. send_response()은 응답을 시작하고, send_header()은 필드를 추가하며, end_headers()은 본문 바이트를 쓰기 전에 헤더 섹션을 완료합니다. Python HTTP server documentation
이 예시에서는 TITLE과 SUMMARY를 의도적으로 한 번씩만 정의합니다. 이 값들은 메타데이터와 화면에 표시되는 텍스트 양쪽에 사용되므로 작은 문서를 일관되게 수정하기 쉽습니다. 페이지가 길어지면 설명은 첫 문단과 달라도 되지만 같은 주제를 정확히 요약해야 합니다.
길이를 계산하기 전에 페이지를 인코딩합니다. HTTP에서 Content-Length는 문자 수가 아니라 바이트 수를 나타냅니다. 이 예시의 em dash를 문자로 세면 잘못된 결과가 나옵니다. RFC 9110, section 8.6
콘텐츠와 메타데이터가 함께 도착했는지 어떻게 확인하나요?
두 번째 Terminal 창을 열고 이 명령을 실행하세요. 일반 문서 요청을 보내고 응답 헤더와 콘텐츠를 모두 표시합니다.
curl -i --max-time 10 http://127.0.0.1:8000/paper-shapes
-i 옵션을 사용하면 응답 헤더가 본문과 같은 출력 스트림에 포함됩니다. 시간 제한은 전송 시간을 10초로 제한합니다. 이 옵션은 curl 명령줄 설명서에 설명되어 있습니다.
출력을 다음 순서로 확인하세요.
- 상태 표시줄에
200 OK가 표시되어야 합니다. Content-Type필드 하나가text/html; charset=utf-8을 선언해야 합니다.- 헤더 섹션의 빈 줄 뒤에 HTML에 제목과 설명이 있어야 합니다.
- 같은 본문에 종이 모양 안내도 있어야 합니다.
- 디코딩된 텍스트에 em dash가 올바르게 표시되어야 합니다.
그다음 Safari 주소 표시줄에 http://127.0.0.1:8000/paper-shapes를 입력하세요. 표시된 페이지에 제목, 요약, 안내가 보여야 합니다. 설명 선언은 메타데이터이므로 페이지의 모양만 보고 있다고 추정하지 말고 반환된 마크업에서 확인하세요.
헤더만 반환되는 경로도 확인할 수 있습니다.
curl -I --max-time 10 http://127.0.0.1:8000/paper-shapes
이 요청은 HEAD을 보내므로 본문에 제목이나 설명이 포함되어 있는지 확인할 수 없습니다. HEAD 응답은 해당 표현에 대한 설명을 제공하면서 콘텐츠를 생략합니다. 실제 문서를 확인하려면 앞서 나온 GET 검사를 사용하세요. RFC 9110, section 8.2
미리보기가 작동하지 않으면 증상에 따라 다음 조치를 선택하세요.
| 증상 | 다음 조치 |
|---|---|
| 시작 시 주소가 이미 사용 중이라고 표시됨 | 프로그램에서 8000을 8001로 바꾸고 다시 실행한 다음, 모든 미리보기 명령에서 8001을 사용하세요. |
| 요청 시 연결 실패가 표시됨 | 첫 번째 터미널에 미리보기가 계속 실행 중인지, 포트가 일치하는지 확인하세요. |
응답이 404임 |
정확히 /paper-shapes를 사용하세요. 이 예시는 끝에 슬래시를 붙이거나 쿼리 문자열을 추가한 경로를 허용하지 않습니다. |
| 브라우저에 이전 버전이 계속 표시됨 | Control-C로 프로그램을 중지하고, 수정한 블록을 다시 실행한 다음 페이지를 새로고침하세요. |
| 제목은 올바르게 보이지만 메타데이터가 없음 | GET 출력을 살펴보고 선언이 문서 head 안에 있는지 확인하세요. |
Google 검색은 이 응답에서 무엇을 활용할 수 있나요?
설명이 담긴 제목, 정확한 설명, 유용한 화면 표시 텍스트는 Google이 페이지를 표시할 때 활용하는 것으로 문서화된 입력 정보입니다. Google은 title 요소, 주요 시각적 제목, 제목 요소 및 기타 출처를 자동 제목 링크 생성에 활용한다고 설명합니다. 이러한 신호가 문서의 주제와 일치하도록 유지하세요. Influencing your title links in search results
Google은 주로 페이지 콘텐츠에서 스니펫을 생성하며, 메타 설명이 페이지를 더 정확하게 설명하는 경우 이를 사용하기도 합니다. 검색어에 따라 스니펫이 달라질 수 있습니다. 설명을 고정된 검색 결과 문구가 아니라 유용한 요약으로 생각하세요. Control your snippets in search results
테스트용 예시에서 설명은 간단한 배치 안내를 약속하고 본문은 그 안내를 제공합니다. 샘플 텍스트를 교체할 때 이 관계를 명확히 확인하세요. 설명만 읽어도 페이지 내용을 정확하게 예상할 수 있어야 합니다.
사용자 지정 메타데이터 이름을 추가해도 해당 이름이 지원된다는 뜻은 아닙니다. Google은 지원하지 않는 메타 태그를 무시한다고 설명합니다. 검색용 메타데이터에는 Google이 문서화한 필드를 사용하세요. 자체 애플리케이션을 위해 만든 필드는 이를 사용하는 소비자를 별도로 정의해야 합니다. Meta tags and attributes that Google supports
미리보기를 공개 게시 방식으로 어떻게 전환하나요?
이 실습의 로컬 주소는 데스크톱 미리보기이지 게시된 페이지가 아닙니다. Python은 또한 http.server을 프로덕션 용도로 권장하지 않는다고 설명합니다. 이 예시를 공개 호스팅 서비스로 사용하지 말고 HTML 구조와 응답 요건을 게시 시스템으로 옮기세요. Python HTTP server documentation
콘텐츠 관리 시스템을 사용한다면 문서화된 페이지 제목 및 메타 설명 설정을 찾으세요. Google은 CMS에서 HTML을 직접 편집하는 대신 검색 설정을 제공할 수 있다고 설명합니다. 해당 설정을 여기서 보여 준 필드에 대응시킨 다음 결과 문서 응답을 살펴보세요. Google’s guidance on adding meta descriptions
HTTP는 멀티파트 표현도 지원하지만 이는 패키징 방식이 다릅니다. 브라우저에서 읽을 수 있는 문서를 만드는 이 작업에는 이미 지원되는 HTML 구조를 사용해 콘텐츠와 문서 메타데이터를 하나의 표현에 담을 수 있습니다. 멀티파트를 선택하면 이 실습에 필요하지 않은 소비자 측 처리 요건이 생깁니다. RFC 9110, section 8.3.3
완료 여부는 구체적으로 확인할 수 있습니다. 한 번의 성공적인 문서 요청으로 올바른 미디어 유형, 완전한 HTML 본문, 정확한 제목과 설명, 독자가 보러 온 텍스트가 모두 반환되어야 합니다. 로컬 미리보기뿐 아니라 최종 공개 응답에도 이 확인을 적용해 게시 시스템의 출력이 준비한 문서와 일치하도록 하세요.
출처
- RFC 9110: HTTP Semantics — IETF / RFC Editor.
- RFC 9112: HTTP/1.1 — IETF / RFC Editor.
- HTML Standard: Document metadata — WHATWG.
- Using Python on macOS — Python Software Foundation.
- http.server — HTTP servers — Python Software Foundation.
- curl — How To Use — curl.
- Influencing Title Links in Google Search — Google Search Central.
- How to Write Meta Descriptions — Google Search Central.
- Meta Tags and Attributes that Google Supports — Google Search Central.