## index.html (기반 메타태그) - title: 풀네임 + 키워드 포함 - description: 160자 최적화 - keywords: 지오정보기술·GUARDiA·공공기관IT·안산IT기업 등 - og:type/title/description/url/image/locale - twitter:card/title/description/image - JSON-LD: Organization (주소·전화·대표자) + WebSite 스키마 - 네이버/구글 서치콘솔 인증 주석 준비 ## public/sitemap.xml (26개 URL) - priority: 홈 1.0, GUARDiA 0.9, 오시는길·문의 0.8 - changefreq: 뉴스/공지 weekly, 솔루션 monthly, 약관 yearly ## public/robots.txt - Googlebot/Yeti(네이버) Allow, Baiduspider Disallow - /admin/ /api/ Disallow - Sitemap 경로 명시 ## hooks/useSeoMeta.js - 페이지별 title/description/og/twitter/canonical 동적 업데이트 ## 적용 페이지 (6개) - Home: AI 인프라 자율 운영 키워드 - GuardiaDetail: GUARDiA ITSM 상세 설명 - Company>Greeting: CEO 인사말·홍영택 - Company>Location: 안산 주소·전화번호 - Privacy/Terms/Sitemap: 각 페이지 설명 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
61 lines
2.3 KiB
JavaScript
61 lines
2.3 KiB
JavaScript
import { useEffect } from 'react';
|
|
|
|
const BASE = 'https://zioinfo.co.kr';
|
|
const SITE = '(주)지오정보기술';
|
|
|
|
/**
|
|
* 페이지별 SEO 메타태그 동적 업데이트.
|
|
* @param {Object} opts
|
|
* @param {string} opts.title 페이지 제목 (| 사이트명 자동 추가)
|
|
* @param {string} opts.description 페이지 설명 (160자 이내 권장)
|
|
* @param {string} [opts.path] 정규 URL 경로 (예: '/solution/guardia')
|
|
* @param {string} [opts.image] OG 이미지 URL
|
|
* @param {string} [opts.keywords] 추가 키워드 (콤마 구분)
|
|
*/
|
|
export function useSeoMeta({ title, description, path = '', image = '/logo.png', keywords = '' }) {
|
|
useEffect(() => {
|
|
const fullTitle = title ? `${title} | ${SITE}` : SITE;
|
|
const canonical = `${BASE}${path}`;
|
|
const ogImage = image.startsWith('http') ? image : `${BASE}${image}`;
|
|
|
|
// title
|
|
document.title = fullTitle;
|
|
|
|
// 메타 업데이트 헬퍼
|
|
const set = (selector, attr, value) => {
|
|
let el = document.querySelector(selector);
|
|
if (!el) {
|
|
el = document.createElement('meta');
|
|
const [k, v] = selector.replace('meta[', '').replace(']', '').split('=');
|
|
el.setAttribute(k, v.replace(/"/g, ''));
|
|
document.head.appendChild(el);
|
|
}
|
|
el.setAttribute(attr, value);
|
|
};
|
|
|
|
// canonical
|
|
let canonical_el = document.querySelector('link[rel="canonical"]');
|
|
if (!canonical_el) {
|
|
canonical_el = document.createElement('link');
|
|
canonical_el.rel = 'canonical';
|
|
document.head.appendChild(canonical_el);
|
|
}
|
|
canonical_el.href = canonical;
|
|
|
|
// 기본
|
|
set('meta[name="description"]', 'content', description);
|
|
if (keywords) set('meta[name="keywords"]', 'content', keywords);
|
|
|
|
// OG
|
|
set('meta[property="og:title"]', 'content', fullTitle);
|
|
set('meta[property="og:description"]', 'content', description);
|
|
set('meta[property="og:url"]', 'content', canonical);
|
|
set('meta[property="og:image"]', 'content', ogImage);
|
|
|
|
// Twitter
|
|
set('meta[name="twitter:title"]', 'content', fullTitle);
|
|
set('meta[name="twitter:description"]', 'content', description);
|
|
set('meta[name="twitter:image"]', 'content', ogImage);
|
|
}, [title, description, path, image, keywords]);
|
|
}
|