diff --git a/components/meta/MetaHead.tsx b/components/meta/MetaHead.tsx
index fd160dad..df2f4c92 100644
--- a/components/meta/MetaHead.tsx
+++ b/components/meta/MetaHead.tsx
@@ -4,36 +4,59 @@ import 뎁구리_og from '@public/image/뎁구리/뎁구리_og.png';
import { META, SITE_URL } from '@/constants/metaData';
-const MetaHead = ({
- title,
- description,
- url,
- keyword,
- image,
-}: {
+export type MetaHeadProps = {
title?: string;
description?: string;
url?: string;
keyword?: string[];
image?: string;
-}) => {
+};
+
+const toAbsoluteUrl = (src: string) => {
+ if (/^https?:\/\//.test(src)) {
+ return src;
+ }
+
+ try {
+ return new URL(src, SITE_URL).toString();
+ } catch {
+ return `${SITE_URL}${src.startsWith('/') ? src : `/${src}`}`;
+ }
+};
+
+const MetaHead = ({ title, description, url, keyword, image }: MetaHeadProps) => {
+ const metaTitle = title ?? META.MAIN.title;
+ const metaDescription = description ?? META.MAIN.description;
+ const metaKeywords = (keyword ?? META.MAIN.keyword).join(',');
+ const metaUrl = url ?? SITE_URL;
+ const defaultImage = toAbsoluteUrl(뎁구리_og.src);
+ const metaImage = image ? toAbsoluteUrl(image) : defaultImage;
+
return (
- {title || META.MAIN.title}
-
+ {metaTitle}
+
-
-
+
+
+ {/* Open Graph */}
+
- {/* TODO: 최종 url은 변경 필요 */}
-
-
-
- {/* 트위터용 */}
-
-
-
+
+
+
+
+
+ {/* Twitter */}
+
+
+
+
+
+
+
);
};
+
export default MetaHead;
diff --git a/pages/_app.page.tsx b/pages/_app.page.tsx
index 31291867..23c4a3a1 100644
--- a/pages/_app.page.tsx
+++ b/pages/_app.page.tsx
@@ -8,7 +8,7 @@ import { QueryClient, QueryClientProvider, HydrationBoundary } from '@tanstack/r
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import Layout from '@components/common/layout';
-import MetaHead from '@components/meta/MetaHead';
+import MetaHead, { type MetaHeadProps } from '@components/meta/MetaHead';
import useSetAxiosConfig from '@/api/useSetAxiosConfig';
import { DAY, HALF_DAY } from '@/constants/TimeConstants';
@@ -18,6 +18,8 @@ import '@/styles/globals.css';
import * as gtag from '../lib/gtag';
+type ComponentWithMeta = AppProps['Component'] & { meta?: MetaHeadProps };
+
export default function MyApp({ Component, pageProps }: AppProps) {
useSetAxiosConfig();
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
@@ -56,7 +58,9 @@ export default function MyApp({ Component, pageProps }: AppProps) {
};
}, [router.events]);
- const meta = pageProps.meta || META.MAIN;
+ const componentMeta = (Component as ComponentWithMeta)?.meta;
+ const meta: MetaHeadProps =
+ (pageProps.meta as MetaHeadProps | undefined) ?? componentMeta ?? META.MAIN;
return (
<>
diff --git a/pages/pickpickpick/[id]/index.page.tsx b/pages/pickpickpick/[id]/index.page.tsx
index 95e0f51a..59e4725d 100644
--- a/pages/pickpickpick/[id]/index.page.tsx
+++ b/pages/pickpickpick/[id]/index.page.tsx
@@ -1,4 +1,5 @@
import Link from 'next/link';
+import type { NextPage } from 'next';
import { useRouter } from 'next/router';
import DevLoadingComponent from '@pages/loading/index.page';
@@ -16,7 +17,9 @@ import {
PICK_VOTE_MODIFIED_MODAL,
} from '@components/common/modals/modalConfig/pickVote';
import MoreButton from '@components/common/moreButton';
+import type { MetaHeadProps } from '@components/meta/MetaHead';
+import { META } from '@/constants/metaData';
import { ROUTES } from '@/constants/routes';
import { useMediaQueryContext } from '@/contexts/MediaQueryContext';
@@ -27,7 +30,9 @@ import SimilarPick from './components/SimilarPick';
import VoteCard from './components/VoteCard';
import usePickDetailHandlers from './handlers/usePickDetailHandlers';
-export default function Index() {
+type NextPageWithMeta = NextPage & { meta?: MetaHeadProps };
+
+const PickDetailPage: NextPageWithMeta = () => {
const router = useRouter();
const { id } = router.query;
@@ -148,4 +153,8 @@ export default function Index() {
>
);
-}
+};
+
+PickDetailPage.meta = META.PICK;
+
+export default PickDetailPage;
diff --git a/pages/techblog/[id]/index.page.tsx b/pages/techblog/[id]/index.page.tsx
index b367cd6b..cbb22eb3 100644
--- a/pages/techblog/[id]/index.page.tsx
+++ b/pages/techblog/[id]/index.page.tsx
@@ -1,5 +1,6 @@
import React from 'react';
+import type { NextPage } from 'next';
import { useRouter } from 'next/router';
import DevLoadingComponent from '@pages/loading/index.page';
@@ -13,7 +14,9 @@ import WritableComment from '@components/common/comment/WritableComment';
import DevGuriHorizontalError from '@components/common/error/DevGuriHorizontalError';
import MobileToListButton from '@components/common/mobile/mobileToListButton';
import { LoginModal } from '@components/common/modals/modal';
+import type { MetaHeadProps } from '@components/meta/MetaHead';
+import { META } from '@/constants/metaData';
import { ROUTES } from '@/constants/routes';
import { useMediaQueryContext } from '@/contexts/MediaQueryContext';
@@ -24,7 +27,9 @@ import CompanyInfoCard from '../components/CompanyInfoCard';
import TechDetailCard from '../components/TechDetailCard';
import { TechCardProps } from '../types/techBlogType';
-export default function Page() {
+type NextPageWithMeta = NextPage & { meta?: MetaHeadProps };
+
+const TechBlogDetailPage: NextPageWithMeta = () => {
const router = useRouter();
const techArticleId = router.query.id as string | undefined;
@@ -116,4 +121,8 @@ export default function Page() {
{isLoginModalOpen && loginStatus !== 'login' && }
>
);
-}
+};
+
+TechBlogDetailPage.meta = META.TECH;
+
+export default TechBlogDetailPage;