개발 slecs

블로그 벌크 시딩의 한국어 제목 추출을 LLM으로 통일

목차

블로그 벌크 시딩 스크립트에서 제목(title) 추출 로직을 LLM 기반으로 변경했다. 마크다운 첫 줄 H1에서 한국어 제목을 명시적으로 추출하도록 강제한 작업인데, 처음엔 단순한 버그 픽스처럼 보이지만 사실 콘텐츠 품질과 시스템 신뢰성에 꽤 깊은 이슈가 숨어 있었다.

왜 제목 추출을 "강제"해야 했나?

블로그를 운영하면서 메타데이터 누락 문제가 계속 나타났다. 특히 다국어 지원을 하는 경우, 시스템이 자동으로 제목을 파싱할 때 몇 가지 경로가 생긴다:

  1. 마크다운 첫 줄 H1 헤더 (# 제목)
  2. YAML 프론트매터의 title 필드
  3. 파일명에서 추론
  4. 기본값 폴백

문제는 여러 경로가 있으면 일관성이 깨진다는 것이다. 누군가는 H1을 썼고, 누군가는 프론트매터를 썼고, 누군가는 둘 다 빠뜨렸다. 벌크 시딩으로 대량의 문서를 초기화할 때 이 불일치가 배로 드러난다.

더 심각한 건, 한국어 제목이 생략되고 영어 폴백이 일어나는 상황이었다. 팀이 한국어 블로그를 운영하는데 제목이 영어로 표시되면 사용자 경험이 깨진다. 그리고 SEO 관점에서도 한국어 키워드가 헤더에 있어야 유리하다.

해결: H1 첫 줄에서 한국어 강제 추출

# 의도: 마크다운 첫 번째 H1에서만 제목을 가져온다
# 이렇게 하면 프론트매터, 파일명 등 다른 경로를 무시
def extract_korean_title_from_h1(content: str) -> str:
    lines = content.split('\n')
    for line in lines:
        if line.startswith('# '):
            # LLM 검증: 이 줄이 정말 한국어인가?
            # 혹은 LLM으로 첫 번째 H1 자체를 강제 생성?
            return line[2:].strip()
    return None  # 폴백 없음 - 엄격함

LLM을 활용한 이유는:

  • 단순 regex 보다 robust: "# " 다음이 정말 제목인지 확인 가능
  • 다국어 감지: 한국어인지 영어인지 구분, 잘못된 것만 걸러냄
  • 의미론적 검증: 단순 문자 추출이 아니라 "이게 제목으로 손색없는가?"를 판단

벌크 시딩 시 모든 문서를 이 규칙으로 일괄 처리하면 데이터 일관성을 보장할 수 있다.

트레이드오프: 속도 vs 정확성

이 변경을 검토할 때 팀과 나눈 고민:

관점 기존 방식 (다중 경로) 새 방식 (H1 강제)
속도 빠름 (fallback 많음) 약간 느림 (LLM 호출)
일관성 낮음 (경로 다양) 높음 (단일 경로)
한국어 보장 약함 (폴백 위험) 강함 (검증)
기존 문서 마이그레이션 쉬움 (자동 적응) 어려움 (수동 정렬 필요)

벌크 시딩은 일회성 또는 저빈도 작업이므로, 속도보다 정확성을 택했다. 매일 실행되는 작업이라면 LLM 비용이 문제가 되겠지만, 초기화나 재구성할 때 한 번씩 도는 작업이면 품질 투자가 맞다.

배운 것: 메타데이터 추출의 원칙

이런 작업을 몇 번 하다 보니 패턴이 보인다:

  1. 단일 source of truth 정하기 — 여러 경로를 두지 말 것. H1은 H1만, 프론트매터는 프론트매터만.
  2. 강제성이 필요한 곳엔 validation을 붙일 것 — "제목이 없으면 에러" 같은 명시적 규칙.
  3. 다국어면 명확한 언어 정책 — "기본은 한국어, 영어는 보조" 같은 원칙을 코드에 태운다.
  4. 벌크 작업일수록 엄격할 것 — 한두 개 문서는 수동 수정 가능하지만, 100개 이상이면 자동화의 정확성이 팀의 시간을 좌우한다.

LLM이 만능은 아니지만, "문서 첫 줄이 정말 제목인지", "이게 한국어인지"를 사람처럼 판단해야 할 때는 꽤 유용하다. 정규표현식이나 단순 텍스트 매칭으로는 놓칠 예외들을 잡아낼 수 있으니.


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

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

댓글 0

첫 댓글 달아줘.