Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const TitleSection = ({ logoUrl, title, subTitle }: TitleSectionProps) => {
<Image src={logoUrl} alt="대학 로고" width={48} height={48} className="rounded-full object-cover" />
<div className="flex flex-col">
<span className="typo-sb-4 text-k-900">{title}</span>
<span className="text-center typo-medium-1 text-k-400">{subTitle}</span>
<span className="typo-medium-1 text-center text-k-400">{subTitle}</span>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { convertImageUrl } from "@/utils/fileUtils";

import LinkifyText from "@/components/ui/LinkifyText";

import InfoSection from "./InfoSection";
import LanguageSection from "./LanguageSection";
import MapSection from "./MapSection";
import TitleSection from "./TitleSection";
import UniversityBtns from "./UniversityBtns";
import InfoSection from "../InfoSection";
import LanguageSection from "../LanguageSection";
import MapSection from "../MapSection";
import TitleSection from "../TitleSection";
import UniversityBtns from "../UniversityBtns";

import { University } from "@/types/university";

Expand All @@ -35,11 +35,9 @@ const UniversityDetail = ({ university, koreanName }: UniversityDetailProps) =>
/>
{/* TODO: totalDispatchCount 추가시 연동, 나라에 국기 추가 */}
<div className="mb-7 mt-10 flex justify-center divide-x">
<span className="px-[30px] typo-sb-9 text-k-900">{}0회 파견</span>
<span className="px-[30px] typo-sb-9 text-k-900">{university.country}</span>
<span className="px-[30px] typo-sb-9 text-k-900">
모집 {university.studentCapacity}명
</span>
<span className="typo-sb-9 px-[30px] text-k-900">{}0회 파견</span>
<span className="typo-sb-9 px-[30px] text-k-900">{university.country}</span>
<span className="typo-sb-9 px-[30px] text-k-900">모집 {university.studentCapacity}명</span>
</div>
<LanguageSection
detailsForLanguage={university.detailsForLanguage}
Expand All @@ -53,16 +51,16 @@ const UniversityDetail = ({ university, koreanName }: UniversityDetailProps) =>
/>
<div className="h-1 bg-k-50" />
<div className="my-7 px-3">
<div className="mb-3 typo-sb-7 text-k-900">전공상세</div>
<div className="break-words typo-medium-2 text-k-600">
<div className="typo-sb-7 mb-3 text-k-900">전공상세</div>
<div className="typo-medium-2 break-words text-k-600">
<LinkifyText>{university?.detailsForMajor}</LinkifyText>
</div>
</div>
<div className="h-1 bg-k-50" />
<div className="my-7 px-3">
<div className="mb-3 typo-sb-7 text-k-900">영어강의 리스트</div>
<div className="typo-sb-7 mb-3 text-k-900">영어강의 리스트</div>
<div>
<span className="break-words typo-medium-2 text-k-600">
<span className="typo-medium-2 break-words text-k-600">
<LinkifyText>{university?.detailsForEnglishCourse}</LinkifyText>
</span>
</div>
Expand Down
86 changes: 78 additions & 8 deletions src/app/university/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Metadata, ResolvingMetadata } from "next";
import { Metadata } from "next";
import { notFound } from "next/navigation";

import TopDetailNavigation from "@/components/layout/TopDetailNavigation";

import UniversityDetail from "./UniversityDetail";
import UniversityDetail from "./_ui/UniversityDetail";

import { getUniversityDetail } from "@/api/university/server/getUniversityDetail";
import { getAllUniversities } from "@/api/university/server/getSearchUniversitiesByText";
import { getUniversityDetail } from "@/api/university/server/getUniversityDetail";

export const revalidate = false;

Expand All @@ -22,10 +22,7 @@ type MetadataProps = {
params: Promise<{ id: string }>;
};

export async function generateMetadata(
{ params }: MetadataProps,
_parent: ResolvingMetadata,
): Promise<Metadata> {
export async function generateMetadata({ params }: MetadataProps): Promise<Metadata> {
const { id } = await params;

const universityData = await getUniversityDetail(Number(id));
Expand All @@ -41,8 +38,51 @@ export async function generateMetadata(
? `${universityData.koreanName}(${universityData.term})`
: universityData.koreanName;

const baseUrl = process.env.NEXT_PUBLIC_WEB_URL || "https://solid-connection.com";
const pageUrl = `${baseUrl}/university/${id}`;
const imageUrl = universityData.backgroundImageUrl
? universityData.backgroundImageUrl.startsWith("http")
? universityData.backgroundImageUrl
: `${baseUrl}${universityData.backgroundImageUrl}`
: `${baseUrl}/images/article-thumb.png`;

// [나라] 교환학생 키워드 생성
const countryExchangeKeyword = `${universityData.country} 교환학생`;

// Description 생성: 대학교 이름과 [나라] 교환학생 키워드 포함
const description = `${convertedKoreanName}(${universityData.englishName}) ${countryExchangeKeyword} 프로그램. 모집인원 ${universityData.studentCapacity}명. 솔리드커넥션에서 ${convertedKoreanName} ${countryExchangeKeyword} 지원 정보 확인.`;

// Title 생성: 대학교 이름과 [나라] 교환학생 키워드 포함 (검색 최적화)
const title = `${convertedKoreanName} - ${countryExchangeKeyword} 정보 | 솔리드커넥션`;

return {
title: convertedKoreanName,
title,
description,
openGraph: {
title,
description,
url: pageUrl,
siteName: "솔리드커넥션",
images: [
{
url: imageUrl,
width: 1200,
height: 630,
alt: `${convertedKoreanName} 대학 이미지`,
},
],
locale: "ko_KR",
type: "website",
},
twitter: {
card: "summary_large_image",
title,
description,
images: [imageUrl],
},
alternates: {
canonical: pageUrl,
},
};
}

Expand All @@ -64,8 +104,38 @@ const CollegeDetailPage = async ({ params }: CollegeDetailPageProps) => {
? `${universityData.koreanName}(${universityData.term})`
: universityData.koreanName;

const baseUrl = process.env.NEXT_PUBLIC_WEB_URL || "https://solid-connection.com";
const pageUrl = `${baseUrl}/university/${collegeId}`;

// [나라] 교환학생 키워드 생성
const countryExchangeKeyword = `${universityData.country} 교환학생`;

// Structured Data (JSON-LD) for SEO - 검색 엔진이 대학 정보를 더 잘 이해하도록
const structuredData: {
"@context": string;
"@type": string;
name: string;
alternateName?: string;
url: string;
description: string;
image: string;
} = {
"@context": "https://schema.org",
"@type": "EducationalOrganization",
name: convertedKoreanName,
alternateName: universityData.englishName,
url: pageUrl,
description: `${convertedKoreanName}(${universityData.englishName}) ${countryExchangeKeyword} 프로그램 정보`,
image: universityData.backgroundImageUrl
? universityData.backgroundImageUrl.startsWith("http")
? universityData.backgroundImageUrl
: `${baseUrl}${universityData.backgroundImageUrl}`
: `${baseUrl}/images/article-thumb.png`,
};

return (
<>
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }} />
<TopDetailNavigation title={convertedKoreanName} />
<div className="w-full px-5">
<UniversityDetail koreanName={convertedKoreanName} university={universityData} />
Expand Down