πβμ¬μ©μ κ²½νμ λμ΄μ¬λ¦° μ§λμ¨ Ajax μ λ°μ΄νΈ 컨νΈλ‘€λ¬β
π 2025-07-02 | βοΈ λ°μ°¬ν¬ |
π§ ꡬν λͺ©ν
κΈ°μ‘΄ νμ΅ μ½ν μΈ μμ μ¬μ©μμ μ§λμ¨(progress)μ μ μ₯ν λλ§λ€ μ 체 νμ΄μ§κ° 리λ‘λλλ λ°©μμ
UX κ΄μ μμ λ무λ κ³ ν΅μ€λ¬μ λ€.
νμ΅μ΄ μλ£λ λλ§λ€ νμ΄μ§κ° λ€μ λ¨κ³ , μλ£ μ²΄ν¬κ° λλ μ΄λλ ꡬ쑰.
λλ μ΄ λ¬Έμ λ₯Ό λ¨λ²μ μμ κ³ μΆμλ€.
κ·Έλμ μ΄λ²μ μλ‘ μ€κ³ν κ²μ΄
/lecture/progress/update κ²½λ‘λ‘ μλνλ Ajax κΈ°λ° μ§λμ¨ μ λ°μ΄νΈ 컨νΈλ‘€λ¬λ€.
π μ£Όμ μλ: ν μμ²μ λ΄κΈ΄ μΌκ΄λ νλ¦
- μΈμ μΈμ¦ 체ν¬
- JSON λ°λ νμ± λ° νμ μμ μ± ν보
- μ§λμ¨ μ μ₯ (
upsert
+ μν λΉκ΅) - μλ μλ£ μ²λ¦¬
- μΌκ΄λ JSON μλ΅ κ΅¬μ‘°
μ΄ νλ¦μ λ¨μν κΈ°μ μ μΈ κ΅¬νμ λμ΄μ
βμ¬μ©μκ° νμ΅νλ λμ μμ€ν μ μ‘°μ©ν, μ ννκ² λ°μν΄μΌ νλ€βλ μ² νμ ꡬνν νλ¦μ΄λ€.
π ꡬ쑰 μμ½
κ³μΈ΅ | ν΄λμ€/νμΌ | μν |
---|---|---|
Controller | ProgressAjaxController |
Ajax μμ² νΈλ€λ§, μλ΅ ν¬λ§· μ²λ¦¬ |
Service | ProgressService |
μ§λμ¨ μ μ₯ λ° μλ£ μν μ μ΄ |
DAO/Mapper | ProgressMapper (MyBatis) |
DB Upsert, μλ£ μ¬λΆ κ²μ¬ λ± |
π ꡬν νλ¦ μμΈ
1οΈβ£ λ‘κ·ΈμΈ κ²μ¦ β 보μμ κ°μ₯ λ¨Όμ
HttpSession session = req.getSession();
UserDTO user = (UserDTO) session.getAttribute("user");
if (user == null) {
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
result.put("success", false);
result.put("message", "λ‘κ·ΈμΈμ΄ νμν©λλ€.");
...
}
- μΈμ κΈ°λ° μΈμ¦ 체ν¬
- λ‘κ·ΈμΈ μ λ μνμμμ Ajax μμ²μ 무쑰건 401 λ°ν
π μ€λ¬΄ ν: Ajax μμ²μΌμλ‘ λ³΄μ μ²λ¦¬λ λμ± μ격ν΄μΌ νλ€.
2οΈβ£ JSON λ°λ νμ± β μ§μ μ½κ³ , μ§μ νμΈνλ€
BufferedReader reader = req.getReader();
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
Map<String, Object> data = gson.fromJson(sb.toString(), Map.class);
- JSμ
number
β JavaμμDouble
λ‘ λμ΄μ€λ μ΄μλ₯Ό κ°μ .intValue()
λͺ μμ λ³ν
int contentId = ((Double) data.get("contentId")).intValue();
int progress = ((Double) data.get("progress")).intValue();
π μ€μ μμ μ€μν 건 νμ μμ μ±μ΄λ€.
νλ‘ νΈμλλ floatμ 보λ΄κ³ , λ°±μλλ intλ₯Ό λ°λλ€κ³ μ°©κ°νλ©΄β¦ 500
μ μκ³ μμ΄ λ μμ¨λ€.
3οΈβ£ μ§λμ¨ μ μ₯ β upsert + μλ£ μ²΄ν¬κΉμ§ ν λ²μ
progressService.saveOrUpdateProgress(user.getUserId(), contentId, progress);
- κΈ°μ‘΄λ³΄λ€ λμ μ§λλ§ μ μ₯ (DB λΆν λ°©μ§)
- μ½ν
μΈ μ 체 μλ£ μ μλμΌλ‘
markEnrollmentComplete
νΈμΆ
π ν΅μ¬μ 컨νΈλ‘€λ¬λ νλ¦λ§ μκ³ , λλ©μΈ μνλ μλΉμ€κ° μ± μμ§λ€.
4οΈβ£ JSON μλ΅ β μΌκ΄μ± μλ μ±κ³΅/μ€ν¨ ꡬ쑰
result.put("success", true);
result.put("message", "μ§λμ¨ μ
λ°μ΄νΈ μ±κ³΅");
resp.getWriter().write(gson.toJson(result));
- νλ‘ νΈμμ
success: true/false
λ§μΌλ‘ κ²°κ³Ό μ²λ¦¬ - μλ¬ λ°μ μ
status = 500
+"message"
ν¬ν¨
π μ΄λ° ꡬ쑰 λλΆμ νλ‘ νΈλ μ€ν¨ μΌμ΄μ€λ UIλ‘ λͺ ννκ² μ²λ¦¬ν μ μλ€.
π§ͺ ν μ€νΈ μλ리μ€
ν μ€νΈ μν© | κΈ°λ λμ |
---|---|
β λ‘κ·ΈμΈ μ¬μ©μ | 200 OK + { success: true } |
β λΉλ‘κ·ΈμΈ μν | 401 Unauthorized + "λ‘κ·ΈμΈμ΄ νμν©λλ€." |
β JSON νλΌλ―Έν° λλ½ | 500 + μ€λ₯ λ©μμ§ |
β μλ£ μ‘°κ±΄ λ§μ‘± | markEnrollmentComplete() νΈμΆλ¨ |
π§ νΈλ¬λΈμν & κ³ λ―Ό
π λ¬Έμ : JSμμ λ³΄λΈ μ«μκ° μκΎΈ Double
λ‘ λ€μ΄μ¨λ€
β ν΄κ²°: ((Double) obj).intValue()
λͺ
μ λ³ν
β μμΈ: JS number
λ floatμ΄λ©°, Gsonμ λͺ¨λ μ«μλ₯Ό Double
λ‘ μ²λ¦¬
π§ λ°°μ΄ μ
- Ajax 컨νΈλ‘€λ¬λ κ²°κ΅ λλ©μΈ νλ¦μ μ‘°μ¨νλ μ€μΌμ€νΈλΌ μ§νμλΌλ κ±Έ μ€κ°νλ€.
- μλ΅ ν¬λ§·, μΈμ¦, μμΈ νλ¦μ΄ μ 리λλ©΄ νλ‘ νΈμμ ν΅μ μ ν¨μ¬ λΆλλ¬μμ§λ€.
- μ€μκ° μ§λμ¨ μ μ₯ ꡬ쑰λ λ¨μν κΈ°λ₯ ꡬνμ΄ μλλΌ μ¬μ©μ μ λ’°κ°μ νμ±νλ ν΅μ¬ UX ν¬μΈνΈλΌλ κ².
βοΈ νκ³
βλ¨μ μ§λ μ μ₯μ΄μμ§λ§, μ΄ μ»¨νΈλ‘€λ¬λ μ¬μ©μ κ²½νκ³Ό λλ©μΈ μν μ μ΄λ₯Ό μμ ν μλνν μ νμ μ΄μλ€.β
μ΄ κ΅¬μ‘°λ μ΄ν λ€μμ μν κΈ°λ°μ΄ λλ€:
- β React κΈ°λ° μ€μκ° νμ΅ UIμ μ°λ
- β μλ μλ£ β μΈμ¦μ λ°κΈ β ν¬μΈνΈ μ§κΈκΉμ§ νμ₯ κ°λ₯
- β μ¬μ©μ ννΈλ§΅/νλ λ‘κ·Έ/μΆμ² λ‘μ§μ ν΅μ¬ λ°μ΄ν° νλ¦μ μμμ