๐ ๋ฐฐํฌ ์ฃผ์ : https://www.pickspot.co.kr
๐ API ๋ช ์ธ์
๐ Swagger
| ๊ธฐ์ ์คํ | ์ ํ ์ด์ |
|---|---|
| React.js | ์ค์๊ฐ ๋ ๋๋ง๊ณผ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ UI๋ก ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ ํ๋ณด |
| TypeScript | ์ ์ ํ์ดํ์ผ๋ก ์ค๋ฅ ์๋ฐฉ ๋ฐ ์๋์์ฑ/๋ฆฌํฉํ ๋ง ํธ์์ฑ ํฅ์ |
| Vite | ๋น ๋ฅธ ๋ฒ๋ค๋ง๊ณผ HMR๋ก ๊ฐ๋ฐ ์์ฐ์ฑ ์ฆ๊ฐ |
| Zustand | ๊ฐ๋จํ๊ณ ๊ฐ๋ฒผ์ด ์ ์ญ ์ํ ๊ด๋ฆฌ |
| Axios | ๊ฐํธํ API ์์ฒญ ์ฒ๋ฆฌ์ ๋น๋๊ธฐ ๊ด๋ฆฌ |
| TailwindCSS | ๋น ๋ฅด๊ณ ์ผ๊ด๋ ์ ํธ๋ฆฌํฐ ๊ธฐ๋ฐ ์คํ์ผ๋ง |
| React-Query | ์๋ฒ ์ํ ์บ์ฑ ๋ฐ ๋ก๋ฉ/์๋ฌ ์ฒ๋ฆฌ ๋ฑ API ์ค์ฌ ์ฑ์ ์ต์ ํ |
| Jest | ์์ ์ ์ธ ๋ฆฌํฉํ ๋ง์ ์ํ ํ ์คํธ ์ฝ๋ ์์ฑ ๊ฐ๋ฅ |
src/
โโโ ๐app/ # ์ ํ๋ฆฌ์ผ์ด์
์ด๊ธฐํ, ์คํ์ผ, ํ๋ก๋ฐ์ด๋
โ โโโ ๐routes/ # ๋ผ์ฐํฐ ์ค์
โโโ ๐pages/ #ํ์ด์ง ์ปดํฌ๋ํธ (๊ฐ ํ์ผ์ URL ๊ฒฝ๋ก ํ๋๋ฅผ ๋ด๋นํ๋ฉฐ, ๊ฐ ํ์ด์ง๋ ์๋ features์์ ์กฐํฉ๋ UI ์ปดํฌ๋ํธ๋ฅผ ํฌํจ)
โ โโโ ๐MapViewPage.tsx
โ โโโ ๐HistoryPage.tsx
โ โโโ ๐FindPage.tsx
โ โโโ ๐ReviewPage.tsx
โ โโโ ๐DetailPage.tsx
โ โโโ ๐MainPage.tsx
โโโ ๐widgets/ # ๋ณตํฉ์ ์ธ UI ๋ธ๋ก(ํ์ด์ง์ ์ํฐํฐ ์ฌ์ด์์ ์ฌ์ฌ์ฉ๋๋ UI ๊ตฌ์ฑ ์์)
โ โโโ ๐headers/
โโโ ๐features/ # ๊ฐ ๊ธฐ๋ฅ(๋๋ฉ์ธ) ๋จ์๋ก ๋ฌถ์ธ ์ปดํฌ๋ํธ ์งํฉ
โ โโโ ๐mapView/
โ โโโ ๐history/
โ โโโ ๐find/
โ โโโ ๐review/
โ โโโ ๐visited/
โ โโโ ๐notVisited/
โโโ ๐entities/ # ๋น์ฆ๋์ค ์ค์ฌ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋จ์ (์ฌ์ฌ์ฉ์ฑ์ด ๋์ api, hooks, model ๋ถ๋ฆฌ)
โ โโโ ๐user/
โ โโโ ๐place/
โ โโโ ๐event/
โโโ ๐shared/ # ํ๋ก์ ํธ ์ ์ญ์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ ํธ๋ฆฌํฐ/์ค์ ๋ชจ์
โ โโโ ๐api/ # Axios ๋ฑ์ API ์ธ์คํด์ค, ์ธํฐ์
ํฐ ์ ์
โ โโโ ๐utils/ # ๋ ์ง ํฌ๋งคํ
, debounce ๋ฑ ์ ํธ๋ฆฌํฐ ํจ์๋ค์ด ์์น
โ โโโ ๐ui/ # ๋ฒํผ, ๋ชจ๋ฌ, ์ธํ, ๋ฐํ
์ํธ ๋ฑ ์์ ๋จ์ UI ์ปดํฌ๋ํธ
โ โโโ ๐stores/ # ๊ธ๋ก๋ฒ ์ํ ๊ด๋ฆฌ
โ โโโ ๐model/ # ์ ์ญ์ ์ผ๋ก ๊ณต์ ๋๋ ํ์
ํน์ Enum
โโโ ๐assets/ # ์ ์ ๋ฆฌ์์ค๋ฅผ ์ ์ฅํ๋ ํด๋ (์ด๋ฏธ์ง ์ฑ๋ฅ ์ต์ ํ)
โโโ ๐icon/
โโโ ๐image/
feature/
โโโ ๐ui/ # UI ๊ด๋ จ ์ฝ๋
โ โโโ ๐index.ts # ์ปดํฌ๋ํธ export
โ โโโ ๐Component.tsx # ์ปดํฌ๋ํธ ํ์ผ
โ
โโโ ๐model/ # ํ์
์ ์
โ โโโ ๐index.ts # ํ์
export
โ โโโ ๐feature.type.ts # ํ์
์ ์ ํ์ผ
โ
โโโ ๐service/ # API ๊ด๋ จ ์ฝ๋
โ โโโ ๐index.ts # ์๋น์ค export
โ โโโ ๐api.ts # API ํธ์ถ ํจ์
โ
โโโ ๐hooks/ # ์ปค์คํ
ํ
โ โโโ ๐index.ts # ํ
export
โโโ โโโ ๐useHook.ts # ํ
์ ์ ํ์ผ
Axios + React + Query
API ์์ฒญ์ service์์ Axios๋ก๋ง ์ฒ๋ฆฌํ๊ณ , hooks์์ React Query๋ฅผ ํตํด ์ํ๋ฅผ ๊ด๋ฆฌํ๋๋ก ๋ถ๋ฆฌํด ๊ฐ ์ญํ ์ ์ฑ ์์ ๋ช ํํ ํ์ต๋๋ค. ์ด๋ก์จ ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ด ํฅ์๋์์ต๋๋ค.
Jest ๊ธฐ๋ฐ ํ ์คํธ ์ฝ๋ ์์ฑ
utils ์ผ๋ถ ํจ์์ ๋ํ ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ์ฌ ์ฝ๋์ ์์ ์ฑ๊ณผ ์ ๋ขฐ๋๋ฅผ ๋์์ต๋๋ค. ๋ณ๊ฒฝ ์ฌํญ์ ๋ํ ํ๊ท ํ ์คํธ๊ฐ ๊ฐ๋ฅํด์ ธ ์์ ์ ์ธ ๋ฆฌํฉํ ๋ง๊ณผ ๋ฐฐํฌ๊ฐ ๊ฐ๋ฅํด์ก์ต๋๋ค.
๋ฐํ ์ํธ ์ฌ์ฉ์ฑ ๊ฐ์
-
์ค๋ ํฌ์ธํธ ๊ธฐ๋ฅ ๊ตฌํ: 30%, 50%, 80% ์์น์ ๋ฐํ ์ํธ๊ฐ ๊ณ ์ ๋๋๋ก ์ค์ ํ์ฌ ์ฌ์ฉ์๊ฐ ์ง๊ด์ ์ผ๋ก ์กฐ์ํ ์ ์๋๋ก ํ์ต๋๋ค.
-
๋์ ๋์ด ์กฐ์ : ResizeObserver๋ฅผ ํ์ฉํด ์ฝํ ์ธ ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ฐํ ์ํธ ๋์ด๊ฐ ์๋์ผ๋ก ์กฐ์ ๋๋๋ก ๊ตฌํํ์ต๋๋ค.
-
์คํฌ๋กค/๋๋๊ทธ ๋ถ๋ฆฌ ๋ก์ง:
- data-scrollable ์์ฑ์ผ๋ก ์คํฌ๋กค ๊ฐ๋ฅํ ์์ญ์ ์๋ณ
- scrollTop === 0์ผ ๋๋ง ๋๋๊ทธ ๊ฐ๋ฅ
- touchAction: pan-y, overscrollBehavior: contain์ ์ ์ฉํด ์คํฌ๋กค๊ณผ ๋๋๊ทธ์ ์ถฉ๋์ ๋ฐฉ์ง
์ด๋ฅผ ํตํด ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ ๋ถ๋๋ฝ๊ณ ์ง๊ด์ ์ธ UX๋ฅผ ์ ๊ณตํ ์ ์์์ต๋๋ค. ๋ํ, ์ปดํ์ด๋ ์ปดํฌ๋ํธ ํจํด์ ๋์ ํ์ฌ ๊ด๋ จ ์ปดํฌ๋ํธ๋ฅผ ๋ค์์คํ์ด์ค ํํ๋ก ๊ตฌ์ฑํ๊ณ , ์ ์ธ์ ์ด๊ณ ์ ์ฐํ API๋ฅผ ์ ๊ณตํ ์ ์๋๋ก ์ค๊ณํ์ต๋๋ค.
Lighthouse ๊ธฐ๋ฐ ์ด๋ฏธ์ง ์ต์ ํ
๊ธฐ์กด์ PNG ํ์ผ์ WebP ํฌ๋งท์ผ๋ก ๊ต์ฒดํ์์ต๋๋ค. ๋ํ, Vite ํ๊ฒฝ์ ๋ง์ถฐ public/icons์ ์๋ ์ด๋ฏธ์ง๋ฅผ src/assets/icons๋ก ์ฎ๊ธฐ๊ณ , static import ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ์ฌ ๋ฒ๋ค ์ต์ ํ ๋ฐ ๋ก๋ฉ ์๋ ๊ฐ์ ์ ์งํํ์์ต๋๋ค.
| ๊ธฐ์ ์คํ | ์ฃผ์ ํ์ฉ ๋ฐ ์ ํ ์ด์ |
|---|---|
| Java 21 | ์ฅ๊ธฐ ์ง์(LTS, ~2031) ์ ๊ณต, Virtual Thread๋ก ๋ค์ค ์ธ๋ถ API ํธ์ถ ์ต์ ํ |
| Spring Boot 3.4.4 | Java 21 ๊ณต์ ์ง์, Virtual Thread ์ต์ ํ, RestClient ๋ฐ Actuator ๋ฑ ์ต์ ๊ธฐ๋ฅ ํฌํจ |
| Spring Data JPA | JPA ๊ธฐ๋ฐ ORM ๊ตฌํ, Repository๋ก CRUD ์๋ํ, QueryDSL๊ณผ์ ์ฐ๊ณ๋ก ๋ณต์กํ ์ฟผ๋ฆฌ ๊ฐ๊ฒฐ ์ฒ๋ฆฌ |
| PostgreSQL + PostGIS | ์ธ๋ฑ์ค ์ต์ ํ๋ก ์ ์ฅ ํจ์จ ์ฆ๊ฐ, PostGIS๋ก ๋์ฉ๋ ๊ณต๊ฐ ์ขํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ |
| Redis | ์ธ๋ฉ๋ชจ๋ฆฌ ์บ์๋ก ์ค์๊ฐ ๊ฒฝ๋ก ์กฐํ ์ฑ๋ฅ ํฅ์, TTL ๊ธฐ๋ฐ ์บ์ฑ์ผ๋ก ๋ฉฑ๋ฑ์ฑ ๋ณด์ฅ |
| Docker & Docker Compose | ์ปจํ ์ด๋ ๋จ์ ๋ฐฐํฌ๋ก ํ์ฅ์ฑ ๋์, ์ปดํฌ๋ํธ๋ณ ๋ ๋ฆฝ ์คํ ๋ฐ ๊ด๋ฆฌ ์ฉ์ด |
| GitHub Actions | ์ฝ๋ ํธ์ ์ ์๋ CI/CD ์คํ, GUI ๊ธฐ๋ฐ ๋ชจ๋ํฐ๋ง์ผ๋ก ๊ฐ๋ฐ ํธ์์ฑ ํฅ์ |
| QueryDSL | ํ์ ์์ ํ DSL ๊ธฐ๋ฐ ์ฟผ๋ฆฌ ์์ฑ, ์ปดํ์ผ ํ์ ์ค๋ฅ ๊ฒ์ถ๋ก ์์ ์ฑ ํ๋ณด |
| Naver Cloud Platform | ์ ์ฐํ ๋ฐฐํฌ/๋คํธ์ํฌ ๊ตฌ์ฑ, ํ๊ธ ๋ฌธ์๋ก ์ ๊ทผ์ฑ ์ฐ์, ์ปจํ ์ด๋/๋ ์ง์คํธ๋ฆฌ/Object Storage ์ฐ๋ ์ฉ์ด |
๋ฌดํ ์คํฌ๋กค ์ฟผ๋ฆฌ ์ต์ ํ
- slice ๋ฐฉ์์ ๋ฌดํ ์คํฌ๋กค ๋ฐฉ์๊ณผ ์ฟผ๋ฆฌ ์์ฑ ์ fetch join ์ ํตํด์ ์ฟผ๋ฆฌ ๋ฐ์์ ๊ฐ์ ์์ผฐ์ต๋๋ค
- ์ด ๊ณผ์ ์์ QueryDSL ์ฌ์ฉ์ ํตํด ๋ณต์กํ ์กฐ๊ฑด์ ๋์ ์ฟผ๋ฆฌ๋ฅผ ์ฝ๊ฒ ๊ตฌ์ฑํ์์ต๋๋ค
Redis ๊ธฐ๋ฐ ์ค์๊ฐ ์บ์ฑ ์ฒ๋ฆฌ
- ์ธ๋ถ API๋ฅผ ํ์ฉํ ์ค์๊ฐ ๊ฒฝ๋ก ์กฐํ ๋ฐ ์ค๊ฐ ์ง์ ๊ณ์ฐ ์, ๋์คํฌ ๊ธฐ๋ฐ DB ์ ๊ทผ(I/O)์ ์ค์ด๊ธฐ ์ํด ์ธ๋ฉ๋ชจ๋ฆฌ NoSQL์ธ Redis๋ฅผ ๋์ ํ์์ต๋๋ค.
- ์ธ๋ถ API ์๋ต์ Redis์ ์บ์ฑํ๊ณ , TTL(Time To Live) ์ ์ ์ฉํ์ฌ ๋ฉฑ๋ฑ์ฑ ๋ณด์ฅ ๋ฐ ์ค๋ณต ํธ์ถ ๋ฐฉ์ง๋ฅผ ์คํํ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ธ๋ถ API ํธ์ถ ํ์ ์ ํ ์ ์ฑ ์ ์ ์ฐํ๊ฒ ๋์ํ ์ ์๋๋ก ๊ตฌ์ฑํ์์ต๋๋ค.
์ฃผ์ ํ์ฑ ์ ๋ถํ์ํ Pattern ๊ฐ์ฒด ์์ฑ ์ ๊ฑฐ
- ๊ธฐ์กด์๋
address.split(" ")์ ์ฌ์ฉํ์ฌ ์ฒซ ๋ฒ์งธ ์ง์ญ๋ช ์ ์ถ์ถํ์ง๋ง, ์ด๋ ๋ด๋ถ์ ์ผ๋กPattern.compile()์ ํตํด ์ ๊ทํํ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ ๋ฉ๋๋ค. - ์ด๋ฅผ
substring()๊ณผindexOf()๊ธฐ๋ฐ์ผ๋ก ๋ณ๊ฒฝํจ์ผ๋ก์จ Pattern ๊ฐ์ฒด ์์ฑ์ ๋ฐฉ์งํ๊ณ , GC ๋ถ๋ด์ ์ค์ฌ ๋ฌธ์์ด ์ฒ๋ฆฌ ์ฑ๋ฅ์ ํ๋ณดํ์์ต๋๋ค.


