diff --git a/next.config.js b/next.config.js index b6a9a6e..f57aa8c 100644 --- a/next.config.js +++ b/next.config.js @@ -24,7 +24,7 @@ const config = { NEXT_PUBLIC_ENV: process.env.NEXT_PUBLIC_ENV, // 필요할 때 끌어다 쓴 토큰 - EXAMPLE_TOKEN: process.env.EXAMPLE_TOKEN, + SSR_TOKEN: process.env.SSR_TOKEN, // NEXT-AUTH 설정에 필요한 값 NEXTAUTH_URL: process.env.NEXTAUTH_URL, diff --git a/src/components/common/dialog/Loading.tsx b/src/components/common/dialog/Loading.tsx index 1dbfab8..42459f5 100644 --- a/src/components/common/dialog/Loading.tsx +++ b/src/components/common/dialog/Loading.tsx @@ -6,8 +6,8 @@ const Loading = () => (
로딩 @@ -42,6 +42,5 @@ const dialogBackdropCSS = css` width: 100%; height: 100%; font-size: 1.25rem; - background: rgba(0, 0, 0, 0.2); z-index: 1; `; diff --git a/src/components/community/PostList.tsx b/src/components/community/PostList.tsx index cdfb5b5..f2fd8a1 100644 --- a/src/components/community/PostList.tsx +++ b/src/components/community/PostList.tsx @@ -41,7 +41,7 @@ const boardListWrapperCSS = css` display: flex; flex-direction: column; word-break: keep-all; - padding: 2rem; + padding: 2rem 0.5rem; padding-top: 1.25rem; width: 100%; `; diff --git a/src/components/community/postList/Post.tsx b/src/components/community/postList/Post.tsx index a655634..225c0cb 100644 --- a/src/components/community/postList/Post.tsx +++ b/src/components/community/postList/Post.tsx @@ -34,16 +34,14 @@ const Post: FC = ({ characterId, post }) => ( -
-
-
+
); export default Post; const postCSS = css` - padding: 0.2rem 0 0.2rem 0; + padding: 0.2rem 0 0.2rem 0.5rem; width: 100%; `; @@ -64,6 +62,7 @@ const liCSS = css` flex-direction: row; align-items: center; gap: 0.25rem; + padding-right: 0.3rem; `; const statusCSS = css` @@ -72,19 +71,10 @@ const statusCSS = css` color: ${color.black}; `; -const lineContainerCSS = css` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - color: ${color.lightGray}; - font-size: 0.875rem; -`; - const lineCSS = css` display: block; - margin: 0.625rem; height: 1px; - background: ${color.lightGray}; width: 100%; + background: ${color.lightGray}; + margin: 0.2rem 0; `; diff --git a/src/pages/chats/[character].tsx b/src/pages/chats/[character].tsx index 5d50d4b..03ead00 100644 --- a/src/pages/chats/[character].tsx +++ b/src/pages/chats/[character].tsx @@ -3,64 +3,66 @@ import MessageInput from '@/components/chat/MessageInput'; import Header from '@/components/chat/Header'; import Main from '@/components/chat/Main'; import SEO from '@/components/common/head/SEO'; -import { useEffect, useState } from 'react'; +import { useEffect } from 'react'; import useChatStore from '@/store/chat'; -import { useRouter } from 'next/router'; import { CharacterInfo } from '@/types/characterInfo'; -import { findCharacterById } from '@/utils/api/character'; -import Loading from '@/components/common/dialog/Loading'; +import { ssrFindAllCharacters, ssrFindCharacterById } from '@/utils/api/character'; +import { GetStaticPaths, GetStaticProps } from 'next'; -const Character = () => { - const router = useRouter(); - const { character: characterId } = router.query; - const [characterInfo, setCharacterInfo] = useState(); +const Character = ({ characterInfo }: { characterInfo: CharacterInfo }) => { const { setChatInfo } = useChatStore(); useEffect(() => { - if (characterId && typeof characterId === 'string') { - findCharacterById(characterId) - .then((data) => { - setCharacterInfo(data); - setChatInfo(data.characterName, data.characterId); - }) - .catch((error) => { - console.error('Error fetching post:', error); - }); - } - }, [characterId]); + setChatInfo(characterInfo.characterName, characterInfo.characterId); + }, []); return ( <> - +
- {characterInfo - ? ( - <> -
-
-
-
- - - ) : } +
+
+
+
+
); }; export default Character; +export const getStaticPaths: GetStaticPaths = async () => { + const characterIds = await ssrFindAllCharacters(); + + return { + paths: characterIds.map((data) => ({ params: { character: data.characterId.toString() } })), + fallback: 'blocking', // 존재하지 않는 경로의 경우, 서버에서 렌더링하도록 설정 + }; +}; + +export const getStaticProps: GetStaticProps = async (context) => { + const { character } = context.params!; + + try { + const characterInfo = await ssrFindCharacterById(character as string); + return { props: { characterInfo } }; + } catch (error) { + return { notFound: true }; + } +}; + const pageCSS = css` min-height: 100vh; display: flex; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 584f9c0..635c495 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -31,7 +31,7 @@ const Home = () => { 시작하기 - + diff --git a/src/store/chat.ts b/src/store/chat.ts index 2d0606f..b0e3ae6 100644 --- a/src/store/chat.ts +++ b/src/store/chat.ts @@ -10,8 +10,8 @@ interface NewChatContentState { export interface ChatState { chatContents: ChatContentsState[], - chatInfo: { characterName: string, characterId: string } | null; - setChatInfo: (characterName: string, characterId: string) => void; + chatInfo: { characterName: string, characterId: number } | null; + setChatInfo: (characterName: string, characterId: number) => void; clearChatContents: () => void; initChatContents: (history: ChatContentsState[]) => void; addChatContents: (newChat: NewChatContentState) => number; @@ -22,7 +22,7 @@ export interface ChatState { const useChatStore = create((set, get) => ({ chatContents: [], chatInfo: null, - setChatInfo: (characterName: string, characterId: string) => set(() => ({ + setChatInfo: (characterName: string, characterId: number) => set(() => ({ chatInfo: { characterId, characterName }, })), clearChatContents: () => set(() => ({ diff --git a/src/utils/api/accounts.ts b/src/utils/api/accounts.ts index cb87472..9a876af 100644 --- a/src/utils/api/accounts.ts +++ b/src/utils/api/accounts.ts @@ -1,5 +1,6 @@ import defaultInstance from '@/utils/axiosInstance/defaultInstance'; import clientInstance from '@/utils/axiosInstance/clientInstance'; +import ssrInstance from '@/utils/axiosInstance/ssrInstance'; interface Credentials { email: string, password: string, provider: string @@ -57,7 +58,7 @@ export const credentialsSignupAPI = async ({ provider: 'Credential', }; - const result = await defaultInstance.post('members/signup', sendSignupData); + const result = await ssrInstance.post('members/signup', sendSignupData); return result.data; }; diff --git a/src/utils/api/character.ts b/src/utils/api/character.ts index b0f194c..839d1e8 100644 --- a/src/utils/api/character.ts +++ b/src/utils/api/character.ts @@ -1,11 +1,23 @@ +import { CharacterInfo } from '@/types/characterInfo'; import webServerInstance from '@/utils/axiosInstance/webServerInstance'; +import ssrInstance from '@/utils/axiosInstance/ssrInstance'; export const findAllCharacters = async () => { - const result = await webServerInstance.get('/characters'); + const result = await webServerInstance.get('/characters'); return result.data; }; export const findCharacterById = async (characterId: string) => { - const result = await webServerInstance.get(`/characters/${characterId}`); + const result = await webServerInstance.get(`/characters/${characterId}`); + return result.data; +}; + +export const ssrFindAllCharacters = async () => { + const result = await ssrInstance.get('/characters'); + return result.data; +}; + +export const ssrFindCharacterById = async (characterId: string) => { + const result = await ssrInstance.get(`/characters/${characterId}`); return result.data; }; diff --git a/src/utils/axiosInstance/ssrInstance.ts b/src/utils/axiosInstance/ssrInstance.ts new file mode 100644 index 0000000..9f8c18b --- /dev/null +++ b/src/utils/axiosInstance/ssrInstance.ts @@ -0,0 +1,29 @@ +import axios, { AxiosError } from 'axios'; + +const ssrInstance = axios.create({ + baseURL: `${process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:8080/'}api/`, +}); + +ssrInstance.interceptors.response.use((response) => response, (error: AxiosError) => { + console.error('ERROR', error.toJSON()); + if (error.response && error.response.status === 401) { + console.error('ERROR', error.toJSON()); + } + return Promise.reject(error); +}); + +ssrInstance.interceptors.request.use( + async (config) => { + const token = process.env.SSR_TOKEN; + + if (token) { + // eslint-disable-next-line no-param-reassign + config.headers.Authorization = `Bearer ${token}`; + } + + return config; + }, + (error) => Promise.reject(error), +); + +export default ssrInstance;