Hreflang 태그와 Next.js: 30개 언어를 118개 페이지에 걸쳐 배포하는 방법

제 잠을 설쳐 준 숫자를 공유하겠습니다: 3,540. 이는 30개 언어에 118개 페이지를 곱한 것입니다. Deluxe Astrology에서 이 모든 것을 동시에 출시했다면 Google은 수천 개의 얇고, 번역되지 않았거나, 기계 생성 쓰레기 페이지를 인덱싱했을 것입니다. 우리의 순위는 폭락했을 것입니다. 대신, 우리는 언어를 단계적으로 롤아웃하고, Claude Haiku를 언어당 약 $22의 배치 번역에 사용하며, Winston AI 채점으로 품질을 제어하는 2단계 번역 게이팅 시스템을 구축했습니다. 전체 시스템은 next-intl 미들웨어를 포함한 Next.js에서 실행되며, 로케일 인식 정규 URL과 HTML head 및 XML 사이트맵의 hreflang 태그를 포함합니다. 이것이 우리가 이를 어떻게 했는지에 대한 완전한 분석입니다 -- 모든 미들웨어 설정, 모든 사이트맵 항목, 모든 비용 계산이 포함되어 있습니다.

목차

Hreflang 태그와 Next.js: 30개 언어를 118개 페이지에 걸쳐 배포하는 방법

2025년에도 Hreflang 태그가 여전히 중요한 이유

Google의 언어 감지 능력은 향상되었습니다. 이 점은 인정합니다. 하지만 "향상된"이 "해결됨"을 의미하지는 않습니다. 지역 변형을 실행 중이라면 -- pt-BRpt-PT, 또는 zh-CNzh-TW -- Google은 여전히 명확한 신호가 필요합니다. hreflang이 없으면 브라질의 포르투갈어 페이지가 포르투갈 대상 콘텐츠를 잠식하는 것을 보게 될 것이며, 그 반대도 마찬가지입니다.

데이터가 무엇을 말하는지 보겠습니다:

  • 다국어 웹사이트의 60% 이상이 hreflang 설정 오류를 가지고 있습니다(출처: 국제 SEO 감사에 대한 Ahrefs 연구)
  • 적절한 hreflang 구현은 4-6주 이내에 대상 시장에서 클릭률을 20-30% 증가시킬 수 있습니다
  • hreflang이 없는 사이트는 언어 버전 간의 예측 불가능한 순위 회전을 경험하여 성능 추적을 거의 불가능하게 만듭니다

Deluxe Astrology의 경우 30개 언어를 구분되는 콘텐츠로 대상으로 하고 있습니다. 지역 변형이 아닙니다 -- 실제 다른 언어들입니다. 검색 결과에서 올바른 버전을 찾아야 하는 30개의 다른 대상입니다. Hreflang은 여기서 선택 사항이 아닙니다. 이것이 기초입니다.

대부분의 가이드가 놓치는 것: HTML <head>와 XML 사이트맵 모두에 hreflang이 필요합니다. 하나 또는 다른 하나가 아닙니다. 둘 다입니다. Google은 여러 출처에서 hreflang을 처리한다고 확인했으며, 여기서 중복은 낭비가 아닙니다 -- 보험입니다.

3,540 페이지 문제

우리의 전체 아키텍처를 형성한 수학을 살펴보겠습니다.

Deluxe Astrology는 다음을 가지고 있습니다:

  • 118개 페이지 (핵심 콘텐츠 페이지)
  • 41개 번역 네임스페이스 (번역 가능 문자열의 논리적 그룹화)
  • 39개 로케일 인식 API 경로
  • 30개 대상 언어

30 × 118 = 3,540개의 총 페이지 변형입니다.

첫 날에 3,540개 페이지를 모두 출시했다면 다음과 같이 됩니다:

  1. 대부분의 페이지에는 영어 폴백 텍스트와 비영어 URL 경로가 포함됩니다. Google은 이것을 얇은/중복 콘텐츠로 봅니다.
  2. Googlebot은 수천 개의 낮은 품질 페이지를 인덱싱하여 크롤 예산을 소모합니다.
  3. 사이트의 전체 품질 신호가 폭락하여 좋은 영어 페이지도 끌어내립니다.
  4. 번역되지 않은 페이지에 도달하는 사용자는 즉시 이탈합니다.

