[json-server CRUD] querySeletorAll, XMLHttpRequest, fetch, json-server

Soozynn·2022년 6월 1일
0

놀이용

목록 보기
1/1
post-thumbnail

친구의 과제를 도와주면서 json-server(가짜 서버로 가정)에 form을 통해 저장된 유저의 정보를 CRUD 하는 작업을 하였다. 이 시간을 통해 이전에 제대로 정리하지 못했던 fetchXMLHttpRequest, querySeletorAll 개념을 한번 더 정리해볼 수 있었다.

기본적인 예시는 아래처럼 form에 유저의 정보를 입력하면 db.json에 새로이 데이터를 생성해주고 결과보기 버튼 클릭 시 저장된 데이터를 가져와 이를 수정, 삭제 해줄 수 있는 기능을 만드는 것이었다.

(모달 창 내의 수정 버튼 클릭 시 모달 창이 닫히게 되고, form에 수정을 원하는 데이터를 불러오는 식으로 구현을 해주었고 수정한 데이터를 다시 저장하는 형태로 만들었다. 친구가 모달 창이 띄워지는 것을 원해서 원하는 바에 맞춰서 만들다보니 추후 기능적인 부분에서 부자연스러움을 많이 느꼈던 것 같다. 기획자와의 소통 부분에서도 앞으로 개발자 입장에서 어떻게 의사소통을 하고 어필을 하면 좋을지도 조금 배우게 된 시간이었다.)

모달의 css는 건들지 않고 대략적인 기능만 만들어 준 상태라 스타일은 흐린 눈 하며 봐주면 감사할 것 같다..

CRUD란?

  • Create(생성), Read(읽기), Update(수정), Delete(삭제) 약자를 유추해보면 알 수 있듯이 대부분의 컴퓨터 소프트웨어가 가지는 "기본적인 데이터 처리 기능"을 묶어서 일컫는다.

예시로 우리는 어느 곳에서든 어디에선가 데이터를 불러와 그것을 읽고 또 수정하며 삭제하기도 하는 작업을 아주 많이 하고 있다. 쇼핑몰에서 장바구니에 원하는 제품을 따로 담고 장바구니에서는 내가 저장한 상품들의 데이터를 불러와 모아 볼 수 있으며 장바구니에 담긴 상품의 사이즈나 색상을 수정할 수도, 마음에 들지 않는 상품은 삭제해줄 수도 있다.

해당 작업은 javascript를 사용하여 작업해주었고, 여기서 서버를 구축할 때 주로 많이 사용하는 expressmongoDB는 사용하지 않고 오직 json-server만을 이용하여 작업하였다. 이를 통해 가볍게 서버가 어떠한 방법으로 돌아가는지, 또 CRUD 작업은 어떤 식으로 동작하는지 내가 느낀 바를 정리해보고자 한다.


  • fetch(url, option)
    기본적인 Fetch 요청은 아래 코드와 같이 만들어 줄 수 있다.
fetch('http://example.com/movies.json')
  .then((response) => response.json())
  .then((data) => console.log(data));

"위 코드는 네트워크에서 JSON 파일을 가져와서 콘솔에 출력합니다.
GET의 fetch()는 가져오고자 하는 리소스의 경로를 나타내는 하나의 인수만 받습니다(option 생략).
응답은 Response 객체 (response)로 표현되며, 직접 JSON 응답 본문을 받을 수는 없습니다.

Response 객체 역시 JSON 응답 본문을 그대로 포함하지는 않습니다.
Response는 HTTP 응답 전체를 나타내는 객체로, JSON 본문 콘텐츠를 추출하기 위해서는 json() 메서드를 호출해야 합니다.
json()은 응답 본문 텍스트를 JSON으로 파싱한 결과로 이행하는, 또 다른 프로미스를 반환합니다." (mdn 참고)

console에 찍히는 값을 보면 json에 저장된 값이 잘 불러와 지는 것을 볼 수 있다.

  • XMLHttpRequest: fetch가 나오기 이전 기능
  • 둘의 차이는 무엇인지 짚고 넘어가기📝

// GET -> 결과보기 버튼을 사용하여 json에 저장된 유저의 정보들을 가져올 때 
// 이 외의 필요한 변수는 최상단에 선언해주었다.

