Snackμ κΈ°μ λ΄λΉμκ° μ¬λ΄ κ°μ λ° μλ£λ₯Ό κ΄λ¦¬νκ³ μ£Όλ¬Έν μ μλ λ§μΌνλ μ΄μ€ νλ«νΌμ λλ€!
μ΅κ³ κ΄λ¦¬μλ μ΄λ©μΌ μ΄λλ‘ μ§μλ€μ νλ«νΌμ κ°μ μν€κ³ , μ μ κΆνμ μΌλ°Β·κ΄λ¦¬μλ‘ λ³κ²½νκ±°λ μ μ μ κ³μ μ μμ ν μ μμ΅λλ€. μλ³ μμ°μ μ€μ ν΄ νμ¬μ κ°μ μ§μΆμ κ΄λ¦¬νλ©°, μμ°μ λ§€μ μλμΌλ‘ μ΄κΈ°νλ©λλ€.
μ§μλ€μ μνλ μνμ μ§μ λ±λ‘ν μ μμΌλ©°, μ₯λ°κ΅¬λμ λ΄μ ꡬ맀λ₯Ό μμ²ν©λλ€. κ΄λ¦¬μλ μ΄λ₯Ό μΉμΈνκ±°λ λ°λ €ν©λλ€. κ΄λ¦¬μλ μ¦μ κ΅¬λ§€κ° κ°λ₯νλ©°, μ₯λ°κ΅¬λμμ μμ¬ μμ°μ μ€μκ°μΌλ‘ νμΈν μ μμ΅λλ€. μΉμΈλ μ£Όλ¬Έμ ꡬ맀 λ΄μμ κΈ°λ‘λμ΄ κ΄λ¦¬μκ° μ 체 λ΄μμ μ‘°νν μ μμ΅λλ€.
| μλΉμ€ | URL |
|---|---|
| π λ°°ν¬ μ¬μ΄νΈ | https://marin-snack.store/ |
| π API λ¬Έμ | http://13.209.35.172/api-docs/ |
| π₯οΈ FE μ μ₯μ | github.com/oh1marin/fs9team3-snack-fe |
| βοΈ BE μ μ₯μ | github.com/oh1marin/fs9team3-snack-be |
| ν | λ‘κ·ΈμΈ | μν λͺ©λ‘ |
|---|---|---|
![]() |
![]() |
![]() |
| μν μμΈ | μν λ±λ‘ λͺ¨λ¬ | μ₯λ°κ΅¬λ |
|---|---|---|
![]() |
![]() |
![]() |
| μ£Όλ¬Έ λ΄μ | κ΄λ¦¬μ | κ΄λ¦¬μ μΉμΈ/λ°λ € |
|---|---|---|
![]() |
![]() |
![]() |
http://13.209.35.172/api-docs/
κ°μΈ νλ‘μ νΈλ‘, κΈ°νλΆν° λ°°ν¬κΉμ§ λ¨λ μΌλ‘ μ§ννμ΅λλ€.
| λΆμΌ | λ΄μ© |
|---|---|
| Frontend | μ νμ΄μ§ UI ꡬν, μν κ΄λ¦¬, μΈμ¦ νλ¦, μ±λ₯ μ΅μ ν |
| Backend | REST API μ€κ³ λ° κ΅¬ν, JWT μΈμ¦Β·κΆν λ―Έλ€μ¨μ΄, μ΄λ©μΌ λ°μ‘ |
| Database | Prisma μ€ν€λ§ μ€κ³, PostgreSQL λ§μ΄κ·Έλ μ΄μ Β·μλ |
| Infra | AWS EC2 λ°°ν¬, S3 μ΄λ―Έμ§ μ λ‘λ, Vercel, Cloudflare λλ©μΈ μ°κ²° |
- μ΄λ©μΌ κΈ°λ° νμκ°μ / λ‘κ·ΈμΈ / λ‘κ·Έμμ
- JWT ν ν° κΈ°λ° μΈμ¦ (μΏ ν€)
- μ΅κ³ κ΄λ¦¬μ μ΄λ λ©μΌ λ°μ‘
- μν λͺ©λ‘ (μΉ΄ν κ³ λ¦¬ νν°, μ λ ¬: μ΅μ μ / νλ§€μ / κ°κ²©μ)
- μν λ±λ‘ Β· μμ Β· μμ
- AWS S3 μ΄λ―Έμ§ μ λ‘λ
- λμ ꡬ맀 νμ λ°°μ§
- μ₯λ°κ΅¬λ λ΄κΈ° Β· μλ λ³κ²½ Β· μμ
- ꡬ맀 μμ² (μΌλ°) / μ¦μ ꡬ맀 (κ΄λ¦¬μ)
- μ£Όλ¬Έ λͺ©λ‘ Β· μμΈ μ‘°ν Β· μ·¨μ
- νμ κ΄λ¦¬: μ΄λ, κΆν λ³κ²½ (μΌλ° / κ΄λ¦¬μ / μ΅κ³ κ΄λ¦¬μ)
- μμ° κ΄λ¦¬: μλ³ μμ° μ€μ (node-cron μλ μ΄κΈ°ν)
- μΉμΈ λκΈ°: ꡬ맀 μμ² μΉμΈ Β· λ°λ €
- μν κ΄λ¦¬: λ±λ‘ μν λͺ©λ‘ Β· μμ
- ꡬ맀 λ΄μ: μΉμΈ μλ£ μ£Όλ¬Έ μ‘°ν
π₯οΈ fs9team3-snack-fe/ # νλ‘ νΈμλ
βββ π src/
β βββ π app/
β β βββ π (auth)/ # λ‘κ·ΈμΈ, νμκ°μ
β β βββ π (protected)/ # μΈμ¦ νμ νμ΄μ§
β β β βββ π¦ items/ # μν λͺ©λ‘Β·μμΈ
β β β β βββ register/ # μν λ±λ‘
β β β βββ π cart/ # μ₯λ°κ΅¬λ
β β β β βββ complete/ # ꡬ맀 μλ£
β β β βββ π orders/ # μ£Όλ¬Έ λͺ©λ‘Β·μμΈ
β β β βββ π€ profile/ # νλ‘ν
β β β βββ βοΈ admin/ # κ΄λ¦¬μ
β β β βββ items/ # μν κ΄λ¦¬
β β β βββ orders/ # μΉμΈ λκΈ°
β β β βββ purchase-history/ # ꡬ맀 λ΄μ
β β β βββ users/ # νμ κ΄λ¦¬
β β βββ π page.tsx # λλ©
β β βββ ui/ # AddProductBtn, SortButton λ±
β βββ π§© components/ # κ³΅ν΅ μ»΄ν¬λνΈ
β β βββ icons/
β βββ π contexts/ # AuthContext, CartContext, ModalContext
β βββ π§ lib/
β β βββ api/ # apiClient, auth, cart, items, orders, superAdmin
β β βββ actions/ # Server Actions
β β βββ service/ # authService, userService
β β βββ utils/ # image, purchaseBadge
β βββ layout/ # NavBar
βοΈ fs9team3-snack-be/ # λ°±μλ
βββ π src/
β βββ π app.ts # Express μ± μ§μ
μ
β βββ π£οΈ routes/ # auth, items, cart, orders, users, admin, super-admin
β βββ π controllers/ # κ° λλ©μΈ λΉμ¦λμ€ λ‘μ§
β βββ π‘οΈ middleware/ # JWT μΈμ¦, κΆν 체ν¬, μλ¬ νΈλ€λ¬
β βββ ποΈ prisma/ # schema.prisma, migrations, seed
β βββ β° cron/ # μλ³ μμ° μ΄κΈ°ν μ€μΌμ€λ¬
β βββ π§ config/ # Swagger, S3 μ
λ‘λ μ€μ
β βββ π types/ # κ³΅ν΅ νμ
μ μ
β βββ π¨ utils/ # μλ¬ ν΄λμ€, μ΄λ©μΌ, μ΄λ―Έμ§ URL, Prisma μ±κΈν€
π νΈλ¬λΈμν
λ‘κ·ΈμΈ μνμμλ μλ‘κ³ μΉ¨νλ©΄ λΉλ‘κ·ΈμΈ ν€λκ° κΉλΉ‘μ΄κ±°λ, ν ν°μ΄ μλλ°λ λΉλ‘κ·ΈμΈμΌλ‘ νμλλ νμμ΄ λ³΅ν©μ μΌλ‘ λ°μνλ€.
μμΈμ μΈ κ°μ§μλ€.
getMe()νΈμΆ μ€setUser()μsetIsLoading(false)κ° μλ‘ λ€λ₯Έ νμ΄λ°μ λ°μλμ΄,user === nullμ΄λ©΄μisLoading === falseμΈ νλ μμ΄ ν μκ° λ λλ§λ¨- ν€λκ°
userκ°λ§μΌλ‘ λ‘κ·ΈμΈ μ¬λΆλ₯Ό νλ¨ν΄,/api/auth/meνμ± μ€ν¨ μ ν ν°μ΄ μμ΄λ λΉλ‘κ·ΈμΈμΌλ‘ μΈμ - νλ‘ νΈΒ·API ν¬νΈκ° λ¬λΌ
Access-Control-Allow-Originμ΄ λͺ ννμ§ μμ λΈλΌμ°μ κ° μΏ ν€λ₯Ό μ μ‘νμ§ μμ
ν΄κ²°
setUser()μ λ‘λ© μν λ³κ²½μ κ°μ νλ¦μμ μ²λ¦¬νκ³ ,finallyμμ 무쑰건setIsLoading(false)λ₯Ό νΈμΆνλ ꡬ쑰λ₯Ό μ κ±°- μλ²μμ ν ν° κ²μ¦ κ²°κ³Όλ₯Ό
hasTokenμΌλ‘ ν€λμ μ λ¬ν΄ λ‘κ·ΈμΈ νλ¨ κΈ°μ€ μΆκ°,AuthInitializerλ‘ userλ₯Ό contextμ 미리 μ£Όμ - λ°±μλ CORS
originμ λͺ νν μ§μ νκ³credentials: trueμ μ§
items/page.tsx, items/[id]/page.tsxμμ ProductModal, DeleteModal, AddToCartModalμ μλ¨ importλ‘ λΆλ¬μ€κ³ μμλ€. λͺ¨λ¬μ λ²νΌμ λλ¬μΌλ§ μ΄λ¦¬λ μ»΄ν¬λνΈμΈλ°, νμ΄μ§ μ§μ
μμ λΆν° λ²λ€μ ν¬ν¨λμ΄ μ΄κΈ° λ‘λ©μ μν₯μ μ£Όκ³ μμλ€.
ν΄κ²° λͺ¨λ¬μ μ¬λ μμ μ await import()λ‘ λμ λ‘λνλλ‘ λ³κ²½νλ€.
const { default: ProductModal } = await import("@/components/ProductModal");
const { default: DeleteModal } = await import("@/components/DeleteModal");
const { default: AddToCartModal } = await import("@/components/AddToCartModal");μ΄κΈ° λ²λ€ ν¬κΈ°κ° μ€μκ³ , λͺ¨λ¬μ²λΌ 쑰건λΆλ‘λ§ νμν μ»΄ν¬λνΈλ dynamic importκ° μ ν©νλ€λ κ²μ νμΈνλ€.








