Ajax
는 클라이언트와 서버간 비동기적으로 데이터를 주고 받기 위한 기술입니다
오늘은 또 다른 방식의 비동기 통신 기술인 Fetch
와 Axios
에 대해 알아보겠습니다
먼저 예제 코드를 통해 코드의 사용법부터 파악해보려 합니다
아래는 지금까지 써온 Ajax
방식의 예제 코드입니다
// 리퀘스트 메서드 생성
const request = ({ method, path, body }) => {
return new Promise((resolve, reject) => {
const host = `http://localhost:3000`;
const xhr = new XMLHttpRequest();
xhr.open(method, `${host}${path}`);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(body));
xhr.onload = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error("Error"));
}
};
});
};
// 코드 사용
const ajax = await request({method : "get", path :"/comments", body : null })
// console.log(ajax)
다음은 Fetch
방식의 예제 코드입니다
const response = await fetch("http://localhost:3000/comments", {
method: "get",
headers: {
"Content-Type": "application/json"
},
body: null
})
// console.log(response)
const body = await response.json(); // 요청에 대한 응답 메세지를 객체화(JSON)해서 출력합니다
마지막으로 Axios
예제 코드입니다
// axios (XMLHttpRequest를 바탕으로 만든 외장 모듈입니다)
// <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
// 공식문서 : http://axios-http.com/kr/docs/example
const getAxios = await axios.get('http://localhost:3000/comments')
const postAxios = await axios.post('http://localhost:3000/comments', {
// 두번째 인자값은 body 영역({})입니다
content : 'axios test'
})
console.log(getAxios.data)
console.log(postAxios.data)
})()
위 예제코드를 바탕으로 각각의 특징과 장단점을 정리하자면 다음과 같습니다
AJAX
장점
- 리퀘스트 메서드를 생성하고 나면 코드 사용이 간편합니다
단점
- 객체 생성 및 사전 작업이 매우 불편합니다
- Promis 기반이 아닙니다
FETCH
장점
- Promis 기반입니다
- 자바스크립트가 기본적으로 제공하는 내장 라이브러리입니다
단점
- 따로 JSON 변환작업이 필요합니다
- 코드 사용이 다소 번거롭고, 응답 바디 영역을 추출하려면await
이 두 번 필요합니다
AXIOS
장점
- Promis 기반입니다
- 사용법이 셋 중 가장 간편하고 많은 기능을 제공합니다
- 전송 데이터 타입의 기본값이 JSON 방식입니다
단점
- 별도의 라이브러리 설치 혹은 외부 링크 연결이 필요합니다
사실상 Fetch
를 쓸 것이냐 Axios를 쓸 것이냐의 2택입니다만
자바스크립트가 자체적으로 더 나은 기능을 제공하지 않는 이상은
AXIOS
를 사용하는 것이 가장 나아보이네요
지난 시간에 AJAX로 만든 댓글 기능구현 코드를 AXIOS로 고쳐보겠습니다
client javascript
const commentList = document.querySelector("#comment-list");
const addComment = document.querySelector(".submit");
const userid = "nazzzo";
const content = document.querySelector(".int");
const totalNumber = document.querySelector(".total-number");
// 현재 시간 (시간표현 수정용)
const getTimeNow = (date) => {
let mm = date.getMonth() + 1;
mm = (mm > 9 ? "" : "0") + mm;
let dd = date.getDate();
dd = (dd > 9 ? "" : "0") + dd;
let yy = date.getFullYear();
let hr = date.getHours();
let mn = date.getMinutes();
let sc = date.getSeconds();
return [yy, mm, dd].join("-") + " " + [hr, mn, sc].join(":");
};
const thisTime = getTimeNow(new Date());
console.log(thisTime);
// 데이터 출력 함수
const displayResult = async () => {
const getComments = await axios.get("http://localhost:3000/comments");
const comments = getComments.data;
totalNumber.innerHTML = `(${comments.length})`;
// 댓글 리스트 초기화 필수
commentList.innerHTML = "";
for (const comment of comments) {
const commentRow = document.createElement("li");
commentRow.innerHTML = `
<span class="comment-id">${comment.id}</span>
<span class="comment-userid">${comment.userid}</span>
<span class="comment-content">${comment.content}</span>
<input class="comment-input" type="text" style="display :none" value="${comment.content}">
<span class="comment-register">${comment.register}</span>
<button class="comment-modify" style="display :none">수정</button>
<button class="comment-delete">삭제</button>
`;
commentRow.setAttribute("data-id", comment.id);
commentList.appendChild(commentRow);
}
// 댓글 삭제
const dltComment = document.querySelectorAll(".comment-delete");
dltComment.forEach((dltButton) => {
dltButton.addEventListener("click", async () => {
const li = dltButton.parentElement;
const id = li.getAttribute("data-id");
console.log(id);
await axios.delete(`http://localhost:3000/comments`, {
data: { id },
});
displayResult();
});
});
// 댓글 수정
const modiComment = document.querySelectorAll(".comment-content");
modiComment.forEach((modiContent) => {
modiContent.addEventListener("click", async () => {
const li = modiContent.parentElement;
const span = li.querySelector(".comment-content");
const modiButton = li.querySelector(".comment-modify");
const id = li.getAttribute("data-id");
const input = li.querySelector(".comment-input");
span.style.display = "none";
input.style.display = "inline-block";
modiButton.style.display = "inline-block";
input.focus();
modiButton.addEventListener("click", async () => {
await axios.put(`http://localhost:3000/comments/${id}`, { id, content: input.value },
);
span.innerHTML = input.value;
displayResult();
});
});
});
// 시간 표현 수정
const regitTimeList = document.querySelectorAll(".comment-register");
console.log(regitTimeList);
regitTimeList.forEach((regitTimeRow, index) => {
const parsedTimeRow = regitTimeRow.innerHTML.split(/[ :]/);
const splitThisTime = thisTime.split(/[ :]/)
console.log(parsedTimeRow);
console.log(splitThisTime);
if (
splitThisTime[0] === parsedTimeRow[0] &&
splitThisTime[1] === parsedTimeRow[1] &&
splitThisTime[2] === parsedTimeRow[2]
) {
regitTimeList[index].innerHTML = "방금전";
}
else if (
splitThisTime[0] === parsedTimeRow[0] &&
splitThisTime[1] === parsedTimeRow[1] &&
splitThisTime[2] !== parsedTimeRow[2]
) {
regitTimeList[index].innerHTML = `${splitThisTime[2] - parsedTimeRow[2]}분전`;
} else if (
splitThisTime[0] === parsedTimeRow[0] &&
splitThisTime[1] - parsedTimeRow[1] < 13
) {
regitTimeList[index].innerHTML = `${splitThisTime[1] - parsedTimeRow[1]}시간전`;
} else {
regitTimeList[index].innerHTML = parsedTimeRow[0];
}
});
};
displayResult();
// 댓글 등록
(async () => {
addComment.addEventListener("click", async () => {
await axios.post("http://localhost:3000/comments", {
userid,
content: content.value,
});
displayResult();
});
})();
여전히 코드가 멋이 없고 특히 수정 코드가 너무 더럽습니다 ㅠㅠ
이제 계속 미뤄두던 디자인 패턴에 대해서도 공부를 해야 할 것 같아요