diff --git a/next-i18next.config.js b/next-i18next.config.js deleted file mode 100644 index 5e1ff69..0000000 --- a/next-i18next.config.js +++ /dev/null @@ -1,11 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-require-imports -const path = require('path'); - -module.exports = { - i18n: { - locales: ['ko', 'en'], - defaultLocale: 'ko', - }, - reloadOnPrerender: true, - localePath: path.resolve('./public/locales'), // 절대 경로 사용 -}; diff --git a/next-i18next.config.ts b/next-i18next.config.ts new file mode 100644 index 0000000..7f29f16 --- /dev/null +++ b/next-i18next.config.ts @@ -0,0 +1,14 @@ +import path from 'path'; +import type { UserConfig } from 'next-i18next'; + +const nextI18NextConfig: UserConfig = { + i18n: { + locales: ['ko', 'en'], + defaultLocale: 'ko', + localeDetection: false, // 리터럴 false + }, + reloadOnPrerender: process.env.NODE_ENV === 'development', + localePath: path.resolve('./public/locales'), +}; + +export default nextI18NextConfig; // ← 반드시 export default diff --git a/next.config.ts b/next.config.ts index f852557..7b5e3d2 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,5 +1,4 @@ import type { NextConfig } from 'next'; -import { i18n } from './next-i18next.config.js'; const nextConfig: NextConfig = { webpack: (config) => { @@ -10,7 +9,6 @@ const nextConfig: NextConfig = { return config; }, reactStrictMode: true, - i18n, images: { remotePatterns: [ { diff --git a/public/locales/en/feed.json b/public/locales/en/feed.json new file mode 100644 index 0000000..7e96a05 --- /dev/null +++ b/public/locales/en/feed.json @@ -0,0 +1,6 @@ +{ + "feed": "Feed", + "more_icon": "more icon", + "loading": "loading...", + "more": "More Epigrams" +} diff --git a/public/locales/ko/feed.json b/public/locales/ko/feed.json new file mode 100644 index 0000000..7050523 --- /dev/null +++ b/public/locales/ko/feed.json @@ -0,0 +1,6 @@ +{ + "feed": "피드", + "more_icon": "더보기 아이콘", + "loading": "불러오는 중...", + "more": "에피그램 더보기" +} diff --git a/src/components/Feed/index.tsx b/src/components/Feed/index.tsx index e5a10eb..d5dd88b 100644 --- a/src/components/Feed/index.tsx +++ b/src/components/Feed/index.tsx @@ -4,14 +4,15 @@ import Link from 'next/link'; type feedProps = { feed: Epigram; + className?: string; }; -const Feed = ({ feed }: feedProps) => { +const Feed = ({ feed, className }: feedProps) => { return ( - -
{feed?.content}
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 4c19ae8..9f19e3f 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -5,7 +5,7 @@ import { AnimatePresence, motion } from 'framer-motion'; import { HydrationBoundary, QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { appWithTranslation } from 'next-i18next'; -import nextI18NextConfig from '../../next-i18next.config.js'; +import nextI18NextConfig from '../../next-i18next.config'; import GlobalNavagationBar from '@/components/GNB/index'; import ModalRoot from '@/components/Modal/ModalRoot'; import { useState } from 'react'; diff --git a/src/pages/feed.tsx b/src/pages/feed.tsx new file mode 100644 index 0000000..6888f4f --- /dev/null +++ b/src/pages/feed.tsx @@ -0,0 +1,91 @@ +import Image from 'next/image'; + +import more from '@/assets/icon/more-icon.svg'; + +import FeedSkeleton from '@/components/Feed/FeedSkeleton'; +import { QUERY_KEYS } from '@/lib/QUERY_KEYS'; +import { listEpigrams } from '@/services/epigrams'; +import { dehydrate, QueryClient } from '@tanstack/react-query'; +import { GetStaticProps } from 'next'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; +import { useTranslation } from 'next-i18next'; +import { useInfiniteEpigrams } from '@/hooks/useEpigrams'; +import Feed from '@/components/Feed'; +import nextI18NextConfig from '../../next-i18next.config'; + +export const getStaticProps: GetStaticProps = async ({ locale }) => { + const qc = new QueryClient(); + + await qc.prefetchInfiniteQuery({ + queryKey: QUERY_KEYS.epigrams(6), + queryFn: ({ pageParam }) => + listEpigrams({ cursor: pageParam === null ? undefined : (pageParam as number), limit: 6 }), + initialPageParam: null, + }); + + return { + props: { + dehydratedState: dehydrate(qc), + ...(await serverSideTranslations(locale ?? 'ko', ['feed'], nextI18NextConfig)), + }, + revalidate: 60, + }; +}; + +const FeedPage = () => { + const { t } = useTranslation('feed'); + + const { + list: latestFeeds, + hasNextPage: hasMoreEpigrams, + fetchNextPage: fetchEpigramNextPage, + isFetchingNextPage: isFetchingEpigramNextPage, + reachedEnd: noMoreEpigrams, + isLoading: isEpigramsLoading, + } = useInfiniteEpigrams(6); + + return ( +{t('feed')}
+