
API를 연동하는 방법은 여러 가지가 있습니다.
주요 방법 4가지로는 fetch(), axios, XMLHttpRequest, jQuery.ajax() 가 있습니다.
fetch()는 모던 자바스크립트에서 대표적으로 사용하는 비동기 요청 방식으로, Promise 기반 API를 제공해 가독성과 활용성이 좋습니다.
axios는 브라우저와 Node.js 모두에서 사용할 수 있는 HTTP 비동기 통신 라이브러리로, React 등 프런트엔드 프레임워크 사용자들이 특히 많이 활용합니다.
XMLHttpRequest는 가장 오래된 API 요청 방식으로, Ajax의 핵심 기반 기술이지만 코드 가독성이 떨어져 요즘은 잘 쓰이지 않습니다.
jQuery.ajax() jQuery 라이브러리의 Ajax 기능으로, 브라우저 호환성이 좋지만 jQuery 자체를 로드해야 하므로 현대적인 프로젝트에서는 거의 사용되지 않습니다.
이런 여러 방식의 연동 방식이 있지만
오늘은 fetch() 함수를 이용해 API를 연동해 보겠습니다.
fetch API 브라우저에서 제공하는 자바스크립트 인터페이스로, 네트워크로 요청을 보내고 응답 처리를 하는 기능을 제공한다.
브라우저에서 fetch() 함수를 지원하기 전에는 클라이언트 단에서 직접 HTTP를 요청하고 응답을 받는 게 복잡해서 axios, jQuery와 같은 라이브러리를 사용하는 것이 합리적이었습니다.
하지만 요즘에는 굳이 이러한 라이브러리의 도움없이도 브라우저에서 내장된 fetch() 함수를 이용하면 대부분의 경우 충분하기 때문에 오히려 이러한 라이브러리를 사용하는 것이 자바스크립트 번들(bundle) 파일의 크기만 늘려서 낭비가 될 수 있습니다.
번들(bundle) 파일이란??
여러 파일을 하나로 결합하는 작업을 나타낸다.
이를 통해 웹 애플리케이션의 성능을 최적화하고 관리를 더 쉽게 만드는데 도움이 된다.
fetch() 함수는 첫번째 인자로 URL, 두번째 인자로 옵셥 객체를 받고 Promise 타입의 객체를 반환합니다.
반환된 객체는, API 호출이 성공했을 경우에는 응답(response) 객체를 resolve하고, 실패했을 경우에는 예외(error) 객체를 reject 합니다.
fetch(url, options)
.then((response) => console.log("response:", response))
.catch((error) => console.log("error:", error));
옵션 객체에는 HTTP 방식, HTTP 요청 헤더, HTTP 요청 전문 등을 설정해줄 수 있습니다.
응답 객체로 부터는 HTTP 응답 상태, HTTP 응답 헤더, HTTP 응답 전문 등을 읽어올 수 있습니다.
fetch method 에는 GET, POST, PUT, PATCH, DELETE가 있습니다.
먼저 단순히 원격 API에 있는 데이터를 가져올 때 사용하는 GET 방식입니다.
인터넷에 공개된 API를 사용해서 예제 코드를 작성하면
fetch() 함수는 디폴트로 GET 방식으로 작동하고 GET 방식은 요청 전문을 받지 않기 때문에 옵션 인자가 필요 없습니다.
fetch("https://jsonplaceholder.typicode.com/posts/1").then((response) =>
console.log(response)
);
응답 객체를 통해 응답 상태가 200 OK(요청이 정상적으로 실행되었다)인 것을 금방 알 수 있습니다.
대부분에 API들은 Json 형태의 데이터를 응답하기 때문에, 응답 객체는 json()메서드를 제공합니다.
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())
.then((data) => console.log(data));
이 json() 메서드를 호출하면 응답 객체로부터 json 포맷의 응답 전문을 자바스크립트 객체로 변환하여 얻을 수 있습니다.
응답 전문이란?
웹에서 클라이언트가 서버에 요청을 보내면, 서버는 그에 대한 응답을 HTTP 응답 메시지 형태로 보내는데 크게 세 부분으로
1. 상태 줄 2. 헤더 3. 본문 으로 나뉘어 응답 전문은 본문에 해당합니다.
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit↵suscipit recusandae consequuntur …strum rerum est autem sunt rem eveniet architecto"
}
단순히 특정 API에 저장된 데이터를 보여주는 웹페이지나 애플리케이션에서는 GET 방식의 HTTP 통신으로 충분합니다.
원격 API에서 관리하고 있는 데이터를 생성해야 한다면 요청 전문을 포함할 수 있는 POST 방식의 HTTP 통신이 필요합니다.
동일한 API로 새로운 포스팅을 생성하기 위해서 fetch() 함수를 사용해보겠습니다.
이에 경우 method 옵션을 POST로 지정해주고 headers 옵션을 통해 JSON 포맷을 사용한다고 알려줘야하고 요청 전문을 JSON 포맷으로 직렬화하여 가장 중요한 body 옵션에 설정해줍니다.
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Test",
body: "I am testing!",
userId: 1,
}),
}).then((response) => console.log(response));
POST에 경우에는 201 Created 나타납니다.
200 OK와 201 Created의 차이로는 200 OK는 요청이 정상적으로 실행되었다 라면 201 Created는 요청이 실행되었고 리소스가 만들어졌다는걸 의미합니다.
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Test",
body: "I am testing!",
userId: 1,
}),
})
.then((response) => response.json())
.then((data) => console.log(data));
마찬가지 방법으로 응답 객체의 json() 메서드를 호출하면 응답 전문을 객체 형태로 얻을 수 있습니다.
{title: "Test", body: "I am testing!", userId: 1, id: 101}
GET과 POST만큼은 아니지만, 원격 API에서 관리하는 데이터의 수정과 삭제를 위해서 PUT과 DELETE 방식의 HTTP 호출을 사용할 때가 있습니다.
PUT 방식은 method 옵션만 put으로 설정한다는 점 빼놓고는 POST 방식과 매우 비슷합니다.
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "finish",
body: "I am die",
userId:21,
}),
})
.then((response) => response.json())
.then((data) => console.log(data));
{title: "Test", body: "I am testing!", userId: 1, id: 1}
DELETE 방식에서는 보낼 데이터가 없기 때문에 headers와 body 옵션이 필요 없습니다.
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "DELETE",
})
.then((response) => response.json())
.then((data) => console.log(data));
그럼 제가 공개 API를 통해 GET method를 사용하여 만든 영화 검색기 코드를 알아보겠습니다.
import config from "./config.js";
const {API_KEY}=config;
document.querySelector('#btn').addEventListener("click", searchMovie);
function searchMovie(){
const title=document.getElementById('ss').value;
const movieinfo = document.getElementById('movie-info');
fetch(`https://www.omdbapi.com/?t=${title}&apikey=${API_KEY}`)
.then(response=>response.json())
.then(data=>{
if(data.Response==='True'){
document.querySelector('#movie-title').textContent = `${data.Title} (${data.Year})`;
document.querySelector('#movie-poster').src = data.Poster;
document.querySelector('#movie-director').textContent = data.Director;
document.querySelector('#movie-plot').textContent = data.Plot;
document.querySelector('#movie-rating').textContent = data.imdbRating;
document.querySelector('#error').textContent = '';
movieinfo.style.display = 'flex';
} else {
document.querySelector('#error').textContent = '영화를 찾을 수 없습니다.';
movieinfo.style.display='none';
}
})
}
한 줄 씩 알아보자면
import config from "./config.js";
const {API_KEY}=config;
apikey가 따로 있기 때문에 config.js 파일에 작성한 것을 가져오고있고
document.querySelector('#btn').addEventListener("click", searchMovie);
id="btn" 인 버튼을 찾아서 클릭하면 searchMovie 함수를 실행하도록 이벤트 리스너를 등록합니다.
searchMovie함수에는
const title = document.getElementById('ss').value;
const movieinfo = document.getElementById('movie-info');
입력창 'ss'에 사용자가 입력한 영화 제목과 검색결과를 표시할 컨테이너 id="movie-info"를 가져옵니다.
fetch(`https://www.omdbapi.com/?t=${title}&apikey=${API_KEY}`)
검색할 영화 제목과 내 API 키를 불러오고 OMDB 공개 API에 요청을 보냅니다.
즉, 특정 영화 정보를 가져오기 위해 GET 요청을 보냅니다.
.then(response => response.json())
서버에 응답을 받으면 json 형식으로 바꿉니다.
.then(data=>{
if(data.Response==='True'){
document.querySelector('#movie-title').textContent = `${data.Title} (${data.Year})`;
document.querySelector('#movie-poster').src = data.Poster;
document.querySelector('#movie-director').textContent = data.Director;
document.querySelector('#movie-plot').textContent = data.Plot;
document.querySelector('#movie-rating').textContent = data.imdbRating;
document.querySelector('#error').textContent = '';
movieinfo.style.display = 'flex';
API 응답에서 "Response": "True"이면 영화 제목과 개봉 연도를 표시하고
이미지 태그 src 속성을 영화 포스터 이미지 URL로 설정합니다.
감독 이름과 줄거리, IMDB 평점을 표시하고
document.querySelector('#error').textContent = ''; 검색에 성공했으니 오류가 없기 때문에 에러 메시지를 비워주고 원래 display: none; 였던 속성들을 flex로 바꿔 화면에 보이도록 설정합니다.
} else {
document.querySelector('#error').textContent = '영화를 찾을 수 없습니다.';
movieinfo.style.display = 'none';
}
만약 "Response": "False"라면 에러 메시지 "영화를 찾을 수 없습니다." 를 표시하고 영화 정보 영역은 숨깁니다.
제가 만든 영화 검색기는 https://movie-dhcqtcbaw-s25023-6950s-projects.vercel.app/ 에서 찾아볼 수 있습니다.
이상으로 fetch 함수를 통한 API 연동법에 대해 알아보았습니다.
흠 흥미로운 글이군요 근데 프로필 사진이 좀 견디기 힘드네요..