이것은 이론적이지 않습니다. Weglot 또는 유사한 도구를 연결하고 하루 밤에 20개 언어로 스위치를 켜버린 클라이언트 사이트에서 이런 일이 발생하는 것을 본 적이 있습니다. 트래픽은 올라가지 않고 내려갔습니다.

해결책: 모든 언어를 한 번에 출시하지 마세요. 게이팅하세요.

2단계 번역 게이팅 시스템

우리는 30개 언어를 근본적으로 다른 출시 전략을 가진 2개 계층으로 나누었습니다.

계층 1: TRANSLATED_LOCALES

이것들은 네이티브 스피커 또는 검증된 이중언어 사용자에 의해 수동으로 검토된 완전히 번역된 핵심 페이지를 가진 15개 언어입니다.

// config/locales.ts
export const TRANSLATED_LOCALES = [
  'en', 'es', 'fr', 'de', 'it', 'pt-BR', 'ja', 'ko',
  'zh-CN', 'zh-TW', 'ru', 'ar', 'hi', 'tr', 'nl'
] as const;

이 15개 언어는 다음을 얻습니다:

  • 모든 118개 페이지에 걸쳐 전체 hreflang 태그
  • XML 사이트맵에 포함
  • 색인 가능한, 정규 URL
  • 로케일 인식 구조화된 데이터 마크업

계층 2: DYNAMIC_TRANSLATED_LOCALES

나머지 15개 언어는 영어 전용 자리표시자로 시작합니다. 인덱싱되지 않습니다. hreflang 항목이 없습니다. 사이트맵에 존재하지 않습니다.

export const DYNAMIC_TRANSLATED_LOCALES = [
  'pl', 'sv', 'da', 'fi', 'no', 'cs', 'ro', 'hu',
  'el', 'th', 'vi', 'id', 'ms', 'uk', 'bg'
] as const;

export const ALL_LOCALES = [
  ...TRANSLATED_LOCALES,
  ...DYNAMIC_TRANSLATED_LOCALES
] as const;

계층 2 언어가 번역 파이프라인을 완료하면 -- Claude Haiku 배치 번역, Winston AI 품질 게이트, 선택적 인간 검토 -- 계층 1로 승격됩니다. hreflang 항목, 사이트맵 포함 및 인덱싱 지시문이 자동으로 업데이트됩니다.

// utils/locale-status.ts
export function isLocaleReady(locale: string): boolean {
  // Check if all required namespaces have translations
  // with Winston AI scores >= 95%
  const status = getTranslationStatus(locale);
  return status.completedNamespaces >= REQUIRED_NAMESPACES
    && status.minQualityScore >= 0.95;
}

export function getIndexableLocales(): string[] {
  return ALL_LOCALES.filter(isLocaleReady);
}

이것이 핵심 통찰입니다: 당신의 hreflang 구현은 동적이어야 합니다. 빌드 시간에 하드코딩된 정적 목록이 될 수 없습니다(로케일이 승격될 때 재구축하면 가능합니다, 이것이 우리가 ISR로 하는 것입니다).

Hreflang 태그와 Next.js: 30개 언어를 118개 페이지에 걸쳐 배포하는 방법 - 아키텍처

next-intl 미들웨어 설정

미들웨어는 로케일 감지, 라우팅 및 게이팅 로직이 모두 수렴하는 곳입니다. 우리의 실제 middleware.ts입니다:

// middleware.ts
import createMiddleware from 'next-intl/middleware';
import { NextRequest, NextResponse } from 'next/server';
import { ALL_LOCALES, TRANSLATED_LOCALES } from './config/locales';

const intlMiddleware = createMiddleware({
  locales: ALL_LOCALES,
  defaultLocale: 'en',
  localePrefix: 'always',
  localeDetection: true
});

