본문 바로가기
Frontend/JavaScript

JavaScript : 비동기 통신에 대해서 (Fetch & Axios)

by 코딩쥐 2024. 8. 14.

통신 종류

동기 통신

동기 통신은 클라이언트가 요청(request)을 전송하면, 해당 요청에 대한 응답(response)을 받을 때까지 기다리는 방식이다.  따라서 응답이 도착하기 전에는 다른 요청을 할 수 없다. 이 방식은 요청에 대한 처리 결과를 보장받을 수 있지만, 응답이 지연되면 클라이언트는 계속해서 기다려야 한다는 단점이 있다.

 

비동기 통신

비동기 통신의 경우 request를 보내더라도 response을 기다리지 않고 다른 작업을 계속 수행할 수 있다. 따라서 response가 지연되더라도 계속해서 다른 요청을 보낼 수 있다. 그러나 비동기 통신은 요청에 대한 처리 결과나 응답의 순서를 보장받기 어렵다는 단점이 있다. 

 

JavaScript의 비동기 처리 필요성

JavaScript의 경우 싱글 스레드로 동작하기 때문에 한 번에 하나의 작업만 처리할 수 있다. 긴 응답 시간이 필요한 작업이 동기적으로 처리될 경우, 그 작업이 완료될 때까지 다른 작업이 중단된다. 이로 인해 사용자들은 화면 깜빡임 등의 불편한 경험을 겪게 된다. 이러한 문제를 해결하기 위해 JavaScript에서는 비동기 통신을 사용한다.


비동기 통신 종류

XMLHttpRequest

비동기 HTTP 요청을 처리하기 위한 초기 API이다. 현재 지원하는 곳이 많이 줄었고, 많은 리소스 사용 및 복잡한 코드 등의 이유로 사용을 거의 하지 않는 상태다.

 

AJAX

JavaScript를 이용하여 비동기적으로 서버와 브라우저가 데이터를 교환할 수 있는 통신 방식으로, 비동기 HTTP 요청을 처리하기 위해  XMLHttpRequest 객체를 사용했다. AJAX의 경우 jQuery와 같은 라이브러리와 함께 사용되면서 간편하게 사용할 수 있었으나, 이후 프레임워크의 사용화와 jQuery의 성능상 문제가 대두되면서 자연스레 jQuery사용이 줄어들게 되었고 현재는 JavaScript 표준인 Fetch API와 async/await 구문으로 대체되는 경우가 많아졌다. 

 

Fetch API 

Fetch API는 비동기 HTTP 요청을 처리할 수 있는 JavaScript 표준 API로, Promise를 기반으로 하여 비동기 작업의 결과를 처리한다. 표준 데이터 형식은 JSON이지만, XML,텍스트 등의 다양한 데이터 형식도 지원한다.   

  • fetch(url, [option])
    .then(response => return response.json();)
    .then(data => {데이터 처리 로직};)
    .cath(error => {요청 실패시 로직};)

 

<Fetch API 예제>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        fetch("https://jsonplaceholder.typicode.com/comments").then(response => response.json())
            .then(data => {
                document.querySelector("#name").textContent = data[0].name;
                document.querySelector("#email").textContent = data[0].email;
                document.querySelector("#addr").textContent = data[0].body;
            })
            .catch(error =>{
                console.log(`에러 발생 : ${error}`);
            }
            );
    </script>
    
    <h1>이름 : <span id="name"></span></h1>
    <h1>이메일 : <span id="email"></span></h1>
    <h1>주소 : <span id="addr"></span></h1>
</body>     

</html>

 

fetch는 비동기 함수이기때문에 fetch를 사용하여 데이터를 불러올 때 동기화가 필요하다.  fetch의 경우 Promise를 기반으로 하기 때문에, async와 await를 사용해서 동기화를 할 수 있다. 

 

아래 내용을 보면 async를 통해서 비동기 함수 앞에 선언하고, await를 통해서 해당 로직이 완료된 다음에 다음 로직이 시행되도록 했다. try, catch문을 사용하여 응답이 성공했을 때, 응답이 성공하지않았을 때(!response.ok) 그리고 에러가 발생했을 때에 대한 예외처리를 시행한다. 응답이 성공했을 때는 불러온 데이터를 사용해서 해당 값을 사용해야하는 곳에 값을 넣어준다. 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        async function getData() {
            const url = "https://jsonplaceholder.typicode.com/comments";
            try {
                const response = await fetch(url);
                if (!response.ok) {
                    throw new Error(`Response status: ${response.status}`);
                }

                const result = await response.json();
                console.log(result)

                document.querySelector("#name").textContent = result[0].name;
                document.querySelector("#email").textContent = result[0].email;
                document.querySelector("#addr").textContent = result[0].body;

            } catch (error) {
                console.error(`에러발생 : ${error.message}`);
            }
        }

        getData();

    </script>

    <h1>이름 : <span id="name"></span></h1>
    <h1>이메일 : <span id="email"></span></h1>
    <h1>주소 : <span id="addr"></span></h1>
