🤔 "오늘 롱블랙 글?"

평범한 질문이었다. Contents Hub에게 "오늘 롱블랙 글?"이라고 물으니, 이런 답이 돌아왔다:

{
  "id": 1829,
  "title": "박웅현 : 문제 해결이라는...",
  "published_at": "2022-11-30T00:00:00"
}

2022년? 오늘 크롤한 건데 2022년이라고?

"이거 오늘 크롤한건데?" 라고 되묻자, Claude도 헷갈려했다.


🎯 문제의 본질

API 응답에 날짜 필드가 하나만 있었다:

  • published_at: 원본 발행일

하지만 현실에서는 두 가지 시간 개념이 필요했다:

  1. 언제 발행되었나? (원본 날짜, 아카이브는 과거)
  2. 언제 수집했나? (최신성 판단 기준)

롱블랙처럼 아카이브 콘텐츠를 재발행하는 곳에서는 이 둘이 완전히 다르다:

  • 2022년 글 → 2026년에 크롤 → "오늘 크롤"인데 "2022년 글"

💡 해결: crawled_at 추가

답은 간단했다. 수집 시점을 명시하는 필드를 추가하자:

{
  "id": 1829,
  "title": "박웅현 : 문제 해결이라는...",
  "published_at": "2022-11-30T00:00:00",  // 원본 발행일
  "crawled_at": "2026-02-15T08:30:00"     // 수집 시점
}

이제 명확하다:

  • 원본은 2022년에 쓰인 글
  • 오늘(2/15) 아침에 크롤됨

📚 하지만 필드만 추가한다고 끝?

아니다. 사용자가 이해하지 못하면 소용없다.

MCP 도구(Claude가 API를 호출하는 인터페이스)의 설명이 부족했다:

Before

"""Get recently crawled contents.

Returns: title, url, author, published_at
"""

이걸로는 부족하다. 언제 사용해야 하는지, 무엇을 반환하는지, 날짜 기준이 뭔지 명확하지 않다.


🚀 MCP 프롬프트 전면 개선

11개 도구 모두에 구조화된 가이드를 추가했다:

After

"""Get recently CRAWLED contents (time-based browsing).

IMPORTANT: Searches by crawled_at (collection time),
NOT published_at (original date).

When to use:
- Time-based browsing: "What's new today?"
- NOT for topic search → use search_contents

Returns:
  JSON array with:
  - published_at: Original date (may be old for archive)
  - crawled_at: When we collected it

  Example:
  [{
    "published_at": "2022-11-30T00:00:00",
    "crawled_at": "2026-02-15T08:30:00"
  }]

Timezone note:
- All datetime in UTC (naive)
- To convert to KST: add 9 hours

Errors:
- 401: Missing JWT token
- 400: Invalid days (must be 1-30)
"""

추가된 내용:

  1. When to use — 언제 이 도구를 쓸지
  2. Example response — JSON 구조 예시
  3. Timezone note — UTC/KST 변환 방법
  4. Errors — 예상 가능한 에러 케이스
  5. Related tools — 연관 도구 (워크플로우 이해)

📖 문서도 업데이트

코드만 고치고 끝? 아니다.

CLAUDE.md 추가:

## Data Model
- **Content.published_at**: 원본 발행일 (아카이브는 과거 날짜)
- **Content.crawled_at**: 수집 시점 (최신성 판단 기준)

예: 2022년 롱블랙 글을 2026년에 크롤
→ published_at=2022-11-30, crawled_at=2026-02-15

README.md 예시 확장:

| 유즈케이스 | 예시 | 도구 |
|-----------|------|------|
| 최근 콘텐츠 | "오늘 롱블랙 글?" | get_recent_contents |
| 전체 본문 | "이 글 전체 내용" | get_content |

🎓 배운 점

1. API 날짜 필드는 하나로 충분하지 않다

"날짜"라는 단일 개념에 속지 말자. 현실에는 여러 시간 개념이 있다:

  • 원본 발행일 (published_at)
  • 수집 시점 (crawled_at)
  • 수정일 (updated_at)
  • 삭제일 (deleted_at)

각각의 의미용도가 다르다.

2. 필드 추가는 시작일 뿐

필드만 추가하고 끝내면 안 된다:

  • ✅ 코드에 필드 추가
  • ✅ 도구 설명 개선 (When to use, Example, Errors)
  • ✅ 문서 업데이트 (CLAUDE.md, README.md)

사용자가 이해하고 올바르게 쓸 수 있게 만들어야 한다.

3. 우선순위를 나눠서 진행

한 번에 다 하려고 하지 말자:

P0 (필수): crawled_at 추가 + 핵심 도구 개선
P1 (권장): 응답 예시 + 에러 처리
P2 (선택): timezone-aware datetime 전환

P0를 먼저 배포하고, P1을 추가했다. P2는 나중에.

작은 단위로 나눠서 빠르게 배포하는 게 중요하다.

4. timezone은 항상 명시하라

"published_at": "2026-02-15T08:30:00"  // UTC? KST? 모호!

이게 UTC인지 KST인지 명시해야 한다:

  • ISO 8601: 2026-02-15T08:30:00Z (UTC)
  • 또는 문서에 "All datetime in UTC (naive)" 명시

시간대 혼란은 디버깅 지옥으로 이어진다.


🏁 결과

Before

User: "오늘 롱블랙 글?"
API: published_at=2022-11-30 ← 혼란
User: "이거 오늘 크롤한건데?"

After

User: "오늘 롱블랙 글?"
API: published_at=2022-11-30 (원본),
     crawled_at=2026-02-15 (오늘 수집) ← 명확!

💭 마치며

좋은 API는 명확한 의미를 전달한다.

필드 이름만으로 충분하지 않다면:

  1. 추가 필드로 개념을 분리하고
  2. 문서와 가이드로 의미를 명확히 하자

"왜 이렇게 설계했는지" 미래의 나(와 동료)에게 설명할 수 있어야 한다.


관련 커밋: