Skip to content
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

언어 처리, 메타데이터, 사이트맵 생성 로직 리팩터링, 최적화 #56

Merged
merged 28 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
79c9132
언어와 경로에 따라 리다이렉트할 URL을 만드는 함수를 파일로 분리
witch-factory Jan 24, 2025
196333a
언어 변경 최적화 시도 - 라우트 핸들러 캐싱, 클라이언트 사이드 네비게이션
witch-factory Jan 24, 2025
a4d6d6d
쿠키 생성된 다음에 라우트 처리하도록 변경
witch-factory Jan 24, 2025
1241378
react 패키지 실험적 최적화 제거
witch-factory Jan 24, 2025
4dc1067
라우트 푸시만 하도록
witch-factory Jan 24, 2025
2f7257d
라우트 핸들러의 주석 설명 변경
witch-factory Jan 25, 2025
95c21de
스위치 동작 변경하여 fetch, replace를 독립 동작하게
witch-factory Jan 25, 2025
cbf50eb
로케일 협상에서 늘 주소를 redirect하게 변경
witch-factory Jan 25, 2025
d343ea4
리다이렉트 URL 생성 로직에서 로케일을 늘 포함하게 변경
witch-factory Jan 25, 2025
00531ef
주석처리한 코드 삭제
witch-factory Jan 26, 2025
e6c37b3
글의 schema 변환 시 url에 /en을 붙이던 것을 삭제
witch-factory Jan 26, 2025
8101a0b
블로그 메타데이터 제작용 헬퍼 함수 제작, 사용
witch-factory Jan 26, 2025
c33da99
글의 URL을 만들 때 언어가 들어가던 것 제거
witch-factory Jan 26, 2025
b41ebb6
기존의 메타데이터 제작 함수 파일 삭제
witch-factory Jan 26, 2025
d15254c
메타데이터 타입 다시 구조화
witch-factory Jan 26, 2025
3faa2db
blogConfig 변수명 변경을 컴포넌트들, 유틸함수에 적용
witch-factory Jan 26, 2025
93d0da6
사이트맵 생성 로직에 config 변경사항 반영
witch-factory Jan 26, 2025
20680b9
ui에 config 변경사항 반영
witch-factory Jan 26, 2025
64963b1
config, metadata 변경사항을 페이지에 반영
witch-factory Jan 26, 2025
41a7e7e
날짜 표기 유틸함수를 국제화
witch-factory Jan 26, 2025
d1408ee
변경된 날짜 포매팅 함수를 UI에 적용
witch-factory Jan 26, 2025
09d2b89
변경된 PostList 컴포넌트를 페이지에 적용
witch-factory Jan 26, 2025
5376a01
불필요해진 글로벌 css 파일 삭제
witch-factory Jan 26, 2025
8976035
태그 목록 너비를 100%로 변경
witch-factory Jan 26, 2025
844c949
불필요한 className 삭제
witch-factory Jan 26, 2025
2472475
날짜 포맷 형식 변경
witch-factory Jan 26, 2025
b394c4e
사이트맵 생성 간소화
witch-factory Jan 27, 2025
4cf1e37
불필요해진 주석 삭제
witch-factory Jan 27, 2025
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
3 changes: 0 additions & 3 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
experimental: {
optimizePackageImports: ['react', 'react-dom'],
},
};