// 🔴 결과보기 버튼 클릭 시 fetch를 통해 json에 저장된 값 가져오기
resultButton.addEventListener("click", () => {
  modal.classList.remove("none");
  modal.classList.add("modal");

// 🟢 GET일 때는 option을 생략해주어도 된다.
  fetch("http://localhost:3000/posts")
    .then((response) => response.json())
    .then((data) => {

    // 가져온 값에 따라서 저장된 데이터의 갯수만큼 자바스크립트 에서 동적으로 태그를 생성
      for (let i = 0; i < data.length; i++) {
        if (stopped) return; // 결과보기 버튼을 중복적으로 눌렀을 때 for문을 중복적으로 돌지 못하도록 하였다. 오로지 json data 값의 변경(POST, UPDATE, DELETE)이 일어났을 때에만 동작한다.
	
        const information = document.createElement("div");
        const content = document.createElement("div");
        const userId = document.createElement("div");
        const numId = document.createElement("div");
        const password = document.createElement("div");
        const editButton = document.createElement("button");
        const deleteButton = document.createElement("button");

        numId.textContent = data[i].id;
        userId.textContent = data[i].userid;
        password.textContent = data[i].pwd;
        content.textContent = data[i].content;
        editButton.textContent = "수정";
        deleteButton.textContent = "삭제";

        body.appendChild(modal);
        modal.appendChild(information);
        information.appendChild(numId);
        information.appendChild(userId);
        information.appendChild(content);
        information.appendChild(editButton);
        information.appendChild(deleteButton);
      }
    })
    .catch((error) => console.log(`fetch GET ERROR! ${error}`));
});

위처럼 결과보기 버튼을 눌렀을 때 fetch 메서드를 통해 json에 데이터를 불러와주었고 그럴 때마다 data의 갯수만큼 동적으로 element를 생성해주었다.

문제점

위 사진처럼 중복적으로 같은 class를 가진 태그들이 만들어지기 때문에 수정과 삭제 버튼이 제일 첫 요소만 클릭되는 문제가 있었다. 문제의 이유는 아래 링크와 같았다.

👉 javascript에서 html 태그를 잡아줄 때, 단일요소를 반환하는 메서드(ex getElementById)를 이용하여 잡아주었기 때문에 중복 되는 태그 중에서도 가장 첫 요소만 클릭 되는 문제였다.

중복되는 모든 태그를 가져오기 위해 기존에 querySelector 메서드를 querySelectorAll 메서드로 변경해주었고, 반복문을 통해 중복적인 모든 요소를 돌아주면서 이벤트리스너가 모든 요소에 작동할 수 있도록 아래 코드와 같이 수정해주었다.

      const deleteBtn = document.querySelectorAll(".deleteBtn"); // 나는 변수명을 지을 때 약자를 지양하지만, 친구의 기존 작업에 덧대어서 기능을 추가하느라 기존 변수명을 그대로 이용하였다.

      for (let i = 0; i < deleteBtn.length; i++) {
        deleteBtn[i].addEventListener("click", (event) => {
          fetch(
            `http://localhost:3000/posts/${event.target.parentNode.firstChild.textContent}`,
            {
              method: "DELETE",
              headers: {
                "Content-Type": "application/json",
              },
            }
          );
        });
      }

<다시한번 정리>
querySelector getElementById단일 요소를 반환!
querySelectorAll getElementsByNameNodeList를 반환!


이전 버전 getElementsByClassNamegetElementsByTagName 둘 다 HTMLCollections를 반환.


NodeListHTMLCollection은 모두 요소 컬렉션이다.



작업 완료된 예시는 아래와 같다 🤓

GET
결과보기 버튼을 누를 시 -> 저장된 정보들을 불러와 모달 창에서 목록을 보여준다.
자바스크립트에서 저장된 유저의 데이터 갯수만큼 동적으로 목록 태그를 생성해주었다.

POST
form에 정보를 입력하고 참여하기 버튼 클릭 시 json에 차례대로 저장이 된다. (저장된 순서대로 json에서 id가 부여되어진다.)
에러 없이 서버에 잘 저장이 되었다면, 저장이 완료되었다는 것을 모달을 통해 알려주었다.

🌈 UPDATE 🌈
결과보기 모달 창 내에서 수정버튼을 누르게 되면, 해당 데이터 값을 form에 다시 옮겨주고 모달 창은 자동으로 닫히게 만들어주었다.
또 이전에 값을 처음 추가할 때 버튼의 이름이 "참여하기" 였다면, 수정 버튼을 눌렀을 때에 기존 버튼 텍스트를 "수정하기"로 바꿔주었다.

수정을 할 때에 기존 저장되어있던 비밀번호와 일치하면 수정이 완료 되었다는 모달이 뜨고, 틀렸을 시에는 비밀번호가 틀렸다는 것을 모달을 통해 알려주었다.

DELETE
결과보기 모달 창 내에서 삭제버튼을 누르게 되면, 서버에서 일치하는 정보를 삭제시켜준다.

2개의 댓글

comment-user-thumbnail
2022년 6월 2일

오 역시.. 👍

1개의 답글