ννΈνλ μ 보λ₯Ό νκ³³μ λͺ¨μΌκ³ , μ€μκ° νΌμ‘λ 곡μ μ κ²μ΄λ―ΈνΌμΌμ΄μ μμλ₯Ό κ²°ν©ν
νμ μ€ν μ΄ ν΅ν© νλ«νΌ ν¬λ‘±(PORONG)μ λλ€.
μ νμμ΄ νλ‘ νΈμλμ λ°±μλλ₯Ό λ΄λΉνμ¬ κΈ°λ₯μ μμ±νμ΅λλ€.
| μ΄μ£Όν | κ³ μ μ | μμ§ν |
|---|---|---|
![]() |
![]() |
![]() |
| @hana03030 | @daenggg | @jhwest-dev |
| λ©μΈ νμ΄μ§, μ°ΎκΈ° νμ΄μ§ | νμ μμΈ, νκΈ°, λ§μ΄νμ΄μ§ | λ‘κ·ΈμΈ/νμκ°μ , κ΄λ¦¬μ νμ΄μ§ |
| μ°/리뷰 CRUD, μ΅κ·Ό 리뷰 API | λκ°/μμ½ CRUD, νΌμ‘λ API | νμ/νμ CRUD, ν΅κ³ μ§κ³ API |
- Pain Point: SNSμ ν©μ΄μ§ μ 보 νμμ μ΄λ €μ, λ°©λ¬Έ μ νμ₯ νΌμ‘λ νμ λΆκ°λ₯μΌλ‘ μΈν μκ° λλΉ
- Our Solution:
- ν΅ν© μ 보 μ 곡: ν©μ΄μ§ νμ μ 보λ₯Ό νκ³³μμ μ€λ§νΈνκ² νμ λ° νν°λ§
- μ¬μ©μ μ°Έμ¬ν λ°μ΄ν°: μ μ λ€μ μ€μ νκΈ°λ₯Ό κΈ°λ°μΌλ‘ ν μ€μκ° νκ· νΌμ‘λ 곡μ
- κ²μ΄λ―ΈνΌμΌμ΄μ : 리뷰 μμ± μ κ·μ¬μ΄ ν€λ§ μμ§ μ λλ‘ μ μ νλμ± μ΄μ§
- Frontend: HTML5, CSS3, JavaScript (kakaomap API μ°λ)
- Backend: Spring Boot, MySQL
- ꡬ맀μ(User): ν(λνΉ) β‘οΈ μ°ΎκΈ°(νν°λ§) β‘οΈ νμ μμΈ(μμ½/리뷰) β‘οΈ λ§μ΄νμ΄μ§(ν€λ§ λκ°)
- νλ§€μ(Admin): νμ κ΄λ¦¬ β‘οΈ νμ λ±λ‘(μλ μ’ν λ³ν) β‘οΈ μμ½/νκΈ° νμΈ λ° ν΅κ³ λμ보λ
- λμ μ΄λ―Έμ§ λ±μ§ μμ€ν : λνΉ λ°μ΄ν° μ€νμ λ§μΆ° μ€μκ° 1, 2, 3μ μμμ κΈ/μ/λ μκ΄ μ€λ²λ μ΄λ₯Ό μ°λνκ³ NEW λ° νΌμ‘λ μ¬μ λ±μ§λ₯Ό μ‘°κ±΄λΆ λ λλ§νμ΅λλ€.
- κ°λ‘ μ€ν¬λ‘€ λ μ΄μμ: μλ§μ νμ μΉ΄λκ° λ°°μΉλλ λ©μΈ λνΉ λ° μΉμ μ μ€ν¬λ‘€ 컨ν μ΄λλ₯Ό μ€κ³νμ¬ λ§€λλ¬μ΄ λΈλΌμ°μ§ μΈν°λμ μ μ 곡ν©λλ€.
- μν μ λ ¬ μ΅μ ν: μμΈ νμ΄μ§ λ΄ νμ
μΌμ λ° μμ½ κΈ°κ° λ°μ΄ν° μ λ ¬ μ
align-items: flex-startλ°align-items: flex-endλ₯Ό ꡬ쑰μ μΌλ‘ νμ©νμ¬ λΌλ²¨κ³Ό λ΄μ©μ ν μ€νΈ μν λμ΄ νμ μ κ΅νκ² λ§μ·μ΅λλ€.
- μ€μκ° μ¬μ§ λ³κ²½/μμ μμ§: νκΈ° μμ μ κΈ°μ‘΄ μ
λ‘λ μ¬μ§ λ λλ§ κ΅¬μ‘°λ₯Ό ννΌνκ³ ,
URL.createObjectURLκΈ°λ° λ‘컬 κ°μ μ£Όμ λ체 λ°©μκ³Ό μμ (null) λΌμ΄νμ¬μ΄ν΄μ μ°κ²°νμ΅λλ€. - μΈν°λν°λΈ νΌ λ°μΈλ©: λ§μ°μ€ ν΄λ¦μ μ°λλλ 5λ¨κ³ λ³μ νμ±ν κΈ°λ₯κ³Ό 3λ¨κ³ μ¬λ μμ΄μ½μΌλ‘ ꡬμ±λ νμ₯ νΌμ‘λ μ νμ ꡬννμ΅λλ€.
- μ‘°κ±΄λΆ μ΄λ―Έμ§ μ€μμΉ κΈ°λ²: ν€λ§ λκ° μμ€ν λ΄μμ μ¬μ©μμ λ―Ένλ μμ΄ν λͺ©λ‘μ νμΌλͺ κ·μΉ κΈ°λ°μ μ κΈ κ·Έλ¦Όμ μ λμ¬λ₯Ό μ‘°ν©νμ¬ κ°κ²°ν μ½λλ‘ μν λΆκΈ°λ₯Ό μλννμ΅λλ€.
-
λ¬Έμ μν©
리뷰 μμ μ λ°±μλ 컨νΈλ‘€λ¬κ°@PatchMappingλ°consumes = MediaType.MULTIPART_FORM_DATA_VALUEλ‘ μ μΈλμ΄ μμμΌλ, νλ‘ νΈμλμμ μΌλ° JSON λ¬Έμμ΄ ν¬λ§·μΌλ‘ μ‘μ νμ¬415 (Unsupported Media Type)λ°405ν΅μ μ₯μ κ° λ°μνμ΅λλ€. -
ν΄κ²° λ°©μ
κΈ°μ‘΄JSON.stringifyμ μ‘ κ΅¬μ‘°λ₯Ό μ λ©΄ νκΈ°νκ³ λΈλΌμ°μ λ΄μ₯ κ°μ²΄μΈFormDataλΉλ ꡬ쑰λ₯Ό μ μ©νμ΅λλ€. λ°μ΄ν°λ₯Ό κ°λ³ 쿼리 νμ λ§μΆ° μ΄νλνκ³ , νμΌ κ°μ²΄(MultipartFileλ§€νμ©)λ₯Ό λ¨λ λΆλ¦¬ νμ¬νμ΅λλ€. νΉν ν€λμContent-Typeμ μλμ μΌλ‘ λͺ μνμ§ μκ³ λΉμλ μΌλ‘μ¨ λΈλΌμ°μ κ° λ©ν°ννΈ κ²½κ³μ (boundary)μ μλμΌλ‘ μΈμ½λ© μ§μ νλλ‘ μ λνμ¬ ν΅μ κ·κ²©μ μλ²½νκ² λκΈ°ννμ΅λλ€.
-
λ¬Έμ μν©
μ΄κΈ° μ€κ³ λΉμ μμ νμ΄μ§ μ§μ μ ν΄λΉ νκΈ°μ λ°μ΄ν°λ₯Ό μλ²μμ ν μ€λ§ κΈμ΄μ€λ λ¨κ±΄ μ‘°ν(GET) APIμ λΆμ¬λ‘ μΈν΄ κΈ°μ‘΄ μμ± μ 보(Pre-fill)λ₯Ό νλ©΄μ λ‘λνμ§ λͺ»νλ λ³λͺ© νμμ΄ μΌμ΄λ¬μ΅λλ€. -
ν΄κ²° λ°©μ
λ°±μλ 리μμ€λ₯Ό 무리νκ² μμ νλ λμ νλ‘ νΈμλ λ¨μμ λ§μ΄νμ΄μ§ μ 체 λͺ©λ‘ μ‘°ν API(api/reviews/me)λ₯Ό μ°ν νΈμΆνλ λ°©μ΄λ²½ μ½λλ₯Ό μ¬μμ΅λλ€. μ 체 리μ€νΈ λ°°μ΄μ λ©λͺ¨λ¦¬μ μ¬λ¦° λ€, μ£Όμμ°½μ 쿼리μ€νΈλ§ νλΌλ―Έν°(?reviewId=XX) κ³ μ μλ³μμ μλ²½νκ² μΌμΉνλ κ°μ²΄ μμλ₯Ό JavaScriptμ.find()λ¬Έλ²μΌλ‘ μ€μκ° λ§€μΉΒ·μ μΆνμ¬ λ°±μλ μΆκ° 곡μ μμ΄ νλ©΄ νΌμ μ±κ³΅μ μΌλ‘ 볡ꡬνμ΅λλ€.
Po-Rong-Frontend/
βββ assets/
β βββ css/
β β βββ global.css # κ³΅ν΅ ν
λ§ λ³μ λ° μ΄κΈ°ν μ€νμΌ
β β βββ main.css # ν λ©μΈ μ»΄ν¬λνΈ λ° λ±μ§ μ€νμΌ
β β βββ popup-detail.css # μ λ ¬ κ΅¬μ‘°κ° κ°μ λ μμΈ νμ΄μ§ μ€νμΌ
β β βββ review.css # νκΈ° λ±λ‘/μμ μ μ© νΌ μ€νμΌ
β βββ images/
β βββ badges/ # κΈ/μ/λ μκ΄ λ° ν
λ§λ³ μν λ±μ§
β βββ icons/ # ννΈ, λ³μ μ±μ°κΈ°, νΌμ‘λ μΈν μμ΄μ½
β βββ keyrings/ # νλ ν€λ§ λ° λ―Ένλ shadow- μ΄λ―Έμ§ μμ
βββ js/
β βββ index.js # κΈλ‘λ² κ°μ΄λ μ μ΄ μ€ν¬λ¦½νΈ
β βββ main.js # ν λνΉ μ€ν¬λ‘€ λ° λ°°λ μ μ΄ μμ§
β βββ popup-detail.js # μμΈ λ°μ΄ν° λ³λ ¬ μ²λ¦¬ λ° μμ½ μ 보 λ§€ν
β βββ review-edit.js # νκΈ° μμ νΌ λ°μ΄ν° λ°μΈλ© λ° νμΌ μ»¨νΈλ‘€λ¬
βββ pages/
βββ explore.html # νμ
ν΅ν© κ²μ λ° νν°λ§ νμ΄μ§
βββ popup-detail.html # νμ
μ 보 λ° νλ¨ κ³ μ λ° μμΈ νμ΄μ§
βββ review-edit.html # νκΈ° μ€μκ° μμ νΌ νμ΄μ§








