From ab0b2e0a671233af6dc62fe727ee34a7df6b32e3 Mon Sep 17 00:00:00 2001 From: minseokim Date: Sat, 3 Jan 2026 22:42:45 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B3=B5=EC=9C=A0=20=EB=AF=B8=EB=A6=AC=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/metadata/home.ts | 56 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/lib/metadata/home.ts b/src/lib/metadata/home.ts index 100e2e0b..b78f6c95 100644 --- a/src/lib/metadata/home.ts +++ b/src/lib/metadata/home.ts @@ -1,18 +1,39 @@ import { Metadata } from 'next'; import { headers } from 'next/headers'; +import { API } from '@/api'; +import { GROUP_LIST_PAGE_SIZE } from '@/lib/constants/group-list'; + export const generateHomeMetadata = async (keyword?: string): Promise => { - const headersList = headers(); - const host = (await headersList).get('host') || process.env.DOMAIN; + const headersList = await headers(); + const host = headersList.get('host') || process.env.DOMAIN || 'wego.monster'; + const protocol = + headersList.get('x-forwarded-proto') || (host.includes('localhost') ? 'http' : 'https'); const currentUrl = keyword - ? `https://${host}/?keyword=${encodeURIComponent(keyword)}` - : `https://${host}/`; + ? `${protocol}://${host}/?keyword=${encodeURIComponent(keyword)}` + : `${protocol}://${host}/`; + const logoImageUrl = `${protocol}://${host}/icons/resizable/icon-wego-logo.svg`; try { if (keyword) { const metaTitle = `${keyword} 검색결과 | WeGo`; const metaDescription = `"${keyword}"에 대한 모임 검색 결과를 확인해보세요.`; + let searchImageUrl = logoImageUrl; + try { + const searchResponse = await API.groupService.getGroups({ + size: GROUP_LIST_PAGE_SIZE, + keyword, + }); + const firstGroupImage = searchResponse.items[0]?.images?.[0]; + if (firstGroupImage) { + searchImageUrl = firstGroupImage; + } + } catch (error) { + // 실패 시 기본 로고 이미지 사용 + console.error('이미지를 가져오는데 실패했습니다:', error); + } + return { title: metaTitle, description: metaDescription, @@ -24,11 +45,20 @@ export const generateHomeMetadata = async (keyword?: string): Promise locale: 'ko_KR', type: 'website', url: currentUrl, + images: [ + { + url: searchImageUrl, + width: 400, + height: 400, + alt: `${keyword} 검색 결과 모임 이미지`, + }, + ], }, twitter: { card: 'summary', title: metaTitle, description: metaDescription, + images: [searchImageUrl], }, robots: { index: true, @@ -54,11 +84,20 @@ export const generateHomeMetadata = async (keyword?: string): Promise locale: 'ko_KR', type: 'website', url: currentUrl, + images: [ + { + url: logoImageUrl, + width: 400, + height: 400, + alt: 'WeGo 로고', + }, + ], }, twitter: { card: 'summary', title: metaTitle, description: metaDescription, + images: [logoImageUrl], }, robots: { index: true, @@ -78,9 +117,18 @@ export const generateHomeMetadata = async (keyword?: string): Promise description: 'WeGo에서 함께할 다양한 모임을 탐색하고 참여하세요.', url: currentUrl, type: 'website', + images: [ + { + url: logoImageUrl, + width: 400, + height: 400, + alt: 'WeGo 로고', + }, + ], }, twitter: { card: 'summary', + images: [logoImageUrl], }, }; } From 117ba050d9bb80e55a6e341fa33d97d3a1826d18 Mon Sep 17 00:00:00 2001 From: minseokim Date: Sun, 4 Jan 2026 00:06:13 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EA=B0=80=EC=9E=85=20=EC=8B=A0?= =?UTF-8?q?=EC=B2=AD=20=EB=AA=A9=EB=A1=9D=20=EC=BF=BC=EB=A6=AC=ED=82=A4?= =?UTF-8?q?=EB=A5=BC=20query-key-group=EC=9C=BC=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/pages/pending/pending-members/index.tsx | 9 +++++---- src/components/pages/pending/pending-summary/index.tsx | 3 ++- src/lib/query-key/query-key-group/index.ts | 2 ++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/pages/pending/pending-members/index.tsx b/src/components/pages/pending/pending-members/index.tsx index 24547724..d514b6b5 100644 --- a/src/components/pages/pending/pending-members/index.tsx +++ b/src/components/pages/pending/pending-members/index.tsx @@ -8,6 +8,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { API } from '@/api'; import { EmptyState } from '@/components/layout/empty-state'; +import { groupKeys } from '@/lib/query-key/query-key-group'; import { GetJoinRequestsResponse } from '@/types/service/group'; import { PendingMemberCard } from './pending-member-card'; @@ -21,7 +22,7 @@ export const GroupPendingMembers = ({ groupId }: Props) => { const queryClient = useQueryClient(); const { data, isLoading, error } = useQuery({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), queryFn: () => API.groupService.getJoinRequests({ groupId }, 'PENDING'), }); @@ -41,11 +42,11 @@ export const GroupPendingMembers = ({ groupId }: Props) => { // 가입 신청 목록 캐시 무효화 및 자동 refetch // GroupPendingSummary의 count도 자동으로 업데이트됨 await queryClient.invalidateQueries({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), refetchType: 'active', // 활성화된 모든 쿼리 자동 refetch }); // 모임 상세 정보도 갱신 - await queryClient.invalidateQueries({ queryKey: ['groupDetails', groupId] }); + await queryClient.invalidateQueries({ queryKey: groupKeys.detail(groupId) }); }, }); @@ -56,7 +57,7 @@ export const GroupPendingMembers = ({ groupId }: Props) => { // 가입 신청 목록 캐시 무효화 및 모든 활성 쿼리 refetch // GroupPendingSummary의 count도 자동으로 업데이트됨 await queryClient.invalidateQueries({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), refetchType: 'active', // 활성화된 모든 쿼리 자동 refetch }); }, diff --git a/src/components/pages/pending/pending-summary/index.tsx b/src/components/pages/pending/pending-summary/index.tsx index e9d05754..bac3db0f 100644 --- a/src/components/pages/pending/pending-summary/index.tsx +++ b/src/components/pages/pending/pending-summary/index.tsx @@ -7,6 +7,7 @@ import { DEFAULT_GROUP_IMAGE } from 'constants/default-images'; import { API } from '@/api'; import { ImageWithFallback } from '@/components/ui'; +import { groupKeys } from '@/lib/query-key/query-key-group'; import { GetJoinRequestsResponse } from '@/types/service/group'; interface Props { @@ -16,7 +17,7 @@ interface Props { export const GroupPendingSummary = ({ groupId, initialData }: Props) => { const { data } = useQuery({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), queryFn: () => API.groupService.getJoinRequests({ groupId }, 'PENDING'), initialData, }); diff --git a/src/lib/query-key/query-key-group/index.ts b/src/lib/query-key/query-key-group/index.ts index d89ca44d..bc2f3313 100644 --- a/src/lib/query-key/query-key-group/index.ts +++ b/src/lib/query-key/query-key-group/index.ts @@ -7,4 +7,6 @@ export const groupKeys = { myList: (filters: { type: 'current' | 'myPost' | 'past'; cursor?: number; size: number }) => [...groupKeys.myLists(), filters] as const, detail: (groupId: string) => [...groupKeys.all, groupId] as const, + joinRequests: (groupId: string, status: string = 'PENDING') => + ['joinRequests', groupId, status] as const, };