Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- react 배열 재정렬하기
- 리액트 dragdrap
- 코어자바스트립트
- 자바스크립트 검색 구현하기
- new Promise()
- 초집합
- 올리브영 발색비교 기능구현하기
- 검색 자동완성
- 순수함수
- debound
- 자바스크립트 reduce 함수 직접 만들어보기
- react-beautiful-dnd
- JavaScript
- range 함수 직접 만들기
- 프로미스
- 자바스크립트
- 유저접근제한
- 넥스트 검색엔진최적화
- 프로미스 직접 구현하기
- 리엑트 검색 기능 구현하기
- 리액트 이미지 미리보기
- 자바스크립트로 하는 자료 구조와 알고리즘
- 리액트 고차컴포넌트
- 러닝리액트
- next seo
- 자바스크립트로 달력만들기
- react search input
- 노드교과서
- search input
- compose 함수
Archives
- Today
- Total
미주알고주알
[Next.js] SEO 태그를 사용해 검색 엔진 최적화 적용하기 본문
Next에서 검색 엔진 최적화를 위한 SEO meta 태그의 예시 작성함.
사용법? 원하는 페이지 뷰에 맞게 해당 meta 태그를 같이 사용해주면 된다. 이때, 태그에 들어갈 데이터는 `getServerSideProp`라는 SSR 메소드와 함께 사용하여 초기 렌더링 데이터 자체를 서버에서 먼저 제공하여 말 그대로 검색 엔진 최적화를 완성한다.
import Head from 'next/head'
import { FC, ReactNode, Fragment } from 'react'
import config from '@config/seo_meta.json'
const siteUrl = process.env.PUBLIC_SITE_URL
const siteBaseUrl = siteUrl ? `https://${siteUrl}` : null
interface Props {
title?: string
description?: string
robots?: string
openGraph?: {
title?: string
type?: string
locale?: string
description?: string
site_name?: string
url?: string
images?: OgImage[]
}
children: ReactNode
}
interface OgImage {
url?: string
width?: string
height?: string
alt?: string
}
const ogImage = ({ url, width, height, alt }: OgImage, index: number) => {
const imgUrl = siteBaseUrl ? new URL(url!, siteBaseUrl).toString() : url
return (
<Fragment key={`og:image:${index}`}>
<meta
key={`og:image:url:${index}`}
property="og:image"
content={imgUrl}
/>
<meta
key={`og:image:width:${index}`}
property="og:image:width"
content={width}
/>
<meta
key={`og:image:height:${index}`}
property="og:image:height"
content={height}
/>
<meta
key={`og:image:alt:${index}`}
property="og:image:alt"
content={alt}
/>
</Fragment>
)
}
const SEO: FC<Props> = ({
title,
description,
openGraph,
robots,
children,
}) => {
return (
<Head>
<title key="title">{title}</title>
<meta
key="description"
name="description"
content={description ?? config.description}
/>
<meta
key="og:type"
property="og:type"
content={openGraph?.type ?? config.openGraph.type}
/>
<meta
key="og:title"
property="og:title"
content={
openGraph?.title ?? config.openGraph.title ?? title ?? config.title
}
/>
<meta
key="og:description"
property="og:description"
content={
openGraph?.description ??
config.openGraph.description ??
description ??
config.description
}
/>
<meta
key="og:site_name"
property="og:site_name"
content={openGraph?.site_name ?? config.openGraph.site_name}
/>
<meta
key="og:url"
property="og:url"
content={openGraph?.url ?? config.openGraph.url}
/>
<meta key="og:locale" property="og:locale" content={openGraph?.locale} />
{openGraph?.images?.length
? openGraph.images?.map((img, i) => ogImage(img, i))
: ogImage(config.openGraph.images[0], 0)}
{config.twitter.cardType && (
<meta
key="twitter:card"
name="twitter:card"
content={config.twitter.cardType}
/>
)}
{config.twitter.site && (
<meta
key="twitter:site"
name="twitter:site"
content={config.twitter.site}
/>
)}
{config.twitter.handle && (
<meta
key="twitter:creator"
name="twitter:creator"
content={config.twitter.handle}
/>
)}
<meta key="robots" name="robots" content={robots ?? 'index,follow'} />
<meta
key="googlebot"
name="googlebot"
content={robots ?? 'index,follow'}
></meta>
{children}
</Head>
)
}
export default SEO
여기서 `config`파일은 정적 데이터를 따로 분리해 관리함.
json 파일 대신 .ts 파일도 사용해도 되지만 key 에 대한 타입 추론도 추가되어야 한다! (`keyof typeof SeoMeta`)
더 나아가 다음을 통해 여러 `ogImage`를 동시에 처리하는 것 뿐만 아니라 `structuredData`(구글-구조화된 데이터) 를 통해 검색 엔진이 해당 페이지의 데이터를 더 잘 이해할 수 있도록 일련의 논리적인 레시피처럼 정리해두는 것도 구현할 수 있다.
function DetailSEO({
title,
description,
openGraph,
robots,
children,
}: Props) {
const { title, type, locale, description, site_name, url, images } = openGraph
const { asPath: path } = useRouter()
const imageArr =
!images || images.length === 0
? [config.banner]
: typeof images === 'string'
? [images]
: images
const featuredImages = imageArr.map((image) => ({
'@type': 'ImageObject',
url: ['https', 'http'].includes(image.split('://')[0]) ? image : config.siteUrl + image,
}))
const structuredData = {
'@context': 'https://schema.org',
'@type': 'Detail Page',
mainEntityOfPage: {
'@type': 'WebPage',
'@id': path,
},
headline: ogTitle,
image: featuredImages,
author: {
'@type': 'Person',
name: config.author,
},
publisher: {
logo: {
'@type': 'ImageObject',
url: config.siteUrl + config.siteLogo,
},
},
description: description,
datePublished: config.datePublished,
}
return (
<>
<SEO
title={title},
description={description},
openGraph={openGraph}
robots={robots}>
<Head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(structuredData, null, 2),
}}
/>
</Head>
</SEO>
)
}
'Next.js' 카테고리의 다른 글
Next.js에서 url 바꾸는 방법 3가지 (0) | 2023.02.16 |
---|---|
Next.js의 서버 사이드 렌더링 기술 3가지 (0) | 2023.02.16 |