Skip to content

Commit 3d61820

Browse files
manNomi한만욱
andauthored
Refactor/layout global (#212)
* refactor : global_layout dynamic 적용했습니다 * refactor : layout.tsx 부분도 다이나믹 및 불필요한 코드들 제거했습니다" * refactor : global_layout및 next.config의 최적화 추가했습니다 * fix : next.config 수정했습니다 --------- Co-authored-by: 한만욱 <manwook-han@hanman-ug-ui-MacBookPro.local>
1 parent 779f78a commit 3d61820

6 files changed

Lines changed: 128 additions & 42 deletions

File tree

next.config.mjs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ const nextConfig = {
1414
"d23lwokhcc3r0c.cloudfront.net",
1515
],
1616
},
17+
// 폰트 최적화 설정
18+
optimizeFonts: true,
19+
// 압축 활성화
20+
compress: true,
21+
// 정적 리소스 최적화
22+
experimental: {
23+
optimizeCss: true,
24+
gzipSize: true,
25+
},
1726
eslint: {
1827
// Warning: This allows production builds to successfully complete even if
1928
// your project has ESLint errors.
@@ -23,6 +32,24 @@ const nextConfig = {
2332
ignoreBuildErrors: true,
2433
},
2534
webpack: (config) => {
35+
// CSS 최적화 - ensure nested objects exist
36+
if (!config.optimization) {
37+
config.optimization = {};
38+
}
39+
if (!config.optimization.splitChunks) {
40+
config.optimization.splitChunks = {};
41+
}
42+
if (!config.optimization.splitChunks.cacheGroups) {
43+
config.optimization.splitChunks.cacheGroups = {};
44+
}
45+
46+
config.optimization.splitChunks.cacheGroups.styles = {
47+
name: "styles",
48+
test: /\.(css|scss)$/,
49+
chunks: "all",
50+
enforce: true,
51+
};
52+
2653
config.module.rules.push({
2754
test: /\.svg$/,
2855
use: ["@svgr/webpack"],

package-lock.json

Lines changed: 57 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"axios": "^1.6.7",
2323
"class-variance-authority": "^0.7.1",
2424
"clsx": "^2.1.1",
25+
"critters": "^0.0.23",
2526
"firebase": "^10.7.2",
2627
"firebase-admin": "^12.0.0",
2728
"lucide-react": "^0.479.0",

src/app/_home/index.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@ import { IconIdCard, IconMagnifyingGlass, IconMuseum, IconPaper } from "@/public
1313

1414
const Home = async () => {
1515
const newsList = await fetchAllNews();
16-
17-
// 추천 대학 정보를 가져옵니다
1816
const { data } = await getRecommendedUniversity();
19-
const recommendedUniversities = data?.recommendedUniversities || [];
20-
17+
const recommendedColleges = data?.recommendedUniversities || [];
2118
// 권역별 전체 대학 리스트를 미리 가져와 빌드합니다
2219
const allRegionsUniversityList = await getAllRegionsUniversityList();
2320

@@ -71,7 +68,7 @@ const Home = async () => {
7168
<div className="mb-2 flex items-center gap-1.5 font-serif text-base font-semibold text-k-700">
7269
실시간 인기있는 파견학교
7370
</div>
74-
<PopularUniversitySection universities={recommendedUniversities} />
71+
<PopularUniversitySection universities={recommendedColleges} />
7572
</div>
7673

7774
<div className="p-5">

src/app/layout.tsx

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,25 @@ export const metadata: Metadata = {
1717

1818
const inter = Inter({
1919
subsets: ["latin"],
20-
display: "swap",
20+
display: "swap", // FOUT 방지
21+
preload: true,
2122
});
2223

2324
const pretendard = localFont({
2425
src: "../../public/fonts/PretendardVariable.woff2",
25-
display: "swap",
26+
display: "swap", // FOUT 방지를 위한 swap 설정
2627
weight: "45 920",
2728
variable: "--font-pretendard",
29+
preload: true, // 폰트 우선 로딩
30+
});
31+
32+
const KakaoScriptLoader = dynamic(() => import("@/lib/ScriptLoader/KakaoScriptLoader"), {
33+
ssr: false,
34+
loading: () => null,
35+
});
36+
const AppleScriptLoader = dynamic(() => import("@/lib/ScriptLoader/AppleScriptLoader"), {
37+
ssr: false,
38+
loading: () => null,
2839
});
2940

3041
const KakaoScriptLoader = dynamic(() => import("@/lib/ScriptLoader/KakaoScriptLoader"), {
@@ -54,23 +65,38 @@ const RootLayout = ({ children }: { children: React.ReactNode }) => (
5465
<AlertProvider>
5566
<html lang="ko">
5667
<head>
57-
<link rel="preload" href="/_next/static/css/globals.css" as="style" />
68+
{/* Critical 폰트 preload with high priority */}
5869
<link
59-
rel="stylesheet"
60-
href="/_next/static/css/globals.css"
61-
media="print"
62-
onLoad={(e) => {
63-
(e.currentTarget as HTMLLinkElement).media = "all";
70+
rel="preload"
71+
href="/fonts/PretendardVariable.woff2"
72+
as="font"
73+
type="font/woff2"
74+
crossOrigin="anonymous"
75+
/>
76+
{/* Prevent layout shift with font-display: swap */}
77+
<style
78+
dangerouslySetInnerHTML={{
79+
__html: `
80+
@font-face {
81+
font-family: 'Pretendard';
82+
src: url('/fonts/PretendardVariable.woff2') format('woff2');
83+
font-weight: 45 920;
84+
font-display: swap;
85+
font-style: normal;
86+
}
87+
`,
6488
}}
6589
/>
66-
<noscript>
67-
<link rel="stylesheet" href="/_next/static/css/globals.css" />
68-
</noscript>
90+
{/* DNS prefetch for external resources */}
91+
<link rel="dns-prefetch" href="//www.googletagmanager.com" />
92+
<link rel="dns-prefetch" href="//connect.facebook.net" />
93+
<link rel="dns-prefetch" href="//t1.kakaocdn.net" />
6994
</head>
70-
<KakaoScriptLoader />
71-
<AppleScriptLoader />
72-
<GoogleAnalytics gaId="G-V1KLYZC1DS" />
95+
7396
<body className={`${pretendard.className} ${inter.className}`}>
97+
<KakaoScriptLoader />
98+
<AppleScriptLoader />
99+
<GoogleAnalytics gaId="G-V1KLYZC1DS" />
74100
<QueryProvider>
75101
<GlobalLayout>{children}</GlobalLayout>
76102
</QueryProvider>

src/app/page.tsx

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,31 @@ import { Metadata } from "next";
33
import TopLogoBar from "@/components/ui/TopLogoBar";
44

55
import Home from "./_home";
6-
import Head from "./_home/Head";
76

87
import { News } from "@/types/news";
98

10-
import getRecommendedColleges from "@/api/university/server/getRecommendedUniversity";
119
import { fetchAllNews } from "@/lib/firebaseNews";
1210

1311
// 동적 메타데이터 생성
1412
export async function generateMetadata(): Promise<Metadata> {
15-
// 최신 뉴스 및 추천 대학 정보를 서버에서 가져옵니다.
13+
// 최신 뉴스 정보를 서버에서 가져옵니다.
1614
const newsList: News[] = await fetchAllNews();
17-
const { data } = await getRecommendedColleges();
18-
const universities = data?.recommendedUniversities ?? [];
1915

2016
// 대표 뉴스(첫 번째 항목)를 선택해 OG 이미지 등에 활용
2117
const mainNews = newsList[0];
2218

23-
// 추천 대학 한글명을 최대 10개까지 keywords로 사용
24-
const keywords = universities
25-
.slice(0, 10)
26-
.map((u) => u.koreanName)
27-
.join(", ");
28-
2919
return {
3020
title: "솔리드 커넥션 – 교환학생의 첫 걸음",
3121
description: mainNews?.description ?? "교환학생 준비를 위한 모든 정보가 여기에!",
32-
keywords,
3322
alternates: {
3423
canonical: "https://solid-connection.com/",
3524
},
3625
};
3726
}
3827

3928
const HomePage = async () => {
40-
const newsList = await fetchAllNews();
4129
return (
4230
<>
43-
<Head newsList={newsList} />
4431
<TopLogoBar />
4532
<Home />
4633
</>

0 commit comments

Comments
 (0)