-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] og 태그 및 아이콘 설정 #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,11 +2,49 @@ import React from 'react'; | |
| import KeywordCard from './_components/KeywordCard'; | ||
| import Button from '@/components/common/Button'; | ||
| import Link from 'next/link'; | ||
| import axios from 'axios'; | ||
| import { Metadata } from 'next'; | ||
|
|
||
| type Props = { | ||
| params: Promise<{ uuid: string }>; | ||
| }; | ||
|
|
||
| export async function generateMetadata({ params }: Props): Promise<Metadata> { | ||
| const { uuid } = await params; | ||
| let userName = '사용자'; | ||
|
|
||
| try { | ||
| const res = await axios.get( | ||
| `${process.env.NEXT_PUBLIC_API_BASE_URL}/teamficial-log/requester`, | ||
| { | ||
| params: { | ||
| requesterUuid: uuid, | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| userName = res.data?.result?.requesterName ?? '사용자'; | ||
| } catch (error) { | ||
| console.error('Failed to fetch requester data:', error); | ||
| } | ||
|
|
||
| return { | ||
| title: `${userName}님의 팀피셜록을 작성해볼까요?`, | ||
| description: `소프트스킬 팀빌딩 서비스, 팀피셜`, | ||
| openGraph: { | ||
| title: `${userName}님의 팀피셜록을 작성해볼까요?`, | ||
| description: `소프트스킬 팀빌딩 서비스, 팀피셜`, | ||
| images: [ | ||
| { | ||
| url: '/og/Teamficial_metatag_Image.jpg', | ||
| width: 1200, | ||
| height: 630, | ||
| }, | ||
| ], | ||
|
Comment on lines
+37
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OG 이미지 URL은 절대 경로로 지정해야 합니다. 소셜 미디어 크롤러(Facebook, Twitter 등)는 상대 경로를 인식하지 못합니다. 🐛 수정 방안방안 1: 절대 URL 직접 사용 images: [
{
- url: '/og/Teamficial_metatag_Image.jpg',
+ url: `${process.env.NEXT_PUBLIC_BASE_URL}/og/Teamficial_metatag_Image.jpg`,
width: 1200,
height: 630,
},
],방안 2: metadataBase 설정 (layout.tsx에서) // layout.tsx
export const metadata: Metadata = {
metadataBase: new URL('https://your-domain.com'),
};🤖 Prompt for AI Agents |
||
| }, | ||
| }; | ||
| } | ||
|
|
||
| const page = async ({ params }: Props) => { | ||
| const { uuid } = await params; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ import Image from 'next/image'; | |
| const Footer = () => { | ||
| return ( | ||
| <> | ||
| {/* 모바일 */} | ||
| <footer className="desktop:hidden"> | ||
| <div className="-mx-4 flex flex-col gap-4 bg-gray-200 py-6"> | ||
| <div className="body-9 flex justify-between px-4"> | ||
|
|
@@ -22,28 +23,45 @@ const Footer = () => { | |
| <a>서비스이용약관</a> | ||
| </div> | ||
| </div> | ||
| <div className="flex justify-between px-4"> | ||
| <div className="flex items-center justify-between px-4"> | ||
| <div> | ||
| <p className="body-11 text-gray-500">Teamficial@gmail.com</p> | ||
| <p className="body-11 text-gray-500">© 2025.Teamficial. ALL rights reserved.</p> | ||
| </div> | ||
| <a | ||
| href="https://www.instagram.com/teamficial.official/" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| aria-label="인스타그램" | ||
| > | ||
| <Image | ||
| src="/icons/mobile-instagram.svg" | ||
| alt="instagram" | ||
| width={24} | ||
| height={24} | ||
| className="justify-end" | ||
| /> | ||
| </a> | ||
| <div className="flex gap-2"> | ||
| <a | ||
| href="https://www.instagram.com/teamficial.official/" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| aria-label="인스타그램" | ||
| > | ||
| <Image | ||
| src="/icons/mobile-instagram.svg" | ||
| alt="instagram" | ||
| width={24} | ||
| height={24} | ||
| className="justify-end" | ||
| /> | ||
| </a> | ||
| <a | ||
| href="https://www.threads.com/@teamficial.official" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| aria-label="쓰레드" | ||
| > | ||
| <Image | ||
| src="/icons/mobile-thread.svg" | ||
| alt="thread" | ||
| width={24} | ||
| height={24} | ||
| className="justify-end" | ||
| /> | ||
| </a> | ||
|
Comment on lines
+32
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: fd "Footer.tsx" --type fRepository: TEAMFICIAL/teamficial-fe Length of output: 162 🌐 Web query:
💡 Result: Yes. For decorative images, accessibility guidance is to use an empty alt ( import Image from "next/image";
<Image
src="/decorative.png"
width={200}
height={200}
alt=""
aria-hidden="true"
/>Sources: [1] Next.js 🌐 Web query:
💡 Result: Decorative images: what to do (and when)1) For a purely decorative <img src="..." alt="">
2) Prefer CSS for purely visual styling when possible
3)
4)
Practical rule of thumb
References
🏁 Script executed: cat -n src/components/common/Footer.tsx | head -100Repository: TEAMFICIAL/teamficial-fe Length of output: 4501 이미지 alt 속성 수정 필요 - 중복 낭독 방지 앵커에 ♿ 제안 수정 <Image
src="/icons/mobile-instagram.svg"
- alt="instagram"
+ alt=""
width={24}
height={24}
className="justify-end"
/> <Image
src="/icons/mobile-thread.svg"
- alt="thread"
+ alt=""
width={24}
height={24}
className="justify-end"
/> <Image src="/icons/mail.svg"
- alt="mail"
+ alt=""
width={24} height={24} /> <Image src="/icons/instagram.svg"
- alt="instagram"
+ alt=""
width={24} height={24} /> <Image src="/icons/thread.svg"
- alt="thread"
+ alt=""
width={24} height={24} />🤖 Prompt for AI Agents |
||
| </div> | ||
| </div> | ||
| </div> | ||
| </footer> | ||
| {/* 데스크탑 */} | ||
| <footer className="desktop:flex mx-auto hidden w-full justify-center bg-gray-600 px-10 pb-10"> | ||
| <div className="flex w-[944px] items-center justify-between"> | ||
| <div className="body-6 flex flex-col text-gray-100"> | ||
|
|
@@ -64,6 +82,14 @@ const Footer = () => { | |
| > | ||
| <Image src="/icons/instagram.svg" alt="instagram" width={24} height={24} /> | ||
| </a> | ||
| <a | ||
| href="https://www.threads.com/@teamficial.official" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| aria-label="쓰레드" | ||
| > | ||
| <Image src="/icons/thread.svg" alt="thread" width={24} height={24} /> | ||
| </a> | ||
| </div> | ||
| <div className="body-7 flex gap-4 text-gray-100"> | ||
| <a | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
환경 변수 및 요청 타임아웃 설정을 확인하세요.
NEXT_PUBLIC_접두사가 붙은 환경 변수는 클라이언트에 노출됩니다.generateMetadata는 서버에서만 실행되므로 서버 전용 환경 변수(예:API_BASE_URL) 사용을 권장합니다.🔧 타임아웃 추가 예시
const res = await axios.get( `${process.env.NEXT_PUBLIC_API_BASE_URL}/teamficial-log/requester`, { params: { requesterUuid: uuid, }, + timeout: 5000, }, );🤖 Prompt for AI Agents