export default withBundleAnalyzer(withVanillaExtract(nextConfig));
7 changes: 3 additions & 4 deletions schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const articleSchema = defineSchema(() =>
.transform((data) => ({ ...data, url: `/posts/${data.slug}` }))
.transform(async (data, { meta }) => {
if (!meta.mdast) return data;
const localThumbnailURL = await generateThumbnailURL(meta, data.title);
const localThumbnailURL = await generateThumbnailURL(meta, data.title, 'ko');
const thumbnail: ThumbnailType = {
local: localThumbnailURL,
};
Expand All @@ -62,7 +62,7 @@ export const articleSchema = defineSchema(() =>
export const enArticleMetadataSchema = defineSchema(() =>
articleMetadataObject
// transform을 거친 타입은 동기 함수일 경우 타입에 포함됨
.transform((data) => ({ ...data, url: `/en/posts/${data.slug}` })),
.transform((data) => ({ ...data, url: `/posts/${data.slug}` })),
);

export const enArticleSchema = defineSchema(() =>
Expand All @@ -74,8 +74,7 @@ export const enArticleSchema = defineSchema(() =>
}),
headingTree: headingTree(),
})
// TODO: slug를 en-posts로 시작하는 것을 posts로 바꾸는 로직을 좀더 확장성 있게 추가하자
.transform((data) => ({ ...data, url: `/en/posts/${data.slug}` }))
.transform((data) => ({ ...data, url: `/posts/${data.slug}` }))
.transform(async (data, { meta }) => {
if (!meta.mdast) return data;
const localThumbnailURL = await generateThumbnailURL(meta, data.title, 'en');
Expand Down
4 changes: 2 additions & 2 deletions src/app/[lang]/about/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const aboutContent = {
links: [
{ name: '블로그', url: 'https://witch.work' },
{ name: 'GitHub', url: 'https://github.com/witch-factory' },
{ name: '이메일', url: `mailto:${blogConfig.ko.email}` },
{ name: '이메일', url: `mailto:${blogConfig.email}` },
{ name: '이력서', url: '/resume/kor' },
],
introduction: {
Expand Down Expand Up @@ -51,7 +51,7 @@ export const aboutContent = {
links: [
{ name: 'Blog', url: 'https://witch.work/en' },
{ name: 'GitHub', url: 'https://github.com/witch-factory' },
{ name: 'Email', url: `mailto:${blogConfig.ko.email}` },
{ name: 'Email', url: `mailto:${blogConfig.email}` },
{ name: 'Resume', url: '/resume/kor' },
],
introduction: {
Expand Down
37 changes: 8 additions & 29 deletions src/app/[lang]/api/language/route.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,28 @@
import { headers } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

import { blogConfig } from '@/config/blogConfig';
import { i18n, Locale, LOCALE_COOKIE_NAME } from '@/types/i18n';

function generateRedirectPath(pathname: string, selectedLocale: Locale) {
const pathSegments = pathname.split('/').filter(Boolean); // 경로를 '/'로 나누고 빈 값 제거
const currentLangIndex = i18n.locales.includes(pathSegments[0] as Locale) ? 0 : -1;
export const dynamic = 'force-static';

// 경로에 언어가 없는 경우 추가
if (currentLangIndex === -1) {
return selectedLocale === i18n.defaultLocale ? pathname : `/${selectedLocale}${pathname}`;
}

pathSegments[currentLangIndex] = selectedLocale === i18n.defaultLocale ? '' : selectedLocale;
return `/${pathSegments.filter(Boolean).join('/')}`;
}

// api/language?locale=ko 등 locale 쿼리스트링을 통해 언어 변경
export function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const selectedLocale = searchParams.get('locale') as Locale | undefined;
// /[lang]/api/language의 lang 동적 라우트 세그먼트를 통해서 언어 변경
export function GET(request: NextRequest, { params }: {
params: { lang: Locale },
}) {
const selectedLocale = params.lang;

// 유효하지 않은 로케일이면 406 Not Acceptable 에러
if (!selectedLocale || !i18n.locales.includes(selectedLocale)) {
if (!i18n.locales.includes(selectedLocale)) {
return NextResponse.json(
{ error: 'Invalid locale' },
{ status: 406 },
);
}

// 이전 페이지의 URL을 referer 헤더를 통해 가져옴
const headersList = headers();
const refererUrl = new URL(headersList.get('referer') ?? blogConfig.ko.url);
const { origin, pathname } = refererUrl;

const newPath = generateRedirectPath(pathname, selectedLocale);
const redirectUrl = new URL(newPath, origin);

const response = NextResponse.redirect(redirectUrl);
const response = NextResponse.json({ locale: selectedLocale });
response.cookies.set(LOCALE_COOKIE_NAME, selectedLocale, {
path: '/',
maxAge: 60 * 60 * 24 * 30, // 1달
sameSite: 'lax',
});

return response;
}
5 changes: 2 additions & 3 deletions src/app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import LanguageSwitcher from '@/components/langSwitch';
import PageContainer from '@/components/pageContainer';
import ViewReporter from '@/components/viewReporter';
import { blogCategory } from '@/config/blogCategory';
import { SEOConfig } from '@/config/blogConfig';
import { blogMetadata } from '@/config/blogMetadata';
import { Locale, i18n } from '@/types/i18n';
import Footer from '@/ui/footer';
import Header from '@/ui/header';

import { Providers } from './Provider';

import '@/styles/reset.css';
import '@/styles/global.css';
import '@/styles/theme.css';
import '@/styles/github-light.css';
import '@/styles/github-dark.css';
Expand Down Expand Up @@ -61,5 +60,5 @@ export function generateStaticParams() {
}

export function generateMetadata({ params: { lang } }: Props) {
return SEOConfig[lang];
return blogMetadata[lang];
}
4 changes: 2 additions & 2 deletions src/app/[lang]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ function Home({ params }: Props) {
<div>
<h2 className={styles.title}>{titles[lang].recentPosts}</h2>
<AllPostTagList selectedTag="all" lang={lang} />
<PostList postList={recentPosts} direction="row" />
<PostList lang={lang} postList={recentPosts} direction="row" />
</div>

<div>
<Link href="/translations/all">
<h2 className={styles.title}>{titles[lang].recentTranslations}</h2>
</Link>
<hr className={styles.separator} />
<PostList postList={recentTranslations} direction="row" />
<PostList lang={lang} postList={recentTranslations} direction="row" />
</div>

</section>
Expand Down
38 changes: 5 additions & 33 deletions src/app/[lang]/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import Giscus from '@/components/giscus';
import TableOfContents from '@/components/toc';
import TranslationNotice from '@/components/translationNotice';
import ViewReporter from '@/components/viewReporter';
import { blogConfig } from '@/config/blogConfig';
import { blogLocalConfig } from '@/config/blogConfig';
import { i18n, Locale } from '@/types/i18n';
import FrontMatter from '@/ui/frontMatter';
import { getPostBySlug, getSortedPosts } from '@/utils/content/post';
import { getSortedPostMetadatas } from '@/utils/content/postMetadata';
import { generatePostPageMetadata } from '@/utils/meta/helper';

import * as contentStyles from './content.css';

Expand Down Expand Up @@ -44,6 +45,7 @@ function PostPage({ params }: Props) {
<>
<ViewReporter slug={slug} />
<FrontMatter
lang={lang}
title={post.title}
date={post.date}
tags={post.tags}
Expand All @@ -55,7 +57,7 @@ function PostPage({ params }: Props) {
className={contentStyles.content}
dangerouslySetInnerHTML={{ __html: post.html }}
/>
{blogConfig[lang].comment.type === 'giscus' ? <Giscus lang={lang} /> : null}
{blogLocalConfig[lang].comment.type === 'giscus' ? <Giscus lang={lang} /> : null}
</>
);
}
Expand Down Expand Up @@ -83,35 +85,5 @@ export function generateMetadata({ params }: Props): Metadata {
notFound();
}

return {
title: post.title,
description: post.description,
alternates: {
canonical: post.url,
},
openGraph: {
title: post.title,
description: post.description,
url: post.url,
images: [{
url: post.thumbnail?.[blogConfig[lang].imageStorage] ?? blogConfig[lang].thumbnail,
width: 300,
height: 200,
alt: `${post.title} thumbnail`,
}],
},
twitter: {
card: 'summary_large_image',
site: '@witch_front',
creator: '@witch_front',
title: post.title,
description: post.description,
images: [
{
url: post.thumbnail?.[blogConfig[lang].imageStorage] ?? blogConfig[lang].thumbnail,
alt: `${post.title} thumbnail`,
},
],
},
};
return generatePostPageMetadata(blogLocalConfig, lang, post);
}
6 changes: 3 additions & 3 deletions src/app/[lang]/posts/all/[page]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Pagination from '@/ui/pagination';
import PostList from '@/ui/postList';
import { ITEMS_PER_PAGE, allPostNumber, allEnPostNumber } from '@/utils/content/helper';
import { getPostsByPage } from '@/utils/content/postMetadata';
import { generatePostsPageMetadata } from '@/utils/generatePostsPageMetadata';
import { generatePostListPageMetadata } from '@/utils/meta/helper';
import { parsePage } from '@/utils/parsePage';

type Props = {
Expand Down Expand Up @@ -58,7 +58,7 @@ function PostListPage({ params }: Props) {
renderPageLink={(page: number) => `${lang === 'ko' ? '' : `/${lang}`}/posts/all/${page}`}
perPage={ITEMS_PER_PAGE}
/>
<PostList postList={pagePostsWithThumbnail} />
<PostList lang={lang} postList={pagePostsWithThumbnail} />
<Pagination
totalItemNumber={totalPostNumber}
currentPage={currentPage}
Expand Down Expand Up @@ -93,5 +93,5 @@ export function generateMetadata({ params }: Props): Metadata {
const currentPage = Number(params.page);
const { lang } = params;

return generatePostsPageMetadata(lang, currentPage, 'all');
return generatePostListPageMetadata(lang, currentPage, 'all');
}
6 changes: 3 additions & 3 deletions src/app/[lang]/posts/all/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Pagination from '@/ui/pagination';
import PostList from '@/ui/postList';
import { ITEMS_PER_PAGE, FIRST_PAGE } from '@/utils/content/helper';
import { getPostsByPage } from '@/utils/content/postMetadata';
import { generatePostsPageMetadata } from '@/utils/generatePostsPageMetadata';
import { generatePostListPageMetadata } from '@/utils/meta/helper';

function PostListPage({ params }: { params: { lang: Locale } }) {
const currentPage = FIRST_PAGE;
Expand Down Expand Up @@ -35,7 +35,7 @@ function PostListPage({ params }: { params: { lang: Locale } }) {
renderPageLink={(page: number) => `${lang === 'ko' ? '' : `/${lang}`}/posts/all/${page}`}
perPage={ITEMS_PER_PAGE}
/>
<PostList postList={pagePostsWithThumbnail} />
<PostList lang={lang} postList={pagePostsWithThumbnail} />
<Pagination
totalItemNumber={totalPostNumber}
currentPage={currentPage}
Expand All @@ -57,7 +57,7 @@ export function generateStaticParams() {
export function generateMetadata({ params }: { params: { lang: Locale } }): Metadata {
const { lang } = params;

return generatePostsPageMetadata(lang, currentPage, 'all');
return generatePostListPageMetadata(lang, currentPage, 'all');
}

export default PostListPage;
2 changes: 1 addition & 1 deletion src/app/[lang]/posts/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function PostSearchPage({ params }: Props) {
{filteredPostList.length === 0
? <p>{content[lang].noResult}</p>
: null}
<PostList postList={filteredPostList.slice(0, ITEMS_PER_PAGE * page)} />
<PostList lang={lang} postList={filteredPostList.slice(0, ITEMS_PER_PAGE * page)} />
<div ref={infiniteScrollRef} />
</>
);
Expand Down
6 changes: 3 additions & 3 deletions src/app/[lang]/posts/tag/[tag]/[page]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import PostList from '@/ui/postList';
import { ITEMS_PER_PAGE } from '@/utils/content/helper';
import { getPostsByPage } from '@/utils/content/postMetadata';
import { getPostCountByTag, getAllPostTags } from '@/utils/content/tag';
import { generatePostsPageMetadata } from '@/utils/generatePostsPageMetadata';
import { generatePostListPageMetadata } from '@/utils/meta/helper';
import { parsePage } from '@/utils/parsePage';

type Props = {
Expand Down Expand Up @@ -69,7 +69,7 @@ function TagPaginationPage({ params }: Props) {
renderPageLink={(page: number) => `${currentTag.url}/${page}`}
perPage={ITEMS_PER_PAGE}
/>
<PostList postList={pagePostsWithThumbnail} />
<PostList lang={lang} postList={pagePostsWithThumbnail} />
<Pagination
totalItemNumber={totalPostNumber}
currentPage={currentPage}
Expand Down Expand Up @@ -102,7 +102,7 @@ export function generateMetadata({ params }: Props): Metadata {
const { lang, tag, page } = params;
const currentPage = parsePage(page);

return generatePostsPageMetadata(lang, currentPage, tag);
return generatePostListPageMetadata(lang, currentPage, tag);
}

export default TagPaginationPage;
6 changes: 3 additions & 3 deletions src/app/[lang]/posts/tag/[tag]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import PostList from '@/ui/postList';
import { ITEMS_PER_PAGE, FIRST_PAGE } from '@/utils/content/helper';
import { getPostsByPage } from '@/utils/content/postMetadata';
import { getAllPostTags } from '@/utils/content/tag';
import { generatePostsPageMetadata } from '@/utils/generatePostsPageMetadata';
import { generatePostListPageMetadata } from '@/utils/meta/helper';

type Props = {
params: {
Expand Down Expand Up @@ -51,7 +51,7 @@ function PostListPage({ params }: Props) {
renderPageLink={(page: number) => `${currentTag.url}/${page}`}
perPage={ITEMS_PER_PAGE}
/>
<PostList postList={pagePostsWithThumbnail} />
<PostList lang={lang} postList={pagePostsWithThumbnail} />
<Pagination
totalItemNumber={totalPostNumber}
currentPage={currentPage}
Expand All @@ -78,5 +78,5 @@ const currentPage = FIRST_PAGE;
export function generateMetadata({ params }: Props): Metadata {
const { tag, lang } = params;

return generatePostsPageMetadata(lang, currentPage, tag);
return generatePostListPageMetadata(lang, currentPage, tag);
}
Loading
Loading