export default function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;
  
  // Extract locale from path
  const pathnameLocale = ALL_LOCALES.find(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
  );

  // If locale is in Tier 2 and not yet ready, 
  // serve content but add noindex header
  if (
    pathnameLocale &&
    !TRANSLATED_LOCALES.includes(pathnameLocale) &&
    !isLocaleReady(pathnameLocale)
  ) {
    const response = intlMiddleware(request);
    response.headers.set('X-Robots-Tag', 'noindex, nofollow');
    return response;
  }

  return intlMiddleware(request);
}

export const config = {
  matcher: ['/((?!api|_next|_vercel|.*\\..*).*)'] 
};

여기서 주목할 몇 가지 사항:

  1. localePrefix: 'always' -- 모든 URL은 로케일 접두사를 얻습니다. /en/horoscope, /de/horoskop 등. 모호함이 없습니다. 모든 대체 URL이 구분되고 예측 가능해야 하기 때문에 hreflang에 중요합니다.

  2. 계층 2 noindex -- 번역되지 않은 로케일은 여전히 렌더링됩니다(해당 지역의 사용자는 여전히 탐색할 수 있음), 하지만 noindex 헤더를 얻습니다. Google은 크롤 예산을 낭비하지 않을 것입니다.

  3. 매처 -- API 경로, Next.js 내부 및 정적 파일을 제외합니다. 39개 로케일 인식 API 경로에는 자체 로케일 처리가 있습니다.

유사한 것을 구축하는 경우, 우리는 더 자세히 작성했습니다 Next.js 개발 방식 및 미들웨어가 아키텍처에 어떻게 맞는지에 대해.

HTML Head에서 Hreflang 구현

Next.js 14+ App Router는 generateMetadata 함수를 제공합니다. 이곳이 hreflang 태그가 HTML <head>에 가는 곳입니다.

// app/[locale]/[...slug]/page.tsx
import { getIndexableLocales } from '@/utils/locale-status';
import { getLocalizedSlug } from '@/utils/slugs';

type Props = {
  params: { locale: string; slug: string[] };
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { locale, slug } = params;
  const baseUrl = 'https://deluxeastrology.com';
  const pagePath = slug ? `/${slug.join('/')}` : '';
  const indexableLocales = getIndexableLocales();

  // Build language alternates -- only for indexable locales
  const languages: Record<string, string> = {};
  
  for (const loc of indexableLocales) {
    const localizedSlug = await getLocalizedSlug(pagePath, loc);
    languages[loc] = `${baseUrl}/${loc}${localizedSlug}`;
  }

  // x-default points to English
  languages['x-default'] = `${baseUrl}/en${pagePath}`;

  return {
    title: await getLocalizedTitle(pagePath, locale),
    alternates: {
      canonical: `${baseUrl}/${locale}${pagePath}`,
      languages
    }
  };
}

이것은 다음과 같은 HTML을 생성합니다:

<link rel="canonical" href="https://deluxeastrology.com/de/horoskop" />
<link rel="alternate" hreflang="en" href="https://deluxeastrology.com/en/horoscope" />
<link rel="alternate" hreflang="de" href="https://deluxeastrology.com/de/horoskop" />
<link rel="alternate" hreflang="fr" href="https://deluxeastrology.com/fr/horoscope" />
<!-- ... 12개 추가 색인 가능 로케일 ... -->
<link rel="alternate" hreflang="x-default" href="https://deluxeastrology.com/en/horoscope" />

두 가지 중요한 세부 사항:

  1. 정규 URL은 로케일 특정입니다. 독일어 페이지의 정규은 영어가 아닌 독일어 URL입니다. 각 언어 버전은 자신의 정규 페이지입니다.
  2. x-default는 항상 있습니다. 영어를 가리킵니다. Google이 사용자의 언어를 hreflang 항목과 일치시킬 수 없으면 x-default가 폴백입니다.

Hreflang 항목을 포함한 사이트맵 생성

HTML <head> hreflang은 필요하지만 충분하지 않습니다. 3,540개의 잠재적 페이지 변형이 있는 사이트의 경우, 또한 XML 사이트맵에 hreflang이 필요합니다. 이유는: Google은 먼저 모든 페이지를 크롤링하지 않고도 사이트맵에서 hreflang 관계를 발견할 수 있습니다.

