개발 slecs

SEO 메타 태그 날짜 파싱 오류를 방어적 타입 변환으로 수정

목차

사소해 보이는 한 줄 수정이었는데, 막상 파고들면 타입 안전성과 SEO 파이프라인 전체가 걸린 문제였다.

배경: pubDate가 왜 갑자기 string이 됐나

Post.astro 레이아웃에서 RSS 피드나 <meta> 태그에 넣을 날짜를 포맷할 때, 보통 pubDateDate 객체라고 가정하고 쓴다. 근데 Astro 콘텐츠 컬렉션 특성상 frontmatter 파싱 타이밍이나 외부 소스에서 데이터를 끌어올 때 "2026-05-24" 같은 문자열이 그대로 넘어오는 경우가 생긴다. .toISOString() 같은 Date 메서드를 바로 호출하면 런타임에 터지고, 그 에러가 빌드 타임이 아닌 렌더 타임에 조용히 터지거나, 더 나쁜 경우 SEO 메타 태그에 undefined 또는 빈 문자열이 박히는 식으로 나타난다.

실제로 이걸 발견한 게 로그나 테스트가 아니라 생성된 HTML을 직접 뒤적이다 pubDate가 이상하게 찍혀있는 걸 본 거였다. 팀이 작은 사이드 프로젝트였지만, SEO 관련 메타는 한 번 잘못 배포하면 크롤러가 캐싱해버리니까 민감하게 봐야 한다.

변경 내용

핵심 수정은 pubDate를 사용하는 시점에 new Date(pubDate) 로 강제 변환하는 것. Date 생성자는 Date 객체를 넘겨도 그냥 복사해서 돌려주고, 문자열을 넘기면 파싱해서 돌려준다. 즉 들어오는 타입이 뭐든 안전하게 처리된다.

---
// Before: Date 객체라고 가정
const isoDate = pubDate.toISOString();

// After: string/Date   처리
const isoDate = new Date(pubDate).toISOString();
---

변경 파일은 src/layouts/Post.astro 단 하나. stat도 크지 않은 핀포인트 수정이다. 파일 한 곳만 건드렸지만 이 레이아웃이 모든 포스트 페이지의 공통 렌더링을 담당하고 있으니 전체 포스트의 SEO 메타 태그에 영향이 가는 변경이다.

항목 Before After
입력 타입 Date 만 허용 (암묵적 가정) string \| Date 둘 다 안전
런타임 에러 string 입력 시 .toISOString is not a function 없음
SEO 출력 일부 케이스에서 깨짐 가능 항상 유효한 ISO 8601 출력
변경 범위 Post.astro 단일 파일

회고: 타입 가정은 항상 방어적으로

이런 류의 버그가 반복적으로 나오는 이유는 결국 인터페이스 경계에서의 타입 가정을 느슨하게 뒀기 때문이다. TypeScript로 frontmatter 스키마를 엄격하게 잡아두면 이런 문제가 컴파일 타임에 잡히긴 하는데, Astro 콘텐츠 컬렉션의 Zod 스키마에서 z.date() 로 선언해도 실제 파싱 결과가 환경에 따라 다를 수 있다는 점이 트릭이다.

그래서 개인적으로 날짜 관련 처리는 아래 원칙을 지키는 편이다.

  • 날짜를 출력하는 시점에서 항상 new Date() 로 한 번 감싼다
  • toISOString(), toLocaleDateString() 등 Date 메서드를 바로 호출하는 코드는 PR 리뷰 때 한 번 더 체크
  • frontmatter 스키마를 Zod로 관리하더라도, 레이아웃 컴포넌트 레벨에서 방어 코드를 두는 것은 중복이 아니라 계층 방어로 인정
  • RSS 피드, OG 태그, JSON-LD 등 SEO 출력단은 변경 후 반드시 실제 HTML 생성물 확인

코드 리뷰할 때도 이 패턴은 자주 지적하게 된다. 특히 주니어 분들이 Date 타입이 맞다고 가정하고 바로 메서드를 호출하는 코드를 짤 때, "이 값이 어디서 오는지 끝까지 추적해봤냐"는 질문을 하게 되는 이유다. 타입 선언이 맞다고 런타임도 맞으리란 보장이 없다는 걸, 이런 작은 픽스들이 계속 상기시켜준다.


끝.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.