ChallengeFlow๋ ๊ทธ๋ฃน์ ๊ตฌ์ฑํ์ฌ ์ํ๋ ์ฃผ์ ์ ๋ํด ์๋ก ํ์ต์ ๋๋ชจํ ์ ์๋๋ก ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ์น ์๋น์ค์ ๋๋ค.
GitHub ๋ก๊ทธ์ธ | ์ฑ๋ฆฐ์ง ์์ฑ |
---|---|
![]() |
![]() |
์ฑ๋ฆฐ์ง ์์ธ | ์ํฌ์คํ์ด์ค ๋ชฉ๋ก |
![]() |
![]() |
์ํฌ์คํ์ด์ค ์์ธ | ์ด๋ฉ์ผ ๋ก๊ทธ์ธ |
![]() |
![]() |
์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ๊ณ ๋ คํ์ฌ ์ ์ธ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ๋ ค ๋ ธ๋ ฅํ์ต๋๋ค. ๊ตฌ์ฒด์ ์ธ ์๋ก, React 18 ๋ฒ์ ์์ ์ ๊ณตํ๋ Suspense์ ErrorBoundary๋ฅผ ํ์ฉํ์ฌ ๋ก๋ฉ ์ํ์ ์ค๋ฅ ๊ฒฝ๊ณ๋ฅผ ๊ตฌ์ฑํ์ผ๋ฉฐ, ๋ก๋ฉ๊ณผ ์ค๋ฅ UI์ ๋ํ ์ฑ ์์ ์ปดํฌ๋ํธ ์ธ๋ถ๋ก ์์ํ์์ต๋๋ค.
<section>
<WorkspaceSearchFilter handleChangeOpenType={setOpenType} />
<CompositionBoundaryReactQuery error={(errorProps) => <WorkspaceError {...errorProps} />} suspense={<Loader />}>
<WorkspaceList openType={openType} />
</CompositionBoundaryReactQuery>
</section>
๐ฆroot/src
โโโ ๐ auth
โโโ ๐ challenge
โโโ ๐ layout
โโโ ๐ pages
โ โโโ ๐ api
โ โโโ ๐ challenge
โ โโโ ๐ profile
โ โโโ ๐ workspace
โโโ ๐ reaction
โ โโโ ๐ comment
โ โโโ ๐ emoji
โโโ ๐ shared
โโโ ๐ workspace
์ง์ญ์ฑ์ ๊ณ ๋ คํ ํจํค์ง ๊ตฌ์กฐ๋, ์ฐ๊ด์ฑ์ด ๋์ ์ฝ๋๋ผ๋ฆฌ ๊ฐ์ ํด๋ ๋ด์ ์์น์ํค๋ ๊ตฌ์กฐ์ ๋๋ค.
์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ์ ํํจ์ผ๋ก์จ ๋๊ฐ์ง ํฐ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค.
1. ๋์ ์์ง๋
ํด๋ ๋ด๋ถ๋ ์๋ก ๋ฐ์ ํ๊ฒ ์ฐ๊ด๋์ด ์์ผ๋ฏ๋ก, ๋ณ๊ฒฝ์ด ๋ฐ์ํ๋๋ผ๋ ํด๋น ํจํค์ง ๋ด์์ ๋๋ถ๋ถ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒํ๊ณ , ์ฝ๋์ ๊ฐ๋
์ฑ์ ํฅ์์ํต๋๋ค.
2. ๋ฎ์ ๊ฒฐํฉ๋
์๋ก ๋ค๋ฅธ ํจํค์ง๊ฐ์ ์์กด์ ์ต์ํํจ์ผ๋ก์จ, ํ ํด๋ ๋ด์์์ ๋ณ๊ฒฝ์ด ๋ค๋ฅธ ํด๋์ ๋ฏธ์น๋ ์ํฅ์ ์ค์ผ ์ ์์ต๋๋ค. ์ด๋ ์ ์ฒด์ ์ธ ์์คํ
์ ์์ ์ฑ์ ์ ์งํ๋๋ฐ ๋์์ด ๋ฉ๋๋ค.
ํด๋น ํ๋ก์ ํธ์์๋ auth
,challenge
,reaction
,workspace
๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ก ๊ตฌ์ฑํ์์ต๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ ๊ฐ ๋๋ฉ์ธ๋ณ๋ก ์ปดํฌ๋ํธ, ํ
๋ฑ์ ํฌํจํ๊ณ ์์ผ๋ฉฐ, ์ด๋ ๊ฐ ๋๋ฉ์ธ์ด ๋
๋ฆฝ์ ์ผ๋ก ์๋ํ ์ ์๋๋ก ํด์ค๋๋ค.
ํ ์์ฒด์ ์ผ๋ก ๊ฐ๋ฐํ ๋์์ธ์์คํ ์ ํ์ฉํ์ฌ ๋ฏธ๋ฆฌ ์ค๊ณ๋ UI ์ปดํฌ๋ํธ ๋ฐ ์คํ์ผ ํฌํผ ์ปดํฌ๋ํธ๋ฅผ ์ ๊ทน์ ์ผ๋ก ํ์ฉํ์ฌ ์ด๊ธฐ ๊ฐ๋ฐ ์๋๋ฅผ ๋์ผ ์ ์์์ต๋๋ค.
ํ๋ก์ ํธ์ ์ฌ์ฉ๋ ๊ธฐ์ ๋ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
React Query๋ API์์ ํต์ ์ ๋ด๋นํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ๋ฉฐ ๋๊ธฐํํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ์บ์ํ๊ณ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ ๋ฐ์ดํธํ์ฌ ํญ์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ํ, ์บ์๋ ๋ฐ์ดํฐ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋์ด ํ์ด์ง ์ด๋์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. React Query๋ React์ ํตํฉ์ด ์ ๋์ด ์๊ณ ContextAPI์ Suspense๋ฅผ ํ์ฉํ์ฌ ๋ ๋์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
๋ฌดํ์คํฌ๋กค ๊ธฐ๋ฅ์ ๋์
ํ๊ธฐ ์ํด react-intersection-observer
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ์์ต๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ์ธ์ ์ธ hook์ ์ ๊ณตํ๊ณ , IntersectionObserver API๋ฅผ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์์ด์ ์ ์ฉํ๊ฒ ํ์ฉํ ์ ์์์ต๋๋ค.
NextAuth๋ ์ฌ์ฉ์ ์ธ์ฆ ์ฒ๋ฆฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ๋ก์ ํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ Firebase๋ฅผ ์ฌ์ฉํ๋ฏ๋ก, NextAuth์์ ์ ๊ณตํ๋ ์ธ์ฆ ๊ณต๊ธ์(Provider)์ ์ฐ๋ํ์ฌ ํ์ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ์ํํ๊ณ API ํต์ ์ ์๋ฒ ๋ด์์ ์ธ์ ์ ํ์ฉํ ์ธ์ฆ ๋ก์ง์ ๊ตฌํํ์์ต๋๋ค.
Challenge Flow๋ Firebase๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ, ์๋ฒ๋ฅผ ์ง์ ๊ตฌ์ถํ๊ณ ์ ์ง๊ด๋ฆฌํ ํ์ ์์ด ๋ฐฑ์๋ ์๋น์ค๋ฅผ ์์ฝ๊ฒ ์ฌ์ฉํ ์ ์์์ต๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ ๋จ๊ณ์์ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๊ฐ๋ฐ์ ๋์ฑ ์ง์คํ๊ณ , ํ๋ก์ ํธ์ ์ด๊ธฐ๋ฒ์ ์ ์ ์ํ๊ฒ ๋ฆด๋ฆฌ์ฆํ๋๋ฐ ์ด์ ์ ๋ง์ถ ์ ์์์ต๋๋ค.
์ด๊ธฐ๋ฒ์ ์์๋ ์ ์ํ ๊ฐ๋ฐ์ ์ํด Firebase๋ฅผ ํ์ฉํ์ง๋ง ํ๋ก์ ํธ๊ฐ ์ฑ์ฅํ๋ฉด์ ๋ ๋ณต์กํ๊ณ ํํํ ๋ฐฑ์๋ ์์คํ ์ด ํ์ํ ๊ฒฝ์ฐ Firebase๋ฅผ Node.js์ RDBS๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๋ฐฑ์๋ ์์คํ ์ผ๋ก ์ ํํ ๊ณํ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
UI ๊ด์ ์์ ํด๋ผ์ด์ธํธ ์ํ๋ฅผ ์ ์ดํ๊ธฐ ์ํด '์ ํ์ํ๊ธฐ๊ณ' ๊ฐ๋ ์ ํ์ฉํ์ต๋๋ค. ์ ํ์ํ๊ธฐ๊ณ๋, ์์คํ ์ด ํน์ ์ํ์์ ๋ค๋ฅธ ์ํ๋ก ์ ์ด๋๋ ๊ณผ์ ์ ๋ชจ๋ธ๋งํ๋ ์ํ์ ๋ชจ๋ธ์ ๋๋ค. ์ด ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ๊ธฐ์กด ๋ฐ์ดํฐ ๊ด์ ์ํ ๊ด๋ฆฌ๋ณด๋ค ์ฌ์ฉ์ ์ธํฐํ์ด์ค์์ ๋ฐ์ํ๋ ๋ค์ํ ์ํฉ์ ๋์ํ ์ ์์ต๋๋ค.