// app/sitemap.ts
import { MetadataRoute } from 'next';
import { getIndexableLocales } from '@/utils/locale-status';
import { getAllPages } from '@/utils/pages';
import { getLocalizedSlug } from '@/utils/slugs';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const baseUrl = 'https://deluxeastrology.com';
  const indexableLocales = getIndexableLocales();
  const pages = await getAllPages(); // Returns 118 page definitions

  const entries: MetadataRoute.Sitemap = [];

  for (const page of pages) {
    for (const locale of indexableLocales) {
      const localizedSlug = await getLocalizedSlug(page.path, locale);
      const url = `${baseUrl}/${locale}${localizedSlug}`;

      // Build alternates for this specific page
      const alternates: Record<string, string> = {};
      for (const altLocale of indexableLocales) {
        const altSlug = await getLocalizedSlug(page.path, altLocale);
        alternates[altLocale] = `${baseUrl}/${altLocale}${altSlug}`;
      }
      alternates['x-default'] = `${baseUrl}/en${page.path}`;

      entries.push({
        url,
        lastModified: page.updatedAt,
        changeFrequency: page.changeFreq || 'weekly',
        priority: locale === 'en' ? 0.9 : 0.8,
        alternates: {
          languages: alternates
        }
      });
    }
  }

  return entries;
}

이것은 다음과 같은 XML을 생성합니다:

<url>
  <loc>https://deluxeastrology.com/de/horoskop</loc>
  <lastmod>2025-01-15</lastmod>
  <xhtml:link rel="alternate" hreflang="en" href="https://deluxeastrology.com/en/horoscope"/>
  <xhtml:link rel="alternate" hreflang="de" href="https://deluxeastrology.com/de/horoskop"/>
  <xhtml:link rel="alternate" hreflang="fr" href="https://deluxeastrology.com/fr/horoscope"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://deluxeastrology.com/en/horoscope"/>
</url>

15개 색인 가능 로케일과 118개 페이지로 1,770개의 사이트맵 항목입니다. 관리 가능합니다. 모든 30개 언어가 준비되면 3,540개가 될 것입니다. 여전히 Google의 50,000-URL 사이트맵 제한 범위 내이지만, 더 깨끗한 Google Search Console 모니터링을 위해 로케일별 사이트맵으로 분할합니다.

번역 파이프라인: Claude Haiku + Winston AI

경제학이 흥미로워지는 곳입니다. 118개 페이지를 41개 네임스페이스에 걸쳐 30개 언어로 번역해야 했습니다. 전문 인간 번역은 금본위제가 되겠지만, 예산 수학은 가혹합니다.

파이프라인

  1. 추출 -- 41개 네임스페이스에서 모든 번역 가능 문자열을 구조화된 JSON으로 가져옵니다
  2. 번역 -- Claude Haiku (Anthropic의 빠르고 저렴한 모델)을 통해 배치 처리합니다 (도메인 (점성술)에 대한 컨텍스트, 톤 및 대상 청중 포함)
  3. 품질 게이트 -- 번역된 콘텐츠를 Winston AI의 콘텐츠 감지 및 품질 채점을 통해 실행합니다. 임계값: 95% 이상 또는 거부.
  4. 인간 검토 -- 높은 가치 페이지 (홈페이지, 랜딩 페이지, 머니 페이지)는 네이티브 스피커에 의한 수동 검토를 받습니다
  5. 승격 -- 모든 네임스페이스가 품질 게이트를 통과하면, 로케일은 DYNAMIC_TRANSLATED_LOCALES에서 TRANSLATED_LOCALES로 이동합니다
// scripts/translate-locale.ts
async function translateLocale(targetLocale: string) {
  const namespaces = await getNamespaces(); // 41 namespaces
  
  for (const ns of namespaces) {
    const sourceStrings = await loadNamespace('en', ns);
    
    const translated = await claude.messages.create({
      model: 'claude-3-haiku-20240307',
      max_tokens: 4096,
      system: `You are a professional translator specializing in astrology content. 
               Translate from English to ${getLanguageName(targetLocale)}. 
               Maintain astrological terminology accuracy. 
               Preserve all interpolation variables like {name} and {date}.`,
      messages: [{
        role: 'user',
        content: `Translate these JSON key-value pairs. Return valid JSON only:\n${JSON.stringify(sourceStrings, null, 2)}`
      }]
    });

    const qualityScore = await winstonAI.analyze(translated.content);
    
    if (qualityScore >= 0.95) {
      await saveNamespace(targetLocale, ns, translated.content);
    } else {
      await flagForReview(targetLocale, ns, translated.content, qualityScore);
    }
  }
}

