'μ€λ λ μ μ§?'λΌλ μκ°μμ κΈ°νλ μ΄ νλ‘μ νΈλ μ¬λλ€μ΄ μΈμΆ μ 무μμ μ μμ§ μ½κ² κ²°μ ν μ μκ² λμλ μμ΄λμ΄λ‘λΆν° κΈ°νλμμ΅λλ€. μ¬μ©μκ° λ μ¨λ₯Ό νμΈνλ©΄μ λ€λ₯Έ μ¬λλ€μ μ€μ μ°©μ₯μ λ³Ό μ μκ² ν¨μΌλ‘μ¨, κ·Έλ€μ μ·μ°¨λ¦Όμ μ°Έκ³ νμ¬ μμ μ μ€νμΌμ μ νν μ μμ΅λλ€. μ¬μ©μλ μμ μ΄ μνλ μ€νμΌμ μ¬λλ€μ νλ‘μ° ν μ μμΌλ©°, μ΄λ₯Ό ν΅ν΄ λ³΄λ€ κ΅¬μ²΄μ μΈ μ€νμΌ μμ΄λμ΄λ₯Ό μ»μ μ μμ΅λλ€. λν, μ¨λΌμΈ μλ₯ μΌνλͺ°κ³Όμ μ°κ³λ₯Ό ν΅ν΄ λΉμ¦λμ€ λͺ¨λΈμ κ³ λνν μ μλ κ°λ₯μ±μ μ΄μ΄λμμ΅λλ€.
μ΄λ¦ | κΉμ±ν | κΆμ€μ |
μν | FE-Lead | TeamMate |
κΈ°λ₯ | * λ©μΈμ§λ, λ μ¨λλ‘ κ²μλ¬Ό λ±λ‘, λ‘κ·ΈμΈ λ° νμνν΄, PWA, FCMμλ, νλ‘ νΈ λ°°ν¬ CI/CD | * νΌλ 리μ€νΈ λ° μμΈ νΌλ RUD, 1:1 μ±ν λ° λ¦¬μ€νΈ, μ μ νλ‘ν, μ 보 μμ , νλ‘μ°, λ‘κ·Έμμ |
κΉνλΈ | κΉμ±νμ GitHub | κΆμ€μμ GitHub |
- κ°λ° κΈ°κ°: 2024.02.29 ~ 2024.04.21
βββ README.md
βββ components.json
βββ dist
βββ index.html
βββ node_modules
βββ package-lock.json
βββ package.json
βββ postcss.config.js
βββ public
βββ src
β βββ App.tsx
β βββ assets
β βββ components
β βββ features
β β βββ Chat
β β βββ Feed
β β βββ Home
β β βββ Login
β β βββ Notifications
β β βββ OauthRedirect
β β βββ OptionalInfo
β β βββ Posts
β β βββ Profile
β β βββ Splash
β βββ global.css
β βββ hooks
β βββ lib
β βββ main.tsx
β βββ mocks
β βββ routes
β βββ services
β βββ store
β βββ types
β βββ vite-env.d.ts
βββ svg.d.ts
βββ svgr.template.cjs
βββ tailwind.config.js
βββ tsconfig.json
βββ tsconfig.node.json
βββ vite.config.ts
βββ yarn.lock
νμΌ κ΅¬μ‘°λ ν¬κ² λ λΆλΆμΌλ‘ λλ μ μμ΅λλ€ :
- 곡ν΅
src λλ ν 리 λ°λ‘ μλμ μμΉ (μ: components, hooks, routes, services, mocks λ±)
νλ‘μ νΈ μ 체μ 곡ν΅μΌλ‘ μ μ©λκ±°λ μ¬λ¬ κΈ°λ₯μμ 곡ν΅μ μΌλ‘ μ¬μ© κ°λ₯ν ꡬν μ¬νμ λ‘λλ€. (components - μ¬μ¬μ© κ°λ₯ν 컀μ€ν λ° shadcn ui μ»΄ν¬λνΈ)
- κΈ°λ₯λ³ νμΌ
src/features λλ ν 리 μλμ μ£Όμ κΈ°λ₯ ꡬλΆμ λ°λΌ λλ ν 리λ₯Ό λ§λ€μ΄ κ΄λ¦¬ μ: Chat, Feed, Home, Notification λ± κ° κΈ°λ₯ λλ ν 리 μμλ api, hooks, store, types λ±μ νμΌλ€μ λ μΌλ‘μ¨ κΈ°λ₯λ³λ‘ νΉνλ ꡬν μ¬νμ ν λ° λͺ¨μ λͺ¨λννμ΅λλ€.
ꡬ쑰μ μ₯μ :
- μ½λμ λͺ¨λνμ μ¬μ¬μ©μ± μ¦κ°
κ³΅ν΅ νμΌ λΆλ¦¬λ‘ μ½λ μ€λ³΅ κ°μ λ° μ¬μ¬μ©μ± ν₯μ
- μ μ§λ³΄μμ± ν₯μ
κΈ°λ₯λ³ νμΌ λΆλ¦¬λ‘ νΉμ κΈ°λ₯ μμ μ νμΌ κ° νμ μκ°μ μ€μ΄κ³ , νλ‘μ νΈ κ·λͺ¨μ λ§λ ν¨μ¨μ μΈ μ μ§λ³΄μ κ°λ₯
- νμΌ κ΅¬μ‘°μ μΌκ΄μ±κ³Ό μμΈ‘ κ°λ₯μ±
μΌκ΄λ κ΅¬μ‘°λ‘ λ€λ₯Έ κ°λ°μλ€λ μ½λλ₯Ό μ½κ² μ΄ν΄νκ³ νμν μ μμ β
- μ¬μ©μ μμΉμ λ μ§ μ 보λ₯Ό κΈ°λ°μΌλ‘ ν΄λΉ μμ μ λ μ¨μ ν¨κ» ootd κ²μλ¬Όμ ν¬μ€ν ν μ μλ κΈ°λ₯μ μ€μ¬μΌλ‘ ν¨
- μΉ΄μΉ΄μ€ μ§λ API, μΉ΄μΉ΄μ€ OAuth 2.0 μ¬μ©
-
μ ν μ 보 μ λ ₯: κ°μΈ λ§μΆ€ν κ²μλ¬Ό μ 곡μ μν΄, μ΅μ΄ κ°μ μ 체ν, 체μ§, μ€νμΌμ λν μ νμ 보 μ λ ₯ (λ§μ΄νμ΄μ§μμ μμ κ°λ₯)
-
μΉ΄μΉ΄μ€ κ°νΈ κ°μ λ° λ‘κ·ΈμΈ: OAuth 2.0 νμ©, Access/Refresh Token μΏ ν€ μ μ₯, μΈμ κ΄λ¦¬
-
useCurrentLocation, useKakaoMap 컀μ€ν ν ꡬν : ν κΈ°λ₯μ μ€λ³΅λλ λ‘μ§μ λΆλ¦¬ν¨μΌλ‘μ¨ μ½λ μ¬μ¬μ©μ±μ λμ
-
tanstack-queryμ useQueryλ₯Ό ν΅ν μλ² λ°μ΄ν° μν κ΄λ¦¬
-
νμ¬ μμΉ μ€μκ° λ μ¨ μ‘°ν: μλ¨ λ μ¨ λ°λ‘ νμΈ κ°λ₯, ν΄λ¦μ νμ₯λμ΄ μμΈ μ 보 μ‘°ν
-
μ§λλ₯Ό λλκ·Ένλ©° μ μ μμΉ κ·Όμ²μ λ μ¨ λλ‘ νμ: ꡬμλ³ κ²μ κ²μλ¬Όλ€μ κ·Έλ£Ήνν΄ λ§μ»€λ‘ νμ
-
react hook formμΌλ‘ multi-step form ꡬν λ° form data μν κ΄λ¦¬
-
zodλ‘ νμ μ€ν¬λ¦½νΈμ μ΅μ νλ validation
-
μ¬μ§ λ±λ‘ (μ€λ³΅ λΆκ°, μ΅λ 3μ₯), μ λ‘λ μμΉ μ§μ (draggable marker 컀μ€ν )
-
μμΉ μ§μ μΌλ‘ νμ¬ λ μ¨ λ°μ΄ν°λ ν¨κ» μ μ₯ (OpenWeatherMap API νμ©)
- useInfiniteQueryλ‘ λ¬΄ν μ€ν¬λ‘€ ꡬν
- νμ¬ μμΉ κΈ°λ° νΌλ 리μ€νΈ νμ
- νΌλ μ€μκ° μ’μμ/λκΈ CRUD
- κ²μκΈ μμΈμ‘°ν: λ μ¨ μ 보 λ° μ¬μ§ μΊλ¬μ λ μ΄μμ
-
νλ‘ν μ ν μ 보 μμ , μλ¦Ό μμ μ¬λΆ μμ
-
νλ‘μ/νλ‘μ 리μ€νΈ μ‘°ν λ° νλ‘μ°/μΈνλ‘μ°
-
λ΄ νΌλ μ‘°ν
-
REST API κΈ°λ° λ‘κ·Έμμ, νμνν΄
-
Websocket (stomp/sockjs)μΌλ‘ μ€μκ° μ±ν ꡬν
-
SSE (Server-Sent-Event)λ‘ μ¬μ©μ μ¨λΌμΈ μν μ€μκ° μ λ°μ΄νΈ
-
μ±ν λͺ©λ‘μμ λ©μμ§ μ½μ μν λ°μ
-
FCM (Firebase Cloud Messaging)μΌλ‘ νΈμ μλ¦Ό ꡬν
-
μ΅μ΄ λ‘κ·ΈμΈ μ μλ¦Ό μ€μ νμ μΌλ‘ κΆν μμ²
-
λΈλΌμ°μ κΆν νμ© μ FCM ν ν° μμ± λ° λ°±μλλ‘ μ μ‘
- νλ‘μ νΈμ κ·λͺ¨μ μꡬμ¬νμ κ³ λ €ν΄λ³΄λ©΄, λ³Έ μλΉμ€λ μ€μκ° μ μ μμΉλ₯Ό κΈ°λ°μΌλ‘ ν ν΄λΌμ΄μΈνΈλ¨μμμ μΈν°λμ λΉμ€μ΄ λμ΅λλ€. λ°λΌμ μλ²μ¬μ΄λ λ λλ§ λ± Next.jsλ§μ μ΄μ μ μλΉμ€μ μ¨μ ν λ Ήμ¬λ΄κΈ° μ΄λ ΅λ€κ³ νλ¨νμ΅λλ€. λλΆμ΄ Next.jsμ App routerλ μλμ μΌλ‘ μ΅κ·Όμ 릴리μ¦λμ΄, ν λΌμ΄λΈλ¬λ¦¬λ€κ³Όμ μλ²½ν νΈνμ±μ 보μ₯νκΈ° μ΄λ €μ μ΅λλ€. μ΄μ μ΅λν μμ μ μ΄κ³ μμ±λ μλ μλΉμ€ ꡬμΆμ μν΄ Next.jsλμ μ μ·¨μνκ³ React νλ‘μ νΈλ‘ μ§ννκ² λμμ΅λλ€.
- μ μ νμ κ²μ¬λ₯Ό ν΅ν΄ μ½λμ μμ μ± ν₯μ, μ½λμ κ°λ μ±μ λμ¬μ£Όλ©°, κ°λ° μμ°μ±μ ν₯μ
- νλ‘μ νΈ κ·λͺ¨κ° 컀μ§λ©΄μ μ½λμ 볡μ‘μ±μ΄ μ¦κ°νμ¬ μ½λμ μ μ§λ³΄μμ±μ λμΌ μ μμ΅λλ€.
- μΉμμΌ(Stomp/SockJS) : μ±ν κΈ°λ₯ ꡬν μΉμμΌμ ν΅ν΄ ν΄λΌμ΄μΈνΈμ μλ² κ°μ μ§μμ μΈ μ°κ²°μ μ μ§νκ³ λ©μμ§λ₯Ό μ€μκ°μΌλ‘ μ£Όκ³ λ°μ μ μμ΅λλ€.
- SSE : μ¬μ©μμ μ¨λΌμΈ μν μ λ°μ΄νΈμ κ°μ΄ μλ²μμ ν΄λΌμ΄μΈνΈλ‘μ λ¨λ°©ν₯ μ΄λ²€νΈ μ μ‘μ΄ νμν κ²½μ° SSEλ μλ²μμ ν΄λΌμ΄μΈνΈλ‘ μ΄λ²€νΈλ₯Ό μ μ‘νλλ° μ ν©νλ©°, μΉμμΌλ³΄λ€ κ°λ¨νκ³ κ°λ³μ΅λλ€.
- κ°λ¨νκ³ μ§κ΄μ μ λλ€.
- Reduxμ λΉν΄ 보μΌλ¬νλ μ΄νΈ μ½λκ° μ μ΄ μμ°μ± ν₯μμ μν΄ μ ννμ΅λλ€.
- μ΅μνμ μ€μ μΌλ‘ λΉ λ₯΄κ² μ΄κΈ° 리μ‘νΈ νλ‘μ νΈ νκ²½μ ꡬμΆν μ μκΈ° λλ¬Έμ μ ννμ΅λλ€. λν HMR, λΉ λ₯Έ κ°λ° μλ² μ§μμΌλ‘ κ°λ° κ³Όμ μμμ μμ°μ±μ ν₯μν΄μ€λ€λ μ λ μ₯μ μ΄μμ΅λλ€.
- μ μ°ν 컀μ€ν°λ§μ΄μ§, μ§κ΄μ μΈ ν΄λμ€ μ΄λ¦, κ·Έλ¦¬κ³ λΉ λ₯Έ κ°λ° μλκ° μ₯μ μ λλ€. λν shadcn/uiμμ νΈνμ±λ κ³ λ €λμμ΅λλ€.
- μ κ·Όμ±κ³Ό λμμΈμ΄ κ³ λ €λ κ³ νμ§μ UI μ»΄ν¬λνΈλ₯Ό λΉ λ₯΄κ² ꡬν κ°λ₯
- Tailwind CSSμ μ ν΅ν©λμ΄ μ¬μ©μ΄ νΈλ¦¬ν©λλ€.
- κ°λ¨νκ³ μ§κ΄μ μΈ APIλ₯Ό μ 곡νλ©°
- λμ λΌμ°ν κ³Ό μ€μ²© λΌμ°ν μ μ½κ² ꡬνν μ μμ΅λλ€.
- nalsee μλΉμ€ νΉμ±μ λ°μ€ν¬ν보λ€λ λͺ¨λ°μΌ νκ²½μμ μ¬μ©μ±μ΄ λλλ¬μ§ κ²μ΄λΌκ³ νλ¨νμ΅λλ€. μ΄μ μΉκΈ°λ° νλ‘μ νΈμ΄λ©΄μλ λͺ¨λ°μΌ μ¬μ©μ±μ λμ΄μ¬λ¦΄ μ μλ Progressive Web Appμ ꡬννμ΅λλ€. λλΆμ΄ λ€μ΄ν°λΈ μ±κ³Ό λΉκ΅νμ λ μ¬μ©μμ μλ μ λ°μ΄νΈ μμ΄λ νμ μ΅μ λ²μ μ μ μ§ν μ μλ€λ μ , μΉ κ²μλ§μΌλ‘λ μ΄νμ λ€μ΄λ°μ μ μλ μ κ·Όμ± λ±μ μ₯μ μ΄ κ³ λ €λμμ΅λλ€.
- μμ²κ³Ό μλ΅μ μ½κ² μΈν°μ νΈνκ³ λ³ν / μλμΌλ‘ JSON λ°μ΄ν°λ₯Ό λ³ν λ° μλ¬ μ²λ¦¬ μ©μ΄
- λ°±μλ APIμλ λ 립μ μΌλ‘ νλ‘ νΈμλ κ°λ° μ§νμ μ€μ ν΅μ νκ²½κ³Ό μ μ¬ν λͺ¨νΉ APIλ₯Ό ν΅ν΄ κ°λ°κ³Ό ν μ€νΈλ₯Ό μννκ³ μ λμ νμ΅λλ€.
- μ μ λ°°ν¬ λκ΅¬λ‘ AWSλ₯Ό, λΉλ λ° S3 μ±ν¬λΆν° CDN νμΌ invalidate κ³Όμ μ μλννκΈ° μν΄ Github Actionsλ₯Ό μ¬μ©νμ΅λλ€. Cloudfrontλ λ¨μν S3λ§μ μ¬μ©νμ λλ³΄λ€ λ³΄μμ μΈ μΈ‘λ©΄μμ μ°μνκΈ°μ μ ννμΌλ©°, μλΈλλ©μΈ μ€μ μ μν΄ Route53μ ν¨κ» λμ νκ² λμμ΅λλ€.
- ν¬λ¨ν΄λ¦° D2hubμμ λΉλ μ νκ²½λ³μ μ€μ μ΄ λΆκ°λ₯νλ κ΄κ³λ‘, Docker hubλ‘ μ΄λ―Έμ§ λ ν¬μ§ν 리λ₯Ό κ΅μ²΄νμ΅λλ€. λν νκ²½λ³μ μ£Όμ λ° λ컀 μ΄λ―Έμ§ λΉλ, νΈμ¬ κ³Όμ μ μλννκΈ° μν΄ Github Actionμ ν¨κ» μ¬μ©νκ² λμμ΅λλ€.
-
Backend νΈλ¬λΈ μν μ¬λ‘μμ μ μ μλ―μ΄, μ΄λ°μλ Cross-site μΏ ν€μ λν μ μ½μ μ°ννκ³ μ νμν μ€μ μ μλ£νμ΅λλ€. κ·Έλ¬λ Safari λΈλΌμ°μ μ κ²½μ°, λ κ°λ ₯ν 보νΈμ μ± μ μ μ©νμ¬ cross-site μΏ ν€λ₯Ό μμ²μμ μ μΈν©λλ€. μΈμ¦ λ° μΈκ° λ°©μμΌλ‘ JWT ν ν°μ μΏ ν€μ λ΄λ μν©μμ λ°λμ ν΄κ²°λμ΄μΌ νλ μν©μ΄μμ΅λλ€.
-
mixed-contentλ₯Ό λ€λ£¨λ λ°©μ λν Safariκ° λ μ격ν΄, μΉ΄μΉ΄μ€ λ‘κ·ΈμΈ ν λΆλ¬μ€λ νλ‘ν μ΄λ―Έμ§κ° κΉ¨μ§λ νμμ΄ λ°μνμ΅λλ€.
β ν΄κ²°
- μΏ ν€μ κ²½μ°, λ°°ν¬ μλΈλλ©μΈ(CNAME)μ μ€μ ν΄μ€μΌλ‘μ¨ λ¬Έμ λ₯Ό ν΄κ²°νμ΅λλ€.
- μ΄λ―Έμ§ μμ€ urlμ κ²½μ° http β httpsλ‘ κ΅μ²΄νλ μ νΈ ν¨μλ₯Ό μ μν΄ μ μ©ν¨μΌλ‘μ¨ ν΄κ²°νμ΅λλ€.
-
μ¬μ©μμ μμΉ μ 보λ₯Ό λΆλ¬μ€κΈ° μν΄ navigator.geolocation APIλ₯Ό μ¬μ©νμ§λ§, μ€μ μμΉλ₯Ό λΆλ¬μ€κΈ°κΉμ§ κ²½μ°μ λ°λΌ μ μ΄μ μκ°μ΄ μμλλ λ¬Έμ κ° μμμ΅λλ€.
-
μ§λλ₯Ό λ λλ§νκΈ° μ κΉμ§ μ§λ νλ©΄ μ μ²΄κ° λ‘λ© μνλ‘ νμλμ΄, μ μ κ²½νμ ν΄μΉκ³ μλΉμ€κ° 맀λλ½μ§ λͺ»νλ€λ μΈμμ μ€ μ μμμ΅λλ€.
β ν΄κ²°
- κΈ°λ³Έ μ’νλ₯Ό μ§μ ν΄λκ³ , μ΄κΈ°μλ ν΄λΉ μ’νλ₯Ό μ¬μ©ν΄ μ§λλ₯Ό μ°μ λ λλ§ν©λλ€.
- μ€μ μμΉλ₯Ό λΆλ¬μ€κΈ° μ κΉμ§λ νμ¬ μμΉ λ§μ»€λ₯Ό νμμΌλ‘, μμΉκ° μ μ©λ νμλ 컬λ¬λ‘ νμνμ¬ μ§λ νλ©΄ λ΄μμ μμΉ μνμ λ³νλ₯Ό μκ°ννμ΅λλ€.
- μ μ μ λ§μ§λ§ μ μ μμΉλ₯Ό localStorageμ μ μ₯νκ³ , μ¬ μ μμ ν΄λΉ κ°μ λΆλ¬μ λ λλ§ν©λλ€.
- μ΄λ¬ν λκ΄μ UI μ λ°μ΄νΈλ‘ λΈλΌμ°μ λ΄μ₯ APIμ μ±λ₯ νκ³λ₯Ό μ΄λμ λ κ°μΆ μ μμμ΅λλ€.
-
λΈλΌμ°μ μμλ μ¬μ©μμ μλ¦Ό κΆν μ€μ νμ μ νλ‘κ·Έλλ°μ μΌλ‘ μ‘°μν μ μλλ‘ μ νν΄λκ³ μμ΅λλ€.
-
μ μ κ° μ§μ λΈλΌμ°μ μ μ€μ μ μ‘°μν΄μΌνκΈ° λλ¬Έμ, μλΉμ€ λ΄μμ μλ νμ±/λΉνμ±νμ μλΉμ€μ컀μ μ€μ μνμ λΈλΌμ°μ μλ¦Ό κΆν μνκ° λΆμΌμΉν μ μλ€λ λ¬Έμ μ μ΄ μμμ΅λλ€.
β ν΄κ²°
- UXλ‘ μ°¨μ μ±
μ ꡬννμ΅λλ€.
- μ΅μ΄ κ°μ μ βμλ¦Ό νμ©νκΈ°βλ²νΌμ΄ μΆκ°λ νμ μΌλ‘ μ¬μ©μμ μ§μ μ μΈ μλ¦Ό μ€μ μ μ λν©λλ€.
- λ§μ΄νμ΄μ§μμ μλ¦Ό μ¬λΆλ₯Ό μ‘°μ ν μ μλ ν κΈμ μΆκ°νμ΅λλ€. λν μλ¦Όμ ν΄μ ν κ²½μ° μ¬μ©μκ° λΈλΌμ°μ μ λν κΆν μ€μ μ λ°λ‘ ν΄μ€μΌνκΈ° λλ¬Έμ, μ΄λ₯Ό νμ μΌλ‘ μλ΄νλ©° UXμ μΈ νλ¦μΌλ‘ νμ΄ κ΅¬ννκ² λμμ΅λλ€.
- UXλ‘ μ°¨μ μ±
μ ꡬννμ΅λλ€.