๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ๏ธ ํ”„๋ก ํŠธ์—”๋“œ/JavaScript

[Axios] Axios๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ

by OR15A 2023. 12. 15.
Axios๋ž€?
  • Axios๋Š” JavaScript๋กœ ์ž‘์„ฑ๋œ ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ HTTP ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ์ฃผ๋กœ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ API ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•จ
  • ๋ธŒ๋ผ์šฐ์ €์™€ Node.js ํ™˜๊ฒฝ์—์„œ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, HTTP ์š”์ฒญ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์คŒ
  • ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•
    • Axios๋Š” GET, POST, PUT, DELETE ๋“ฑ ๋‹ค์–‘ํ•œ HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•จ
// PUT ์š”์ฒญ
axios.put('/api/users/1', {
  	username: 'updateduser',
  	password: 'newpassword'
	})
  	.then(response => {
    	console.log(response.data); // ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ์˜ ์‘๋‹ต
  	})
  	.catch(error => {
    console.error(error);
  	});
  • Promise ๊ธฐ๋ฐ˜
    • Axios๋Š” Promise ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™
    • ๋น„๋™๊ธฐ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ .then()๊ณผ .catch()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๊ณต์ ์ธ ์‘๋‹ต๊ณผ ์—๋Ÿฌ๋ฅผ ์‰ฝ๊ฒŒ ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ์Œ + finally
axios.get('url')
      .then(response => {
        // ์„ฑ๊ณต์ ์ธ ์‘๋‹ต ์ฒ˜๋ฆฌ
      })
      .catch(error => {
        // ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ
      });
  • ์š”์ฒญ๊ณผ ์‘๋‹ต ์ธํ„ฐ์…‰ํŠธ
    • ์š”์ฒญ ์ „์— ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„๊ฑฐ๋‚˜, ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ์˜ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑ„์–ด ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Œ
    • ex) ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ํ—ค๋”์— ํ† ํฐ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ์‘๋‹ต์„ ๋ฐ›์€ ํ›„ ํŠน์ • ํฌ๋งท์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…
axios.interceptors.request.use(request => {
      console.log('Starting Request', request);
      return request;
});

axios.interceptors.response.use(response => {
      console.log('Response:', response);
      return response;
});
  • ์š”์ฒญ ์ทจ์†Œ
    • ์ง„ํ–‰ ์ค‘์ธ ์š”์ฒญ์„ ์ทจ์†Œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณต
    • ex) ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ํด๋ฆญํ•˜์—ฌ ์ค‘๋ณต ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ์œ ์šฉํ•จ
const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
      cancelToken: new CancelToken(function executor(c) {
       	 cancel = c;
      })
});

// ๋‚˜์ค‘์— ์š”์ฒญ์„ ์ทจ์†Œํ•˜๋ ค๋ฉด cancel ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
cancel();
  • ๊ธ€๋กœ๋ฒŒ ์„ค์ •
    • Axios ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„ค์ •์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Œ
    • ex) ๋ชจ๋“  ์š”์ฒญ์— ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉ๋  ๊ธฐ๋ณธ URL, ํ—ค๋”, ํƒ€์ž„์•„์›ƒ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.timeout = 2500;
  • ์—๋Ÿฌ ํ•ธ๋“ค๋ง
    • Axios ์š”์ฒญ์ด ์‹คํŒจํ•  ๋•Œ, ์—๋Ÿฌ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์ƒํƒœ ์ฝ”๋“œ, ์‘๋‹ต ๋ฉ”์‹œ์ง€ ๋“ฑ์˜ ์ •๋ณด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ
    • ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Œ
axios.get('/user/12345')
      .catch(function (error) {
            if (error.response) {
                  console.log(error.response.data);
                  console.log(error.response.status);
                  console.log(error.response.headers);
            } else if (error.request) {
              	console.log(error.request);
            } else {
              	console.log('Error', error.message);
            }
            console.log(error.config);
      });
  • ์‘๋‹ต ํ˜•์‹
    • Axios๋Š” JSON ํ˜•์‹์˜ ์‘๋‹ต์„ ์ž๋™์œผ๋กœ JavaScript ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์คŒ
    • ๋ฐ์ดํ„ฐ๋ฅผ ์ฆ‰์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•จ
axios.get('/user/12345')
      .then(function (response) {
            console.log(response.data); // ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฐ์ดํ„ฐ
            console.log(response.status); // HTTP ์ƒํƒœ ์ฝ”๋“œ
            console.log(response.statusText); // ์ƒํƒœ ๋ฉ”์‹œ์ง€
            console.log(response.headers); // ์‘๋‹ต ํ—ค๋”
            console.log(response.config); // ์š”์ฒญ ๊ตฌ์„ฑ
      });
  • ํŒŒ์ผ ์—…๋กœ๋“œ
    • Axios๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Œ
    • FormData ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ€ํ‹ฐํŒŒํŠธ ํผ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ์ „์†กํ•  ์ˆ˜ ์žˆ์Œ