Claude Haiku를 사용한 언어당 비용은 대략 $22로 118개 페이지 전체 41개 네임스페이스로 계산됩니다. 대부분 토큰 비용입니다 -- Haiku는 입력 토큰 100만 개당 $0.25, 출력 토큰 100만 개당 $1.25 (2025년 가격)로 매우 저렴합니다.

비용 비교: 우리의 방식 대 다른 방식들

이것은 Deluxe Astrology 팀을 확신시킨 표입니다:

방식 30개 언어 비용 지속적 비용 품질 출시 시간
Claude Haiku + Winston AI ~$660 총액 (언어당 $22) $0 (일회성) 95%+ 품질 게이트, 핵심 페이지에 대한 인간 검토 2-3주 롤링
Weglot $0 설정 월 $699 (연 $8,388) 기계 번역, 편집 가능 즉시 하지만 위험
전문 번역사 $150K-$300K (언어당 $5K-10K) 언어당 $2K-5K 업데이트 최고 품질 3-6개월
DeepL API ~$400 총액 $0 (일회성) 좋음 하지만 품질 게이트 없음 1-2주
Google Translate API ~$300 총액 $0 (일회성) 틈새 콘텐츠에 낮은 품질 1주

솔직하게 말하겠습니다: Claude Haiku 번역의 $660 총 비용 30개 언어는 거의 의심스러울 정도로 저렴합니다. 함정은 품질 게이트 (Winston AI)와 인간 검토 레이어가 필요하다는 것입니다 프로덕션 준비를 위해. 이러한 비용도 포함하면 -- Winston AI API 호출을 위해 $50-100, 높은 가치 페이지에 대한 인간 검토를 위해 $500-1,000 -- 여전히 총 $2,000 미만입니다. Weglot의 월 $699와 비교하세요. 3개월 이내에 손익분기점이 됩니다.

Weglot 및 유사 서비스의 실제 문제점: 한 번에 모든 것을 번역합니다. 게이팅 없음. 페이지당 품질 제어 없음. 스위치를 켜면 갑자기 Google은 3,540개 페이지를 봅니다, 많은 것이 평범한 기계 번역입니다. 우리의 접근 방식은 수술적으로 처리할 수 있게 합니다.

우리는 가격 책정 페이지에서 이런 프로젝트에 접근하는 방식에 대해 더 이야기합니다 -- 번역 파이프라인은 더 큰 헤드리스 CMS 개발 아키텍처의 한 요소입니다.

로케일 인식 구조화된 데이터 마크업

이것은 거의 모든 사람을 놀라게 합니다. 구조화된 데이터는 페이지 언어와 일치해야 합니다. 영어 FAQ 스키마가 있는 독일어 페이지는 페이지 언어에 대한 Google의 이해를 혼란스럽게 합니다.

// utils/schema.ts
export function generateFAQSchema(
  faqs: Array<{ question: string; answer: string }>,
  locale: string
) {
  return {
    '@context': 'https://schema.org',
    '@type': 'FAQPage',
    'inLanguage': locale, // 중요: 페이지 로케일과 일치해야 합니다
    'mainEntity': faqs.map((faq) => ({
      '@type': 'Question',
      'name': faq.question, // 대상 언어여야 합니다
      'acceptedAnswer': {
        '@type': 'Answer',
        'text': faq.answer // 대상 언어여야 합니다
      }
    }))
  };
}

inLanguage를 지원하는 모든 스키마 유형이 이를 사용해야 합니다. Deluxe Astrology의 경우 다음이 포함됩니다:

  • FAQPage -- 대상 언어의 질문과 답변
  • Article -- 로케일과 일치하는 inLanguage
  • WebPage -- inLanguage 속성
  • BreadcrumbList -- 대상 언어의 이름

