์ž‘๊ฐ€:
    ์ƒ์„ฑ:2026-08-29๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ:2026-08-29

    Hreflang: ๋‹ค๊ตญ์–ด SEO ๊ฐ€์ด๋“œ

    ์•ฑ์„ ๋ฒˆ์—ญํ–ˆ์Šต๋‹ˆ๋‹ค. /en, /fr, /es๋ฅผ ๋ฐฐํฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ํ”„๋ž‘์Šค ์‚ฌ์šฉ์ž๋“ค์€ ์—ฌ์ „ํžˆ ์˜๋ฌธ ํŽ˜์ด์ง€์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

    ๋ฒˆ์—ญ์€ ์‰ฌ์šด ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์–ด๋ ค์šด ๋ถ€๋ถ„์€ ๊ฒ€์ƒ‰ ์—”์ง„์— ์ด ํŽ˜์ด์ง€๋“ค์ด ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๋œ ๊ฐ™์€ ํŽ˜์ด์ง€์ด์ง€, ์„œ๋กœ ๊ฒฝ์Ÿํ•˜๋Š” ์„ธ ๊ฐœ์˜ ๋ฌธ์„œ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์•Œ๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด hreflang์ด ํ•˜๋Š” ์ผ์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๊ตญ์–ด ์‚ฌ์ดํŠธ๊ฐ€ ์กฐ์šฉํžˆ ํŠธ๋ž˜ํ”ฝ์„ ์žƒ๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.

    hreflang์ด ์‹ค์ œ๋กœ ๋ฌด์—‡์ธ๊ฐ€

    ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ฃผ์„์œผ๋กœ, ์ด URL์€ ์ € ์–ธ์–ด๋“ค์„ ์œ„ํ•ด ๋‹ค๋ฅธ ๊ณณ์— ๋™๋“ฑํ•œ ๋ฒ„์ „์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    html
    <link rel="alternate" hreflang="en" href="https://example.com/about" />
    <link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
    <link rel="alternate" hreflang="es" href="https://example.com/es/about" />
    <link rel="alternate" hreflang="x-default" href="https://example.com/about" />
    

    ๋‘ ๊ฐ€์ง€๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ฌ๋ฐ”๋ฅธ ๋ฒ„์ „์ด ํ‘œ์‹œ๋˜๊ณ , ๋กœ์ผ€์ผ์ด ์ค‘๋ณต์œผ๋กœ ์„œ๋กœ ๊ฒฝ์Ÿํ•˜๋Š” ๋Œ€์‹  ํ•˜๋‚˜์˜ ํด๋Ÿฌ์Šคํ„ฐ๋กœ ํ†ตํ•ฉ๋ฉ๋‹ˆ๋‹ค.

    ์ด๊ฒƒ์ด ๋ฌด์—‡์ด ์•„๋‹Œ์ง€ ๋ช…ํ™•ํžˆ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค โ€” ํžŒํŠธ์ผ ๋ฟ์ด๋ฉฐ, Google์ด ์ด๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ˆœ์œ„ ๋ถ€์ŠคํŠธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค โ€” ์ˆœ์œ„ ์—ฌ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ ์–ด๋А ๋ฒ„์ „์ด ์ˆœ์œ„๋ฅผ ์–ป์„์ง€ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Bing์€ ์ด๋ฅผ ์™„์ „ํžˆ ๋ฌด์‹œํ•˜๋ฉฐ ๋Œ€์‹  content-language์™€ ์ง€์—ญ ํƒ€๊ฒŒํŒ…์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค.

    ์„ ์–ธ ์œ„์น˜

    ์„ธ ๊ฐ€์ง€ ๋ฐฐ์น˜, ๋ชจ๋‘ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜๊ณ  ๊ฑฐ๊ธฐ์— ๋จธ๋ฌผ๋Ÿฌ ์žˆ์œผ์„ธ์š” โ€” ๊ฐ™์€ ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ๋‘ ๊ณณ์—์„œ ์„ ์–ธ๋˜๋ฉด ์„ธํŠธ๊ฐ€ ๋ถ„์‚ฐ๋˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

    HTML <head>๋Š” ์ผ๋ฐ˜์ ์ธ ์„ ํƒ์ž…๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ์ฃผ์˜์‚ฌํ•ญ: hydration ํ›„์— ์ฃผ์ž…๋œ ํƒœ๊ทธ๋Š” ์‹ ๋ขฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ํฌ๋กค๋Ÿฌ๊ฐ€ ์ด๋ฅผ ๋ณผ ์ˆ˜ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    XML sitemap์€ ๊ทœ๋ชจ๊ฐ€ ํด ๋•Œ ๋” ์ข‹์Šต๋‹ˆ๋‹ค. 10๊ฐœ์˜ ๋กœ์ผ€์ผ์— ๊ฑธ์ณ 5,000๊ฐœ์˜ ํŽ˜์ด์ง€๊ฐ€ ์žˆ์œผ๋ฉด 50,000๊ฐœ์˜ <link> ์š”์†Œ๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์— ์ „์†ก๋˜๋Š”๋ฐ ์•„๋ฌด ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. sitemap์—์„œ๋Š” ํŽ˜์ด์ง€์— 0๋ฐ”์ดํŠธ๊ฐ€ ์†Œ์š”๋ฉ๋‹ˆ๋‹ค.

    HTTP Link header๋Š” PDF์™€ ๊ฐ™์€ non-HTML ํŒŒ์ผ์˜ ์œ ์ผํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

    ๊ทœ์น™

    Self-reference์™€ ์ƒํ˜ธ์„ฑ

    /fr/about์˜ ์ง‘ํ•ฉ์—๋Š” /fr/about์„ ๊ฐ€๋ฆฌํ‚ค๋Š” hreflang="fr"์ด ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  /about์ด /fr/about์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค๋ฉด, /fr/about์€ ๋ฐ˜๋“œ์‹œ ๋‹ค์‹œ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. Google์€ ๋‹จ๋ฐฉํ–ฅ ์ฐธ์กฐ๋ฅผ "no return tag"๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

    ์‹ค์ œ๋กœ๋Š” ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ชจ๋“  ํŽ˜์ด์ง€๊ฐ€ ๋™์ผํ•œ ๋งํฌ ์ง‘ํ•ฉ์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ณต์œ ๋œ ๋กœ์ผ€์ผ ๋ชฉ๋ก์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ํŽธ์˜์„ฑ์ด ์•„๋‹ˆ๋ผ ๋‘ ๊ฐœ ์ด์ƒ์˜ ๋กœ์ผ€์ผ์ด ์žˆ์„ ๋•Œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์œ ์ง€ํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    ์ ˆ๋Œ€ URL, ํ•ญ์ƒ

    html
    <!-- ์ž๋™์œผ๋กœ ๋ฌด์‹œ๋จ -->
    <link rel="alternate" hreflang="fr" href="/fr/about" />
    
    <!-- ์˜ฌ๋ฐ”๋ฆ„ -->
    <link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
    

    ์ด ์ด์œ ๋ฅผ ์•”๊ธฐํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. hreflang์€ cross-document ์ฐธ์กฐ์ž…๋‹ˆ๋‹ค: ๊ฒ€์ƒ‰ ์—”์ง„์€ URL์„ ํ‚ค๋กœ ํ•˜๋Š” cluster๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ , ์ด๋ฅผ cluster ๋‚ด์˜ ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. ์ƒ๋Œ€ ๊ฒฝ๋กœ๋Š” ๊ทธ๊ฒƒ์ด ํฌํ•จ๋œ ๋ฌธ์„œ์— ์ƒ๋Œ€์ ์ธ ์˜๋ฏธ๋งŒ ๊ฐ€์ง€๋ฏ€๋กœ, ์ด๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ host๋ฅผ ๋„˜์„ ์ˆ˜ ์—†์œผ๋ฉฐ, locale์ด example.fr ๋˜๋Š” fr.example.com์— ์žˆ์„ ๋•Œ alternate๋Š” ์ข…์ข… host๋ฅผ ๋„˜์Šต๋‹ˆ๋‹ค. sitemap์ด๋‚˜ HTTP header์—๋Š” resolveํ•  base document๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค.

    ์ด๊ฒƒ์€ ์ฝ”๋“œ์— ์ง์ ‘์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. getLocalizedUrl("/about", "fr")๋Š” /fr/about์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค โ€” ์ƒ๋Œ€ ๊ฒฝ๋กœ ์ž…๋ ฅ, ์ƒ๋Œ€ ๊ฒฝ๋กœ ์ถœ๋ ฅ. hreflang์˜ ๊ฒฝ์šฐ ์ ˆ๋Œ€ URL์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

    ts
    getLocalizedUrl("/about", "fr"); // โ†’ "/fr/about"          โŒ ์‚ญ์ œ๋จ
    getLocalizedUrl("https://example.com/about", "fr"); // โ†’ "https://example.com/fr/about"  โœ…
    

    ํ•œ ๊ฐ€์ง€ ์˜ˆ์™ธ๋Š” ๋ Œ๋”๋ง ์ „์— ์ƒ๋Œ€ ๊ฐ’์„ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค: Next.js๋Š” ์ƒ๋Œ€ alternates๋ฅผ metadataBase์— ๋Œ€ํ•ด ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. ์ข‹์Šต๋‹ˆ๋‹ค โ€” ํ•˜์ง€๋งŒ ๊ทœ์น™์€ ์ƒ์„ฑ๋œ HTML์— ์ ์šฉ๋˜๋ฏ€๋กœ, DevTools inspector๊ฐ€ ์•„๋‹Œ curl๋กœ ํ™•์ธํ•˜์„ธ์š”.

    ์–ธ์–ด ์ฝ”๋“œ

    ์–ธ์–ด๋Š” ISO 639-1, ์„ ํƒ์  ์ง€์—ญ์€ ISO 3166-1 Alpha 2: fr, fr-CA, pt-BR.

    ๋‘ ๊ฐ€์ง€ ํ•จ์ •์ด ๊ฑฐ์˜ ๋ชจ๋“  ์‚ฌ๋žŒ์„ ์žก์•„๋ƒ…๋‹ˆ๋‹ค. ์ง€์—ญ๋งŒ์œผ๋กœ๋Š” ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” hreflang="ca"๋Š” ์นดํƒˆ๋กœ๋‹ˆ์•„์–ด์ด์ง€, ์บ๋‚˜๋‹ค๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค; en-CA ๋˜๋Š” fr-CA๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  en-UK๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: ์˜๊ตญ์˜ ๊ตญ๊ฐ€ ์ฝ”๋“œ๋Š” GB์ด๋ฏ€๋กœ en-GB์ž…๋‹ˆ๋‹ค.

    ์ง€์—ญ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ๊ทธ ์ง€์—ญ์— ๋‹ค๋ฅธ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•  ๋•Œ๋งŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค โ€” ๋‹ค๋ฅธ ๊ฐ€๊ฒฉ, ๋‹ค๋ฅธ ๋ฒ•์  ๊ณต์ง€. ๋™์ผํ•œ ์ฝ˜ํ…์ธ ์—์„œ fr๊ณผ fr-FR์€ ๋…ธ์ด์ฆˆ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

    x-default

    html
    <link rel="alternate" hreflang="x-default" href="https://example.com/" />
    

    ๊ฐ€์žฅ ์ž์ฃผ ์žŠํ˜€์ง€๊ณ , ์ž˜๋ชป ์ดํ•ด๋˜๋Š” ๊ฐœ๋…์€ x-default์ž…๋‹ˆ๋‹ค โ€” ์•ฑ์˜ 30% ๋ฏธ๋งŒ๋งŒ ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

    ์ด๋Š” ๊ท€ํ•˜์˜ ์ง‘ํ•ฉ์—์„œ ์–ด๋–ค ์–ธ์–ด์™€๋„ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ํด๋ฐฑ์ž…๋‹ˆ๋‹ค. ์˜์–ด, ํ”„๋ž‘์Šค์–ด, ์ŠคํŽ˜์ธ์–ด๋งŒ ์ œ๊ณตํ•˜๋Š” ์‚ฌ์ดํŠธ์— ์žˆ๋Š” ๋„ค๋œ๋ž€๋“œ์–ด ์‚ฌ์šฉ์ž๋Š” ์–ด๋–ค ํ•ญ๋ชฉ๊ณผ๋„ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. x-default๊ฐ€ ์—†์œผ๋ฉด Google์ด ์ž๋™์œผ๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

    ์‚ฌ๋žŒ๋“ค์ด ์ž˜๋ชป ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ ๊ทธ ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. x-default๋Š” "์˜์–ด ๋ฒ„์ „"์ด ์•„๋‹ˆ๋ฉฐ "๊ธฐ๋ณธ ๋กœ์ผ€์ผ"๋„ ์•„๋‹™๋‹ˆ๋‹ค. ๋น„๋ก ๋Œ€๊ฐœ ๊ทธ๊ณณ์„ ๊ฐ€๋ฆฌํ‚ค์ง€๋งŒ ๋ง์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ด ์ง‘ํ•ฉ์ด ๋‹ค๋ฃจ์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ํŽ˜์ด์ง€๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ •๋‹นํ•œ ์ด์œ ์ด๋ฉฐ, ์ข…์ข… ๋” ๋‚˜์€ ์ด์œ ์ด๊ธฐ๋„ ํ•œ๋ฐ, /en ๋Œ€์‹  ์–ธ์–ด ์„ ํƒ๊ธฐ๋‚˜ ์ง€์—ญ ๋ฆฌ๋””๋ ‰์…˜ ๋žœ๋”ฉ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌํ•œ ํŽ˜์ด์ง€๊ฐ€ ์—†๋‹ค๋ฉด ๊ท€ํ•˜์˜ ์ฃผ์š” ์–ธ์–ด๊ฐ€ ํ•ฉ๋ฆฌ์ ์ธ ๋‹ต๋ณ€์ž…๋‹ˆ๋‹ค.

    ๋‘ ๊ฐ€์ง€๋ฅผ ๋ช…ํ™•ํžˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: x-default๋Š” self-referencing ํ•ญ๋ชฉ์„ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์„ธํŠธ์˜ ์ถ”๊ฐ€ ํ•ญ๋ชฉ์ด๋ฉฐ, ๋‹ค๋ฅธ ๋ชจ๋“  ํ•ญ๋ชฉ์ฒ˜๋Ÿผ ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ๋™์ผํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    canonical ํ•จ์ •

    ๊ฐ ๋กœ์ปฌ๋ผ์ด์ œ์ด์…˜๋œ ํŽ˜์ด์ง€๋Š” ์ž์‹ ์˜ canonical์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

    html
    <!-- https://example.com/fr/about์—์„œ -->
    <link rel="canonical" href="https://example.com/fr/about" />
    <link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
    <link rel="alternate" hreflang="en" href="https://example.com/about" />
    

    ๋ชจ๋“  ๋กœ์บ˜์˜ canonical์„ ์˜์–ด ๋ฒ„์ „์œผ๋กœ ๊ฐ€๋ฆฌํ‚ค๋ฉด:

    html
    <!-- https://example.com/fr/about์—์„œ โ€” ํŽ˜์ด์ง€๊ฐ€ ์‚ญ์ œ๋จ -->
    <link rel="canonical" href="https://example.com/about" />
    

    ํ”„๋ž‘์Šค ํŽ˜์ด์ง€๊ฐ€ ์ธ๋ฑ์‹ฑ๋˜์ง€ ์•Š์•„์•ผ ํ•˜๋Š” ์ค‘๋ณต์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๋ฐ˜๋ฉด, hreflang์€ ํ”„๋ž‘์Šค ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณตํ•  ํŽ˜์ด์ง€๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ์‹ ํ˜ธ๊ฐ€ ๋ชจ์ˆœ๋˜๊ณ , canonical์ด ์šฐ์„ ๋˜๋ฉฐ, ํ”„๋ž‘์Šค ํŽ˜์ด์ง€๊ฐ€ ์ธ๋ฑ์Šค์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

    Canonical์€ ๋กœ์ผ€์ผ๋ณ„๋กœ ์ž์ฒด ์ฐธ์กฐ์ž…๋‹ˆ๋‹ค. hreflang์€ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

    URL ๊ตฌ์กฐ ์„ ํƒ

    hreflang์€ URL์— ์ฃผ์„์„ ๋‹ฌ๋ฏ€๋กœ ๊ตฌ์กฐ๊ฐ€ ๋จผ์ € ์ •ํ•ด์ง‘๋‹ˆ๋‹ค.

    ๊ตฌ์กฐ์˜ˆ์‹œ์žฅ๋‹จ์ 
    ์„œ๋ธŒ๋””๋ ‰ํ† ๋ฆฌexample.com/fr/๋‹จ์ผ ๋„๋ฉ”์ธ, ๊ณต์œ  ๊ถŒํ•œ โ€” ์•ฝํ•œ ์ง€์—ญ ์‹ ํ˜ธ
    ์„œ๋ธŒ๋„๋ฉ”์ธfr.example.com๋กœ์ผ€์ผ ์ถ”๊ฐ€ ๋˜๋Š” ์ œ๊ฑฐ ์šฉ์ด โ€” ๋ณ„๋„ ์‚ฌ์ดํŠธ๋กœ ๋ณด์ผ ์ˆ˜ ์žˆ์Œ
    ccTLDsexample.fr๊ฐ€์žฅ ๊ฐ•ํ•œ ๊ตญ๊ฐ€ ์‹ ํ˜ธ โ€” ๋„๋ฉ”์ธ๋ณ„๋กœ ๊ตฌ์ถ•๋œ ๊ถŒํ•œ

    ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์„œ๋ธŒ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค. ccTLD์— ๋„๋‹ฌํ•˜๋Š” ๊ฒƒ์€ ์ •๋ง๋กœ ๋ณ„๋„์˜ ๊ตญ๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค๋กœ ์šด์˜ํ•  ๋•Œ๋งŒ์ž…๋‹ˆ๋‹ค.

    ํ”ผํ•ด์•ผ ํ•  ๊ตฌ์กฐ ํ•˜๋‚˜: Accept-Language ๋˜๋Š” IP์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๋™์ผํ•œ URL์—์„œ ๋‹ค๋ฅธ ์–ธ์–ด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํฌ๋กค๋Ÿฌ๋Š” ํ•œ ๋ฒ„์ „์„ ๋ณด๊ณ  ํ•œ ๋ฒ„์ „์„ ์ธ๋ฑ์‹ฑํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์€ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    Intlayer๋Š” routing.mode ๋ฐ routing.domains๋ฅผ ํ†ตํ•ด ์„ธ ๊ฐ€์ง€ ๋ชจ๋‘๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๋„๋ฉ”์ธ ๋ฐ ๊ตฌ์„ฑ ์ฐธ์กฐ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

    ๊ตฌํ˜„

    ์ด๋Ÿฌํ•œ ํƒœ๊ทธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋‘ ๋ฒˆ์งธ locale๊ณผ์˜ ์ ‘์ด‰์—์„œ ์œ ์ง€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  locale ๋ชฉ๋ก์—์„œ ํŒŒ์ƒ์‹œํ‚ค์„ธ์š”.

    1. ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ cluster ๋‚ด๋ณด๋‚ด๊ธฐ

      ๋ชจ๋“  ๊ณณ์—์„œ ๋™์ผํ•œ set, locale๋ณ„ canonical, ์ ˆ๋Œ€ URL, x-default ํฌํ•จ.

      Metadata API๋Š” alternates.languages๋ฅผ ๋…ธ์ถœํ•˜๊ณ , getMultilingualUrls๋Š” ๊ตฌ์„ฑ๋œ locale์—์„œ ์ „์ฒด record๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค:

      src/app/[locale]/about/page.tsx
      import { getMultilingualUrls } from "intlayer";
      import type { Metadata } from "next";
      import type { LocalPromiseParams } from "next-intlayer";
      
      const SITE_URL = "https://example.com";
      
      export const generateMetadata = async ({
        params,
      }: LocalPromiseParams): Promise<Metadata> => {
        const { locale } = await params;
      
        /**
         * getMultilingualUrls(`${SITE_URL}/about`)๋Š” ๋‹ค์Œ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:
         * {
         *   en: 'https://example.com/about',
         *   fr: 'https://example.com/fr/about',
         *   es: 'https://example.com/es/about',
         * }
         */
        const multilingualUrls = getMultilingualUrls(`${SITE_URL}/about`);
      
        return {
          alternates: {
            canonical: multilingualUrls[locale as keyof typeof multilingualUrls],
            languages: { ...multilingualUrls, "x-default": `${SITE_URL}/about` },
          },
        };
      };
      

      ์ „์ฒด ์„ค์ •: Next.js 16 i18n ๊ฐ€์ด๋“œ.

      ๋ผ์šฐํŠธ์˜ head ํ•จ์ˆ˜๊ฐ€ ๋งํฌ๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. localeMap์€ ์„ค์ •๋œ ๋กœ์ผ€์ผ์„ ๋ฐ˜๋ณตํ•˜๋ฏ€๋กœ, ์„ค์ •์— ๋กœ์ผ€์ผ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ•œ ๋ฒˆ์— ๋ชจ๋“  ๊ณณ์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค:

      src/routes/{-$locale}/about.tsx
      import { createFileRoute } from "@tanstack/react-router";
      import { defaultLocale, getLocalizedUrl, localeMap } from "intlayer";
      
      const SITE_URL = "https://example.com";
      
      export const Route = createFileRoute("/{-$locale}/about")({
        head: ({ params }) => {
          const { locale = defaultLocale } = params;
          const url = `${SITE_URL}/about`;
      
          return {
            links: [
              { rel: "canonical", href: getLocalizedUrl(url, locale) },
      
              ...localeMap(({ locale: mapLocale }) => ({
                rel: "alternate",
                hrefLang: mapLocale,
                href: getLocalizedUrl(url, mapLocale),
              })),
      
              {
                rel: "alternate",
                hrefLang: "x-default",
                href: getLocalizedUrl(url, defaultLocale),
              },
            ],
          };
        },
      });
      

      head๋Š” ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜๋ฏ€๋กœ ํƒœ๊ทธ๊ฐ€ ์ดˆ๊ธฐ HTML์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ „์ฒด ์„ค์ •: TanStack Start i18n guide.

    2. ๋˜๋Š” ๋ชจ๋“  ๊ฒƒ์„ sitemap์œผ๋กœ ์ด๋™

      ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด ํŽ˜์ด์ง€์—์„œ ์ฃผ์„์„ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜์„ธ์š”. generateSitemap์€ config์—์„œ ๋กœ์ผ€์ผ๊ณผ ๋ผ์šฐํŒ… ๋ชจ๋“œ๋ฅผ ์ฝ์–ด ํ•ญ๋ชฉ๋งˆ๋‹ค xhtml:link alternates๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

      src/routes/sitemap[.]xml.ts
      import { generateSitemap } from "intlayer";
      
      const sitemap = generateSitemap(
        [
          { path: "/", changefreq: "daily", priority: 1.0 },
          { path: "/about", changefreq: "monthly", priority: 0.8 },
        ],
        { siteUrl: "https://example.com" }
      );
      

      ์•Œ์•„๋‘๋ฉด ์ข‹์€ ๋‘ ๊ฐ€์ง€ ์˜ต์…˜:

      • xhtmlLinks (๊ธฐ๋ณธ๊ฐ’ true) โ€” alternates๋Š” locale URL์ด ์‹ค์ œ๋กœ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋งŒ emit๋ฉ๋‹ˆ๋‹ค. no-prefix ๋ชจ๋“œ์—์„œ๋Š” ๋ชจ๋“  locale์ด ํ•˜๋‚˜์˜ URL์„ ๊ณต์œ ํ•˜๋ฏ€๋กœ, routing.domains์—์„œ locale์— ์ž์ฒด ํ˜ธ์ŠคํŠธ๋ช…์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ํ•œ skip๋ฉ๋‹ˆ๋‹ค.
      • entryPerLocale (๊ธฐ๋ณธ๊ฐ’ false) โ€” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•˜๋‚˜์˜ <url> ํ•ญ๋ชฉ์ด ๋ชจ๋“  ๋Œ€์ฒด ์–ธ์–ด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋‘ ํ˜•์‹ ๋ชจ๋‘ ์œ ํšจํ•˜์ง€๋งŒ, <loc>์œผ๋กœ ๋‚˜์—ด๋œ URL๋งŒ Search Console์—์„œ ์ œ์ถœ๋จ์œผ๋กœ ๊ณ„์‚ฐ๋˜๋ฉฐ, ๋Œ€์ฒด ์–ธ์–ด ์ „์šฉ locale์€ ๋ฐœ๊ฒฌ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ sitemap์— ์†ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์„ ์ผœ๋ฉด ๋ชจ๋“  ์ง€์—ญํ™”๋œ URL์ด ์ž์ฒด ํ•ญ๋ชฉ์„ ๊ฐ€์ง€๊ณ  ์ „์ฒด ๋Œ€์ฒด ์–ธ์–ด ์„ธํŠธ๊ฐ€ ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ญ๋ชฉ ์ˆ˜๊ฐ€ locale ์ˆ˜๋งŒํผ ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ 50,000 URL / 50 MB ์ œํ•œ์„ ์ฃผ์˜ํ•˜๊ณ , ์ดˆ๊ณผํ•˜๋ฉด sitemap ์ธ๋ฑ์Šค๋กœ ๋ถ„ํ• ํ•˜์„ธ์š”.
    3. crawler๊ฐ€ ์ˆ˜์‹ ํ•˜๋Š” ๋‚ด์šฉ ํ™•์ธ

      hreflang์€ ์กฐ์šฉํžˆ ์‹คํŒจํ•˜๋ฏ€๋กœ, ๊ฐ€์ •ํ•˜์ง€ ๋ง๊ณ  ํ™•์ธํ•˜์„ธ์š”.

      ์†Œ์Šค๋ฅผ ์ฝ์œผ์„ธ์š”. ๊ฒ€์‚ฌ๊ธฐ๊ฐ€ ์•„๋‹Œ โ€” curl https://example.com/fr/about | grep hreflang๋Š” ํฌ๋กค๋Ÿฌ๊ฐ€ ๋ฐ›๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. DevTools๋Š” JavaScript๊ฐ€ ์‹คํ–‰๋œ ํ›„์˜ DOM์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ ๋Œ€์ฒด ํ•ญ๋ชฉ์„ ๋”ฐ๋ผ๊ฐ€์„œ ๋™์ผํ•œ ์ง‘ํ•ฉ์œผ๋กœ ๋‹ค์‹œ ๊ฐ€๋ฆฌํ‚ค๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๊ทธ ์ค‘ ์–ด๋А ๊ฒƒ๋„ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. Search Console์˜ ๊ตญ์ œ ํƒ€๊ฒŸํŒ… ๋ณด๊ณ ์„œ๋Š” ์ „์ฒด ์‚ฌ์ดํŠธ์—์„œ ๋‚˜๋จธ์ง€๋ฅผ ํฌ์ฐฉํ•ฉ๋‹ˆ๋‹ค.

      ๋‹ค๊ตญ์–ด ํŠนํ™” ํฌ๋กค๋ง์˜ ๊ฒฝ์šฐ, Intlayer SEO Scanner๋Š” ๋กœ์ปฌ๋ผ์ด์ฆˆ๋œ ํŽ˜์ด์ง€ ์ „์ฒด์—์„œ ๋ˆ„๋ฝ๋œ ํƒœ๊ทธ, ๋Š์–ด์ง„ ๋Œ€์ฒด ํ•ญ๋ชฉ ๋ฐ canonical ์ถฉ๋Œ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    ์ฒดํฌ๋ฆฌ์ŠคํŠธ

    • ๊ฐ ๋กœ์บ˜์€ ๊ณ ์œ ํ•˜๊ณ  ํฌ๋กค ๊ฐ€๋Šฅํ•œ URL์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค
    • ๋ชจ๋“  ํŽ˜์ด์ง€๋Š” ์ž์ฒด ์ฐธ์กฐํ•˜๋ฉฐ, ๋ชจ๋“  ์ฐธ์กฐ๋Š” ์ƒํ˜ธ์ ์ž…๋‹ˆ๋‹ค
    • ๋™์ผํ•œ ์ง‘ํ•ฉ์ด ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ชจ๋“  ํŽ˜์ด์ง€์— ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค
    • ๋ชจ๋“  href ๊ฐ’์ด emitted HTML์—์„œ ์ ˆ๋Œ€ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค
    • ์ฝ”๋“œ๋Š” ISO 639-1 + ISO 3166-1 Alpha 2์ž…๋‹ˆ๋‹ค (en-GB, en-UK ์•„๋‹˜)
    • x-default๊ฐ€ ์กด์žฌํ•˜๋ฉฐ, ๋งค์นญ๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋™ํ•ด์•ผ ํ•  ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค
    • Canonical์€ locale๋ณ„๋กœ ์ž์ฒด ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค
    • ํƒœ๊ทธ๋Š” ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๋ฉฐ, hydration ํ›„์— ์ฃผ์ž…๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
    • ์ •ํ™•ํžˆ ํ•œ ๊ณณ์—์„œ ์„ ์–ธ๋ฉ๋‹ˆ๋‹ค
    • Alternate ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค

    ๋งˆ๋ฌด๋ฆฌ

    hreflang์€ ๋‹จ์ˆœํ•˜๋ฉด์„œ๋„ ์—„๊ฒฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ๋ˆ„๋ฝ๋œ return ํƒœ๊ทธ, ํ•˜๋‚˜์˜ ์ƒ๋Œ€ URL, ํ•˜๋‚˜์˜ cross-locale canonical์ด ์žˆ์œผ๋ฉด ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์•„๋ฌด ์˜ค๋ฅ˜ ์—†์ด ๋ฒ„๋ ค์ง‘๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ๋ฌธ์ œ๋Š” ํƒœ๊ทธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐ์„œ ๋น„๋กฏ๋ฉ๋‹ˆ๋‹ค.

    ๋‹จ์ผ ๋กœ์ผ€์ผ ๋ชฉ๋ก์—์„œ ์„ธํŠธ๋ฅผ ๋„์ถœํ•˜๊ณ , ์„œ๋ฒ„ ์ธก์—์„œ ๋ Œ๋”๋งํ•˜๊ณ , canonical์„ ์ž๊ธฐ ์ฐธ์กฐ์ ์œผ๋กœ ์œ ์ง€ํ•˜๋ฉฐ, x-default์— ๊ทธ์— ๋งž๋Š” ๊ด€์‹ฌ์„ ๊ธฐ์šธ์ด์„ธ์š”. ํ•œ ๋ฒˆ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ •ํ™•์„ฑ ์œ ์ง€๊ฐ€ ๋” ์ด์ƒ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    ๋” ์•Œ์•„๋ณด๊ธฐ

    ๋Œ“๊ธ€

    ์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋กœ ์˜๊ฒฌ์„ ๋‚˜๋ˆ ๋ณด์„ธ์š”.

    ๊ด€๋ จ ๊ฒŒ์‹œ๋ฌผ

    ์ตœ๊ทผ ๊ฒŒ์‹œ๋ฌผ