diff --git a/.storybook/provider.tsx b/.storybook/provider.tsx
index 771a51ce..e0a1dc9d 100644
--- a/.storybook/provider.tsx
+++ b/.storybook/provider.tsx
@@ -3,6 +3,7 @@ import theme from '../src/styles/theme';
import GlobalStyle from '../src/styles/GlobalStyles';
import React, { ReactNode, useState } from 'react';
import { BrowserRouter } from 'react-router-dom';
+import { HelmetProvider } from 'react-helmet-async';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
interface ProviderProps {
@@ -16,8 +17,10 @@ export const Provider = ({ children }: ProviderProps) => {
return (
-
- {children}
+
+
+ {children}
+
);
diff --git a/index.html b/index.html
index ad5c4c98..8b8bb13d 100644
--- a/index.html
+++ b/index.html
@@ -3,6 +3,11 @@
+
+
+
+
+
다루다(daruda)
diff --git a/package.json b/package.json
index 606a0022..d7ef485f 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"lottie-react": "^2.4.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-helmet-async": "^2.0.5",
"react-intersection-observer": "^9.15.1",
"react-lottie": "^1.2.10",
"react-lottie-player": "^2.1.0",
diff --git a/public/og_img.png b/public/og_img.png
new file mode 100644
index 00000000..75f2b576
Binary files /dev/null and b/public/og_img.png differ
diff --git a/public/og_img1.png b/public/og_img1.png
new file mode 100644
index 00000000..76779d4e
Binary files /dev/null and b/public/og_img1.png differ
diff --git a/public/og_img2.png b/public/og_img2.png
new file mode 100644
index 00000000..0a4b9be4
Binary files /dev/null and b/public/og_img2.png differ
diff --git a/src/components/common/title/Title.tsx b/src/components/common/title/Title.tsx
new file mode 100644
index 00000000..f8fc606e
--- /dev/null
+++ b/src/components/common/title/Title.tsx
@@ -0,0 +1,12 @@
+import { Helmet } from 'react-helmet-async';
+
+const Title = ({ title, tool }: { title: string; tool?: string }) => {
+ return (
+
+ {title}
+
+
+ );
+};
+
+export default Title;
diff --git a/src/components/layout/MyPageLayout.tsx b/src/components/layout/MyPageLayout.tsx
index 4b543e4f..cecd9344 100644
--- a/src/components/layout/MyPageLayout.tsx
+++ b/src/components/layout/MyPageLayout.tsx
@@ -1,5 +1,6 @@
import Footer from '@components/footer/Footer';
import Header from '@components/header/Header';
+import Title from '@components/title/Title';
import { HEADER_STATE, HeaderState } from '@constants/headerState';
import styled from '@emotion/styled';
import MyPageTab from '@pages/myPage/components/tab/MyPageTab';
@@ -14,6 +15,7 @@ const MyPageLayout = () => {
return (
<>
+
diff --git a/src/main.tsx b/src/main.tsx
index a88017a0..4aee8c4b 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import React from 'react';
import ReactDOM from 'react-dom/client';
+import { HelmetProvider } from 'react-helmet-async';
import App from './App';
@@ -15,10 +16,12 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
-
-
-
-
+
+
+
+
+
+
,
diff --git a/src/pages/CommunityDetail/CommunityDetail.tsx b/src/pages/CommunityDetail/CommunityDetail.tsx
index d1a17eae..8a9a9cf5 100644
--- a/src/pages/CommunityDetail/CommunityDetail.tsx
+++ b/src/pages/CommunityDetail/CommunityDetail.tsx
@@ -1,6 +1,7 @@
import { IcCommentGray24, IcBookmark } from '@assets/svgs';
import SquareButton from '@components/button/squareButton/SquareButton';
import Card from '@components/postCard/PostCard';
+import Title from '@components/title/Title';
import { handleScrollDown } from '@utils';
import { useRef, useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';
@@ -37,6 +38,7 @@ const CommunityDetail = () => {
const comments = CommentData?.pages.flatMap((page) => page.commentList) || [];
return (
<>
+
글 상세보기
diff --git a/src/pages/community/Community.tsx b/src/pages/community/Community.tsx
index 65e4d4df..3ffd1133 100644
--- a/src/pages/community/Community.tsx
+++ b/src/pages/community/Community.tsx
@@ -1,6 +1,7 @@
import { IcPlusWhite20, IcChevron } from '@assets/svgs';
import ToolListBanner from '@components/banner/ToolListBanner';
import CircleButton from '@components/button/circleButton/CircleButton';
+import Title from '@components/title/Title';
import { handleScrollUp } from '@utils';
import { useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';
@@ -31,24 +32,27 @@ const Community = () => {
setIsNoTopic(toolId === null);
};
return (
-
-
-
-
-
- {postList?.map((post) => )}
- {hasNextPage ? : null}
-
-
-
- }>
- 글쓰기
-
-
-
-
-
-
+ <>
+
+
+
+
+
+
+ {postList?.map((post) => )}
+ {hasNextPage ? : null}
+
+
+
+ }>
+ 글쓰기
+
+
+
+
+
+
+ >
);
};
diff --git a/src/pages/communityWrite/CommunityWrite.tsx b/src/pages/communityWrite/CommunityWrite.tsx
index 20141533..09212f9b 100644
--- a/src/pages/communityWrite/CommunityWrite.tsx
+++ b/src/pages/communityWrite/CommunityWrite.tsx
@@ -1,5 +1,6 @@
import ToolListBanner from '@components/banner/ToolListBanner';
import CircleButton from '@components/button/circleButton/CircleButton';
+import Title from '@components/title/Title';
import Toast from '@components/toast/Toast';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
@@ -47,29 +48,32 @@ const CommunityWrite = () => {
};
return (
-
- 글쓰기
-
-
-
-
-
-
-
-
-
- 글 게시하기
-
-
-
- {isToastVisible && (
-
-
- {toastMessage}
-
-
- )}
-
+ <>
+
+
+ 글쓰기
+
+
+
+
+
+
+
+
+
+ 글 게시하기
+
+
+
+ {isToastVisible && (
+
+
+ {toastMessage}
+
+
+ )}
+
+ >
);
};
diff --git a/src/pages/login/KakaoAuth.tsx b/src/pages/login/KakaoAuth.tsx
index 0ef501e7..d588b146 100644
--- a/src/pages/login/KakaoAuth.tsx
+++ b/src/pages/login/KakaoAuth.tsx
@@ -1,24 +1,28 @@
import { ImgDarudalogo40 } from '@assets/svgs';
+import Title from '@components/title/Title';
import SvgKakaoVector from './assets/KakaoVector';
import * as S from './KakaoAuth.styled';
const KakaoAuth = () => {
return (
-
-
-
-
-
- 모든 대학생이 찾는 솔루션, 다루다에서 만나보세요.
-
-
-
- 카카오 로그인
-
-
-
-
+ <>
+
+
+
+
+
+
+ 모든 대학생이 찾는 솔루션, 다루다에서 만나보세요.
+
+
+
+ 카카오 로그인
+
+
+
+
+ >
);
};
diff --git a/src/pages/signUp/SignUp.tsx b/src/pages/signUp/SignUp.tsx
index 473b9acc..c84693a2 100644
--- a/src/pages/signUp/SignUp.tsx
+++ b/src/pages/signUp/SignUp.tsx
@@ -1,6 +1,7 @@
import { ImgModalcheck } from '@assets/svgs';
import CircleButton from '@components/button/circleButton/CircleButton';
import { AlterModal } from '@components/modal';
+import Title from '@components/title/Title';
import React, { useState } from 'react';
import AffiliationBtn from './components/affiliationButton/AffiliationBtn';
@@ -43,50 +44,53 @@ const SignUp = () => {
};
return (
-
-
-
-
-
- 쉬운 대학생활,
- 앞으로 한 걸음 남았어요.
-
-
- 공부, 과제, 팀플, 동아리, 대외활동
- 복잡하고 어렵기만 했던 툴에 대한 고민은
- 다루다가 해결해 드릴게요.
-
-
-
-
- 회원가입
-
- 소속을 선택해주세요.
-
- {AFFILIATION_OPTIONS.map((label) => (
- setSelectedAffiliation(label)}
- />
- ))}
-
-
-
- {/* TODO: 중복확인 상태에 따른 로직 구현 */}
-
-
-
- {/* TODO: 중복확인 되었을 때만 작동되도록 */}
-
- 회원가입 하기
-
-
-
-
-
-
+ <>
+
+
+
+
+
+
+ 쉬운 대학생활,
+ 앞으로 한 걸음 남았어요.
+
+
+ 공부, 과제, 팀플, 동아리, 대외활동
+ 복잡하고 어렵기만 했던 툴에 대한 고민은
+ 다루다가 해결해 드릴게요.
+
+
+
+
+ 회원가입
+
+ 소속을 선택해주세요.
+
+ {AFFILIATION_OPTIONS.map((label) => (
+ setSelectedAffiliation(label)}
+ />
+ ))}
+
+
+
+ {/* TODO: 중복확인 상태에 따른 로직 구현 */}
+
+
+
+ {/* TODO: 중복확인 되었을 때만 작동되도록 */}
+
+ 회원가입 하기
+
+
+
+
+
+
+ >
);
};
diff --git a/src/pages/toolDetail/ToolDetail.tsx b/src/pages/toolDetail/ToolDetail.tsx
index 3c02885a..51a6d481 100644
--- a/src/pages/toolDetail/ToolDetail.tsx
+++ b/src/pages/toolDetail/ToolDetail.tsx
@@ -1,4 +1,5 @@
import Spacing from '@components/spacing/Spacing';
+import Title from '@components/title/Title';
import { useRef } from 'react';
import BreadCrumb from './components/breadcrumb/BreadCrumb';
@@ -29,38 +30,41 @@ const ToolDetail = () => {
};
return (
-
-
-
-
-
+ <>
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ >
);
};
diff --git a/yarn.lock b/yarn.lock
index c19a6f80..f3f18ea8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4073,6 +4073,13 @@ internal-slot@^1.1.0:
hasown "^2.0.2"
side-channel "^1.1.0"
+invariant@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+ dependencies:
+ loose-envify "^1.0.0"
+
is-arguments@^1.0.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b"
@@ -4555,7 +4562,7 @@ log-update@^6.1.0:
strip-ansi "^7.1.0"
wrap-ansi "^9.0.0"
-loose-envify@^1.1.0, loose-envify@^1.4.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -5171,11 +5178,20 @@ react-docgen@^7.0.0:
loose-envify "^1.1.0"
scheduler "^0.23.2"
-react-fast-compare@^3.0.1:
+react-fast-compare@^3.0.1, react-fast-compare@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
+react-helmet-async@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.5.tgz#cfc70cd7bb32df7883a8ed55502a1513747223ec"
+ integrity sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==
+ dependencies:
+ invariant "^2.2.4"
+ react-fast-compare "^3.2.2"
+ shallowequal "^1.1.0"
+
react-intersection-observer@^9.15.1:
version "9.15.1"
resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.15.1.tgz#5866b6fdfef24be9f288b74b35b773f63d90c3eb"
@@ -5536,6 +5552,11 @@ set-proto@^1.0.0:
es-errors "^1.3.0"
es-object-atoms "^1.0.0"
+shallowequal@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
+ integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
+
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"