보이는 콘텐츠만 번역하고 구조화된 데이터는 잊지 마세요. Google은 둘 다 읽습니다.

순위를 망칠 일반적인 실수들

x-default hreflang 누락

이것을 상수 봅니다. 사이트는 모든 언어에 대해 hreflang을 구현하지만 x-default를 잊습니다. 이것이 없으면 Google은 사용자의 언어가 버전과 일치하지 않는 경우 폴백이 없습니다. 항상 포함하세요. 항상 기본 언어 (보통 영어)를 가리키세요.

URL과 콘텐츠의 불일치하는 로케일

URL이 /fr/horoscope라고 하지만 페이지 콘텐츠는 번역이 로드되지 않았거나 폴백되었기 때문에 영어인 경우, Google은 이것을 소프트 404 또는 얇은 콘텐츠로 플래그 지정합니다. 이것이 정확히 우리가 2단계 게이팅 시스템을 구축한 이유입니다 -- 페이지는 프랑스어 콘텐츠를 가질 때까지 프랑스어 URL을 가져올 수 없습니다.

한 번에 모든 언어 출시

나는 이미 이 점을 두드렸지만 반복할 가치가 있습니다. 동시에 30개 언어를 출시하는 것은 국제 SEO의 가장 일반적인 실수입니다. 번역이 완벽하더라도, Google에 3-5개 언어 배치로 롤아웃하세요. GSC에서 인덱싱을 모니터링하세요. 그 다음 더 추가하세요.

상호 hreflang 태그

페이지 A (영어)가 hreflang을 통해 페이지 B (독일어)를 가리키면, 페이지 B는 페이지 A로 다시 가리켜야 합니다. 이 상호 링크가 누락되면 Google은 hreflang을 완전히 무시합니다. 동적으로 생성할 때 (우리처럼), 상호성은 자동입니다. 하지만 수동으로 관리하는 경우, 정기적으로 감사하세요.

자체 참조 hreflang 누락

모든 페이지는 자신의 hreflang 세트에 포함되어야 합니다. 독일어 페이지는 자신을 가리키는 hreflang="de"를 나열해야 합니다. 이것은 수동 구현에서 놓치기 쉽습니다.

한 위치에만 Hreflang

hreflang을 <head>에만 또는 사이트맵에만 넣는 것은 실수입니다. 둘 다 사용하세요. 안전빠침. Google은 두 출처를 모두 처리하며, 하나가 크롤링되지 않으면, 다른 하나가 백업으로 제공됩니다.

이 규모의 프로젝트의 경우, 경험 많은 팀이 이러한 함정을 피하는 데 도움이 됩니다. 다국어 빌드를 계획하고 있다면, 우리는 접근 방식을 논의할 수 있습니다.

FAQ

언어 차이만 있고 지역 차이가 없는 경우 hreflang 태그가 필요합니까?

네. Google의 언어 감지가 2025년에 개선되었지만, hreflang은 여전히 검색 엔진에 어떤 언어 버전을 제공할지 알려주는 최종적인 신호입니다. 이것이 없으면 Google이 단순히 영어 버전이 더 많은 백링크를 가지고 있기 때문에 영어 페이지를 프랑스어 사용자에게 표시할 위험이 있습니다. Hreflang은 10개 이상의 언어를 가질 때 더욱 중요해집니다 -- 언어 간 잠식 확률이 규모에 따라 증가합니다.

단일 페이지에 대한 hreflang 항목이 너무 많은 것은 얼마나 많습니까?

Google은 공식 제한을 발표하지 않았지만, 실제 테스트에서는 페이지당 50개 언어 변형을 초과하면 수익 감소 및 간헐적 파싱 문제가 시작됩니다. 우리의 30개 언어 설정의 경우, 각 페이지는 31개 hreflang 항목을 가집니다 (30개 언어 + x-default), 이것은 안전 영역 내입니다. 50개 이상의 지역 및 언어 조합을 다루는 경우, <head> 크기를 관리 가능하게 유지하기 위해 XML 사이트맵 접근만 사용하는 것을 고려하세요.

hreflang을 HTML head, XML 사이트맵 또는 HTTP 헤더에서 사용해야 합니까?