</body>

</html>

 

Axios 

Axios는 Promise API를 활용하는 HTTP 비동기 통신 라이브러리로, 브라우저와 node.js 환경 모두에서 사용이 가능하다. Fetch API의 경우 웹 브라우저에서 기본적으로 제공하는 API이므로 추가적인 라이브러리나 의존성 없이 사용이 가능하고, Axios의 경우 따로 설치가 필요하다. 하지만 Axios의 경우 Fetch API보다 사용이 간편하고 추가적인 기능을 제공하고 있기 때문에 사용환경 및 요구사항에 맞게 Fetch API / Axios를 선택하여 사용한다. 

 

JavaScript에서 Axios 사용 방법

  • <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"/>
    Axios 라이브러리를 불러온 다음에 사용이 가능하다.
  • axios.get(url).then(response => {데이터(reponse.data) 처리 로직} ;
    Fetch의 경우 JSON을 변환을 한 다음에 데이터를 사용가능하지만, Axios의 경우 JSON 데이터의 변환을 자동으로 처리한다. 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>

<body>
    <h1 id="title">제목 로딩 중...</h1>
    <h3 id="body">내용 로딩 중...</h3>
    <script>
        window.addEventListener("load", () => {
            axios.get("https://jsonplaceholder.typicode.com/posts/2")
                .then(response => {
                    console.dir(response.data);
                    document.querySelector("#title").textContent = response.data.title;
                    document.querySelector("#body").textContent = response.data.body;
                })
                .catch(error => {
                    console.error('Error fetching data:', error);
                    document.querySelector("#title").textContent = "제목을 로딩하는데 실패하였습니다.";
                    document.querySelector("#body").textContent = "내용을 로딩하는데 실패하였습니다.";
                });
        });
    </script>
</body>

</html>


Fetch와 Axios 메서드

GET

리소스 조회를 위해 사용한다. fetch의 경우 JSON파일 변환하기 위한 추가적인 단계가 필요하다. Axios의 경우 자동으로 JSON을 변환하기 때문에 response.data를 통해 데이터에 접근이 가능하다. 

 

Fetch

fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));

 

Axios

axios.get('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error));

 

POST

서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다. fetch는 POST요청 시에 method, headers, body를 직접 설정해야 한다. 

 


Fetch

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    title: '코딩쥐',
    body: '코딩쥐의 티스토리',
    userId: 1
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

 

Axios

axios.post('https://jsonplaceholder.typicode.com/posts', {
  title: '코딩쥐',
  body: '코딩쥐의 티스토리',
  userId: 1
})
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error));

 

 

PUT

기존의 리소스를 새로운 데이터로 완전히 교체한다. 


Fetch

fetch('https://jsonplaceholder.typicode.com/posts/1', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    id: 1,
    title: '코딩쥐',
    body: '티스토리',
    userId: 1
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));


Axios

axios.put('https://jsonplaceholder.typicode.com/posts/1', {
  id: 1,
  title: '코딩쥐',
  body: '티스토리',
  userId: 1
})
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error));


PATCH

기존 리소스를 새로운 데이터로 부분적으로 변경하고 싶을 때 사용한다. 부분변경이 필요 없을 경우에는 POST를 사용한다.


Fetch

fetch('https://jsonplaceholder.typicode.com/posts/1', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    title: '코딩쥐가 공부하는 법'
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

 

Axios

axios.patch('https://jsonplaceholder.typicode.com/posts/1', {
  title: '코딩쥐가 공부하는 법'
})
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error));

 

DELETE

서버에서 리소스를 제거하려는 경우 사용된다. Fetch의 경우 네트워크 오류만 catch 블록으로 잡을 수 있어, 응답이 성공적인지 여부를 확인하기 위해서는 그에 대한 로직을 따로 작성해야 한다. Axios의 경우 HTTP 오류 상태 코드를 자동으로 reject상태로 만들어 catch 블록에서 잡을 수 있다. 


Fetch

fetch('https://jsonplaceholder.typicode.com/posts/1', {
  method: 'DELETE'
})
  .then(response => {
    if (response.ok) {
      console.log('삭제 성공');
    } else {
      console.log('삭제 실패');
    }
  })
  .catch(error => console.error('Error:', error));


Axios

axios.delete('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => console.log('삭제 성공'))
  .catch(error => console.error('Error:', error));