๐งฉ 1. HTML <form> ์ ์ก ๋ฐฉ์
๐น ๊ฐ์
- ๋ธ๋ผ์ฐ์ ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ํผ ์ ์ก ๊ธฐ๋ฅ ์ฌ์ฉ
- <form> ํ๊ทธ์ action๊ณผ method ์์ฑ์ ์ด์ฉํด ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ก
- ์ ์ก ํ์์ ๊ธฐ๋ณธ์ ์ผ๋ก application/x-www-form-urlencoded ๋๋ multipart/form-data (ํ์ผ ์ ๋ก๋ ์)
๐น ์์ ์ฝ๋
<form action="/signup" method="POST">
<label>์์ด๋: <input type="text" name="username" /></label><br>
<label>๋น๋ฐ๋ฒํธ: <input type="password" name="password" /></label><br>
<button type="submit">ํ์๊ฐ์
</button>
</form>
๐น ์๋ฒ (Spring Boot Controller)
@ReauireArgsConstructor
@Controller
public class UserController {
private final UserService userservice;
@PostMapping("/user")
public String signup(AddUserRequest request){
userservice.save(request);
return "redirect:/login";
}
}
๐น ์ ์ก๋๋ ๋ฐ์ดํฐ (์์ฒญ ์์)
POST /signup HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=kim123&password=1234
๐น ์ฅ์
โ
๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ๊ธฐ๋ฅ → ๊ตฌํ ๊ฐ๋จ
โ
์๋ฐ์คํฌ๋ฆฝํธ ์์ด๋ ๋์ (์ ๊ทผ์ฑ ๋์)
โ
์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR) ๊ตฌ์กฐ์ ์ ํฉ
๐น ๋จ์
โ ํ์ด์ง ์ ์ฒด ์๋ก๊ณ ์นจ ๋ฐ์
โ JSON ํํ ์๋ → API ์๋ฒ์ ๋ณด๋ด๊ธฐ์ ๋ถํธ
โ ์ ํจ์ฑ ๊ฒ์ฌ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ด๋ ต๋ค (JS ํ์)
๐งฉ 2. JavaScript(JSON ์ ์ก) ๋ฐฉ์ (์: fetch())
๐น ๊ฐ์
- JS๋ก ์ง์ HTTP ์์ฒญ์ ๋ง๋ค์ด ์๋ฒ์ ๋ณด๋ (๋ณดํต fetch๋ axios ์ฌ์ฉ)
- ์ ์ก ํ์: application/json
- SPA(React, Vue ๋ฑ)๋ REST API ์๋ฒ ํต์ ์ ๋ง์ด ์ฌ์ฉ
๐น ์์ ์ฝ๋
<form id="signupForm">
<label>์์ด๋: <input type="text" id="username" /></label><br>
<label>๋น๋ฐ๋ฒํธ: <input type="password" id="password" /></label><br>
<button type="submit">ํ์๊ฐ์
</button>
</form>
<script>
document.getElementById("signupForm").addEventListener("submit", async (e) => {
e.preventDefault(); // ํผ ๊ธฐ๋ณธ ์ ์ก ๋ง๊ธฐ
const data = {
username: document.getElementById("username").value,
password: document.getElementById("password").value
};
try {
const response = await fetch("/signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
// HTTP ์๋ฌ ์ํ ์ฝ๋ ์ฒ๋ฆฌ (ex. 400, 500)
if (!response.ok) {
throw new Error("์๋ฒ ์๋ต ์ค๋ฅ (" + response.status + ")");
}
const result = await response.json();
alert(result.message);
window.location.href = "/login"; // ์ฑ๊ณต ์ ๋ก๊ทธ์ธ ํ์ด์ง ์ด๋
} catch (error) {
console.error("ํ์๊ฐ์
์ค ์ค๋ฅ ๋ฐ์:", error);
alert("ํ์๊ฐ์
์ ์คํจํ์ต๋๋ค. ์ ์ ํ ๋ค์ ์๋ํด์ฃผ์ธ์.");
}
});
</script>
๐น ์๋ฒ (Spring Boot Controller)
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RequiredArgsConstructor
@RestController
public class UserController {
private final UserService userService;
@PostMapping("/signup")
public Map<String, String> signup(@RequestBody AddUserRequest request) {
try {
// ํ์๊ฐ์
๋ก์ง ์ํ
userService.save(request);
// ์ฑ๊ณต ์๋ต JSON
return Map.of("message", request.getUsername() + "๋ ํ์๊ฐ์
์ฑ๊ณต!");
} catch (Exception e) {
// ์๋ฒ์์ ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ
return Map.of("message", "ํ์๊ฐ์
์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.");
}
}
}
๐น ์ ์ก๋๋ ๋ฐ์ดํฐ (์์ฒญ ์์)
POST /signup HTTP/1.1
Content-Type: application/json
{"username": "kim123", "password": "1234"}
๐น ์ฅ์
โ
ํ์ด์ง ์๋ก๊ณ ์นจ ์์ด ๋น๋๊ธฐ ์์ฒญ ๊ฐ๋ฅ (UX ํฅ์)
โ
JSON์ผ๋ก ์ง์ ํต์ → API ์๋ฒ ์ฐ๋ ํธ๋ฆฌ
โ
ํด๋ผ์ด์ธํธ ๋จ ์ ํจ์ฑ ๊ฒ์ฌ, ๋์ UI์ ์ฝ๊ฒ ํตํฉ
๐น ๋จ์
โ JS ๋นํ์ฑํ ์ ๋์ ์ ํจ
โ ์ฝ๋ ๊ตฌํ์ด ๋ ๋ณต์ก
โ CORS ๋ฑ ๋ณด์ ์ค์ ํ์
โ๏ธ ๋น๊ต ์ ๋ฆฌํ
| ๊ตฌ๋ถ | HTML Form ์ ์ก | JS(JSON) ์ ์ก |
| ์์ฒญ ํ์ | application/x-www-form-urlencoded | application/json |
| ์ปจํธ๋กค๋ฌ ์ด๋ ธํ ์ด์ | @Controller | @RestController |
| ์์ฒญ ๋ฐ์ดํฐ ์ฒ๋ฆฌ | @RequestParam ํน์ dto์ผ๋ @RequestParam ์ฌ์ฉ์์ด ์๋ ๋ฐ์ธ๋ฉ |
@RequestBody |
| ์๋ต ํ์ | HTML View (Thymeleaf ๋ฑ) | JSON (API ์๋ต) |
| ์ฌ์ฉ ๋ชฉ์ | ์ ํต์ SSR ์น์ฌ์ดํธ | SPA, ํ๋ก ํธ-๋ฐฑ์๋ ๋ถ๋ฆฌํ ๊ตฌ์กฐ |
| ์ฅ์ | ๊ฐ๋จ, JS ์์ด ๋์ | ๋น๋๊ธฐ, UX ์ข์, API ์นํ์ |