Next.js 애플리케이션의 경우, HTML <head>와 XML 사이트맵을 모두 사용하세요. HTTP 헤더는 주로 PDF와 같은 비-HTML 리소스에 유용합니다. HTML <head> 접근은 크롤 시간에 처리되며 가장 빠른 신호를 제공합니다. 사이트맵은 백업으로 작동하며 Google이 아직 크롤링하지 않은 대체 페이지를 발견하는 데 도움이 됩니다. 우리는 단 하나의 방법에만 의존하는 것을 권장하지 않습니다.

2025년에 AI로 전체 웹사이트를 번역하는 비용은 얼마입니까?

Claude Haiku를 사용하면 118개 페이지를 41개 네임스페이스에 걸쳐 대략 언어당 $22에 번역합니다. 30개 언어의 경우 총 약 $660입니다. 대략 $50-100 API 호출을 위한 Winston AI 품질 게이팅, 그리고 높은 가치 페이지에 대한 선택적 인간 검토 $500-1,000를 추가하면, 전부 포함 비용은 $2,000 미만입니다. Weglot의 월 $699 또는 전문 번역 서비스 언어당 $5,000-10,000과 비교하세요.

모든 것을 한 번에 번역하는 대신 왜 2단계 번역 게이팅 시스템을 사용합니까?

Google은 얇은 콘텐츠를 전체 도메인을 끌어내릴 수 있는 부정적 품질 신호로 취급합니다. 30개 언어를 출시하지만 15개만 품질 번역이 있으면, 그 15개 형편한 번역 언어가 대략 1,770개의 낮은 품질 페이지를 생성합니다. 2단계 시스템은 95%+ 품질 임계값을 충족하는 페이지만 인덱싱되도록 보장합니다. 언어는 번역이 품질 게이트를 통과할 때 계층 2에서 계층 1로 승격되어, 롤아웃 전반에 걸쳐 도메인 권위를 보호합니다.

부분 번역된 로케일에서 번역되지 않은 페이지를 어떻게 처리합니까?

일부 네임스페이스는 번역되었지만 다른 네임스페이스는 번역되지 않은 로케일의 경우, 우리는 영어 콘텐츠로 폴백하고 미들웨어를 통해 noindex 메타 태그를 추가합니다. URL은 여전히 해결됩니다 (사용자가 액세스할 수 있음), 하지만 Google은 혼합 언어 페이지를 인덱싱하지 않습니다. 모든 필수 네임스페이스가 품질 게이트를 통과하면, noindex 태그가 제거되고 hreflang 항목이 추가됩니다. 이것은 부분 번역이 색인을 오염시키는 것을 방지합니다.

AI 번역을 위해 어떤 품질 점수 임계값을 사용해야 합니까?

우리는 Winston AI를 95%+ 품질 점수 임계값으로 사용합니다. 그 이하는 인간 검토 또는 조정된 프롬프트로의 재번역을 위해 플래그 지정됩니다. 실제로, Claude Haiku는 첫 번역에서 약 85%의 네임스페이스 배치에서 95%를 달성합니다. 나머지 15%는 일반적으로 도메인 특정 용어 (직접 번역하지 않는 점성술 용어) 또는 복잡한 문장 구조로 인해 실패합니다. 90% 임계값은 눈에 띄게 어색한 표현을 통과시킬 것입니다.

다국어 사이트를 위해 hreflang으로 대신 Astro를 사용할 수 있습니까?

절대적으로. Astro는 Astro 4.0+ 이후로 우수한 i18n 지원을 기본 제공하며, 정적 생성 모델은 실제로 모든 URL이 빌드 시간에 알려져 있기 때문에 hreflang 구현을 단순화합니다. 우리는 두 프레임워크 모두로 다국어 프로젝트를 구축했습니다. 무거운 동적 콘텐츠와 API 경로를 가진 사이트 (Deluxe Astrology의 39개 로케일 인식 엔드포인트)의 경우, Next.js가 더 좋습니다. 상호작용이 적은 콘텐츠 무거운 사이트의 경우, Astro 개발이 더 빠르고 성능이 좋을 수 있습니다. hreflang 원칙은 프레임워크에 관계없이 동일합니다.