const formData = new FormData();
formData.append('file', fileInput.files[0]);

axios.post('/upload', formData, {
      headers: {
        	'Content-Type': 'multipart/form-data'
      }
});
  • ๋ณด์•ˆ ์‚ฌํ•ญ
    • API ์š”์ฒญ์„ ํ•  ๋•Œ ๋ณด์•ˆ์„ ๊ณ ๋ คํ•ด์•ผํ•จ
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์š”์ฒญ ์œ„์กฐ(CSRF)์™€ ๊ฐ™์€ ๊ณต๊ฒฉ์œผ๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด ์ ์ ˆํ•œ ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”
axios.get('/user/12345', {
  	withCredentials: true // ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์š”์ฒญ ์‹œ ์ธ์ฆ ์ •๋ณด(์ฟ ํ‚ค ๋“ฑ)์„ ํ•จ๊ป˜ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ ์„ค์ •
});
  • Axios์˜ ๊ธฐ๋Šฅ
    • axios.create
    • ์ƒˆ๋กœ์šด Axios ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณต
const apiClient = axios.create({
      baseURL: 'https://api.example.com',
      timeout: 1000,
      headers: {'X-Custom-Header': 'foobar'}
});
  • Axios์˜ ์ „์—ญ ์„ค์ •์„ ์ •์˜ํ•˜๋Š” ์†์„ฑ ๋˜๋Š” ํ”„๋กœํผํ‹ฐ
    • axios.default
    • ์ „์—ญ Axios ์„ค์ •์„ ์ •์˜ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณต, Axios์˜ ์ „์—ญ ์„ค์ •์„ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์˜ ํŠน์ •๊ฐ’
axios.defaults.baseURL = 'https://api.example.com';
//axios.defaults๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „์—ญ Axios ์„ค์ •์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Œ
//์ด๊ฒƒ์€ ๋ชจ๋“  Axios ์š”์ฒญ์— ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค

axios.get('/user', { timeout: 5000 });
//๊ฐœ๋ณ„ Axios ์š”์ฒญ์— ์ง์ ‘ ๊ตฌ์„ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ.ํ•ด๋‹น ์š”์ฒญ์—๋งŒ ์ ์šฉ๋จ

 

 

 

 

์ปจํŠธ๋กค๋Ÿฌ ์˜ˆ์‹œ

 

@Controller
public class MyController {
    @GetMapping("/get-data")
    @ResponseBody
    public ResponseEntity<String> getData() {
        // ์Šคํ”„๋ง ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์‘๋‹ตํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑ
        String responseData = "Hello, this data is from the server!";
        return ResponseEntity.ok(responseData);
    }
}

 

 

 

JSP

 

<!DOCTYPE html>
<html>
<head>
    <!-- Axios ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ CDN์„ ํ†ตํ•ด ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
    <button id="getDataButton">๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ</button>
    <div id="responseData"></div>

    <script>
        // ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
        document.getElementById('getDataButton').addEventListener('click', function () {
            // Axios๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GET ์š”์ฒญ์„ ์„œ๋ฒ„๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
            axios.get('/get-data')
                .then(function (response) {
                    // ์š”์ฒญ์ด ์„ฑ๊ณตํ•˜๋ฉด ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
                    document.getElementById('responseData').innerText = '์„œ๋ฒ„ ์‘๋‹ต: ' + response.data;
                })
                .catch(function (error) {
                    // ์š”์ฒญ์ด ์‹คํŒจํ•˜๋ฉด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
                    console.error('์—๋Ÿฌ:', error);
                });
        });
    </script>
</body>
</html>
  • ์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” Axios๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์„œ๋ฒ„๋กœ GET ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„์—์„œ ์‘๋‹ตํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ
  • ์ด๋ ‡๊ฒŒ ์Šคํ”„๋ง๊ณผ JSP์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ Axios๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
 

 

 

 
Thymeleaf

 

<!DOCTYPE html>
<html>
<head>
    <!-- ํƒ€์ž„๋ฆฌํ”„๋กœ ๋™์ ์ธ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๋“ฑ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค -->
    <title>ํŽ˜์ด์ง€ ์ œ๋ชฉ</title>
</head>
<body>
    <h1>ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ </h1>

    <!-- Axios ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํฌํ•จ -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    <script>
        // Axios๋ฅผ ์‚ฌ์šฉํ•œ API ํ˜ธ์ถœ ์˜ˆ์‹œ
        axios.get('/api/your-endpoint')
            .then(function (response) {
                // ์‘๋‹ต ์ฒ˜๋ฆฌ
                console.log(response);
            })
            .catch(function (error) {
                // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
                console.error(error);
            });
    </script>
</body>
</html>