
HTTP ์์ฒญ์ ๋ง๋ค๊ณ ์๋ต์ ์ฒ๋ฆฌํ๋ JavaScript ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค. ์ฃผ๋ก ์น ์ ํ๋ฆฌ์ผ์ด์
์์ ์๋ฒ์์ ํต์ ์ ๋ด๋นํฉ๋๋ค. ๋ํ, Axios๋ฅผ ์ฌ์ฉํ๋ฉด HTTP GET, POST, PUT, DELETE ๋ฑ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ์ ์์ฒญ์ ๋ณด๋ผ ์ ์์ต๋๋ค. ๋ํ ์์ฒญ ํค๋๋ ์์ฒญ ๋ณธ๋ฌธ์ ์ค์ ํ๊ณ ์๋ต ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. axios ์ฌ์ฉํ๋ ์ด์ ๋ ์์ฒญ์ ์ฃผ๊ณ ๋ฐ๊ธฐ ํ๊ธฐ ์ํด์ ์ฌ์ฉํฉ๋๋ค.
get ์์ฒญ(axios.get("๊ฒฝ๋ก"))
import React from "react";
import axios from "axios";
function App(props) {
function handleClick1() {
axios.get("/path1");
}
function handleClick2() {
const qs = new URLSearchParams();
qs.append("city", "๋ฏธ๊ตญ");
qs.append("address", "๋ด์");
axios.get("/path2?" + qs.toString());
}
function handleClick3() {
const qs = new URLSearchParams();
qs.append("name", "kim");
qs.append("age", 24);
axios.get(`/path3?${qs.toString()}`);
}
return (
<div>
<div>
<button onClick={handleClick1}>/path1 get ์์ฒญ</button>
</div>
<div>
<button onClick={handleClick2}>/path2 get ์์ฒญ</button>
</div>
<div>
<button onClick={handleClick3}>/path3 get ์์ฒญ</button>
</div>
</div>
);
}
export default App;
handleClick1() : '/path1'๋ก GET ์์ฒญ์ ๋ณด๋
๋๋ค.handleClick2() : '/path2'๋ก GET ์์ฒญ์ ๋ณด๋
๋๋ค. URLSearchParams๋ฅผ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ๊ณ ์ด๋ฅผ ๊ฒฝ๋ก์ ๋ถ์ฌ์ ์์ฒญ์ ๋ณด๋
๋๋ค. /path2?city=๋ฏธ๊ตญ&address=๋ด์handleClick3() : '/path3'๋ก GET ์์ฒญ์ ๋ณด๋
๋๋ค. URLSearchParams๋ฅผ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ๊ณ ์ด๋ฅผ ๊ฒฝ๋ก์ ๋ถ์ฌ์ ์์ฒญ์ ๋ณด๋
๋๋ค. /path3?name=kim&age=24๋จผ์ React์ Spring Boot์ ์ฐ๊ฒฐํ๊ธฐ ์ํด์ ์ค์ ์ ํด์ค๋๋ค.
Vite ์ค์ ํ์ผ (vite.config.js)
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/api": {
target: "http://localhost:8080",
},
},
},
});
api๋ก ์์ํ๋ ์์ฒญ์ "http://localhost:8080 (Spring Boot ํฌํธ๋ฒํธ)"์ผ๋ก ๋ณด๋ด๋ ํ๋ก์ํ๋๋ก ์ค์ ์ ํฉ๋๋ค.ํ๋ก์ : ํด๋ผ์ด์ธํธ์ ์๋ฒ ์ฌ์ด์์ ์ค๊ณํ๋ ์ญํ ์ ํฉ๋๋ค. React(App.jsx)
import React from "react";
import axios from "axios";
function App(props) {
function handleClickButton1() {
// ajax get ์์ฒญ
axios.get("/api/someurl");
}
function handleClickButton2() {
axios.post("/api/someurl");
}
return (
<div>
<button onClick={handleClickButton1}>get ์์ฒญ</button>
<button onClick={handleClickButton2}>post ์์ฒญ</button>
</div>
);
}
export default App;
get ์์ฒญ ๋ฒํผ ํด๋ฆญ ์, handleClickButton1 ํธ๋ค๋ฌ ๋ฉ์๋๊ฐ ์คํ๋๊ณ /api/someurl ๊ฒฝ๋ก๋ก get ์์ฒญ์ ๋ณด๋
๋๋ค.post ์์ฒญ ๋ฒํผ ํด๋ฆญ ์, handleClickButton2 ํธ๋ค๋ฌ ๋ฉ์๋๊ฐ ์คํ๋๊ณ /api/someurl ๊ฒฝ๋ก๋ก post ์์ฒญ์ ๋ณด๋
๋๋ค.Spring Boot(Controller40.java)
@Controller
public class Controller40 {
@GetMapping("/api/someurl")
public void method1(){
System.out.println("Controller40.method1");
}
@PostMapping("/api/someurl")
public void method2(){
System.out.println("Controller40.method2");
}
}
/api/someurl ๊ฒฝ๋ก๋ก get ์์ฒญ์ ๋ณด๋ด๋ฉด @GetMapping์ผ๋ก ์ง์ ๋ ๋ฉ์๋(method1)๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ์ฌ Controller40.method1์ด ์ถ๋ ฅ๋ฉ๋๋ค./api/someurl ๊ฒฝ๋ก๋ก post ์์ฒญ์ ๋ณด๋ด๋ฉด @PostMapping์ผ๋ก ์ง์ ๋ ๋ฉ์๋(method2)๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ์ฌ Controller40.method2๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.React(App.jsx)
import React from "react";
import axios from "axios";
function App(props) {
function handleClickButton5() {
const params = new URLSearchParams();
params.append("id", 3);
params.append("name", "son");
params.append("email", "son@gmail.com");
// axios.get("/api/someurl3?"+params);
axios.get(`/api/someurl3?${params}`);
}
function handleClickButton6() {
const params = new URLSearchParams();
params.append("foods", "pizza");
params.append("foods", "coffee");
params.append("city", "busan");
axios.post("/api/someurl3", params);
}
return (
<div>
<button onClick={handleClickButton5}>get ์์ฒญ with query string</button>
<button onClick={handleClickButton6}>post ์์ฒญ with data</button>
</div>
);
}
export default App;
handleClickButton5() : GET ์์ฒญ์ ๋ณด๋ด๊ณ ์ฟผ๋ฆฌ ์คํธ๋ง์ ์์ฑํ์ฌ axios.get()์ ํตํด /api/someurl3 ๊ฒฝ๋ก์ ํด๋น ์ฟผ๋ฆฌ ์คํธ๋ง์ ํฌํจํ์ฌ GET ์์ฒญ์ ๋ณด๋
๋๋ค. handleClickButton6() : axios.post()์ ํตํด /api/someurl3 ๊ฒฝ๋ก๋ก POST ์์ฒญ์ ๋ณด๋ผ ๋ ์์ฒญ ๋ณธ๋ฌธ์ ๋ฐ์ดํฐ(foods[], city)๋ฅผ ๋ด์์ ์ถ๊ฐํ ํ์ POST ์์ฒญ์ ๋ณด๋
๋๋ค. Spring Boot(Controller40.java)
@GetMapping("/api/someurl3")
public void method5(@RequestParam("id") Integer id,
@RequestParam("name") String name,
@RequestParam("email") String email){
System.out.println("id = " + id + ", name = " + name + ", email = " + email);
}
@PostMapping("/api/someurl3")
public void method6(String[] foods, String city){
System.out.println("foods = " + Arrays.toString(foods) + ", city = " + city);
}
GET ๋ฐฉ์์ ์์ฒญ์ ๋ณด๋ผ ๋ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ URL์ ํฌํจ์์ผ ์ ๋ฌํ๋ฉฐ, POST ๋ฐฉ์์ ์์ฒญ์ ๋ณด๋ผ ๋ ๋ณ๋์ ๋ชธํต(body)์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์ ๋ฌํฉ๋๋ค.@RequestParam์ ์์ฒญ ํ๋ผ๋ฏธํฐ์ ๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ด ๋์ผํ๋ฉด @RequestParam ์๋ต ๊ฐ๋ฅํฉ๋๋ค.React์์ Spring Boot ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ด๊ณ ์์ฒญ์ ์ฒ๋ฆฌํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ๊ณผ์ ์ ๋ณด์ฌ์ค๋๋ค.
React ์ ํ๋ฆฌ์ผ์ด์ (App.js)
import React, { useState } from "react";
import axios from "axios";
function App(props) {
const [customerId, setCustomerId] = useState("");
const [customerName, setCustomerName] = useState("");
function handleSearchClick() {
// ์กฐํ๋ฒํผ ํด๋ฆญ ์ /api/customer?id=#๋ก ์์ฒญ
axios
.get(`/api/customer?id=${customerId}`)
.then((response) => response.data)
.then((data) => setCustomerName(data));
}
return (
<div>
<div>
<input type="number" onChange={(e) => setCustomerId(e.target.value)} />
</div>
<button onClick={handleSearchClick}>์กฐํ</button>
<div>์ด๋ฆ : {customerName}</div>
</div>
);
}
export default App;
Controller39.java
@Controller
@RequiredArgsConstructor
public class Controller39 {
private final Service05 service;
// /api/customer?id=#
@GetMapping("/api/customer")
@ResponseBody
public String customerName(Integer id) {
return service.getCustomerName(id);
}
}
/api/customer ๊ฒฝ๋ก๋ก GET ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์์ฒญ๋ ๊ณ ๊ฐ ID๋ฅผ ์๋น์ค์ ์ ๋ฌํ์ฌ ๊ณ ๊ฐ์ ์ด๋ฆ์ ๊ฐ์ ธ์ต๋๋ค.Service05.java
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
public class Service05 {
private final Mapper09 mapper;
public String getCustomerName(Integer id) {
return mapper.selectNameById(id);
}
}
Mapper09.java
@Mapper
public interface Mapper09 {
@Select("""
SELECT CustomerName
FROM Customers
WHERE CustomerId = #{id}
""")
String selectNameById(Integer id);
}