๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
SpringBoot

[SpringBoot] HTML form ์ „์†ก vs JavaScript๋กœ JSON ์ „์†ก

by ๊ฐœ๋ฐœLOG 2025. 11. 2.
๋ฐ˜์‘ํ˜•

๐Ÿงฉ 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 ์นœํ™”์ 

 

๋ฐ˜์‘ํ˜•