티스토리 뷰

지난주 주말에 html, css, js로 화면 구현 테스트를 봤다. 오랜만에 React가 아닌 js로만 구현하려니 아쉬운 코드라고 느끼면서도 그렇게 제출할 수밖에 없었다...🥺 어떻게 해야할지 모르겠어요.... 시험을 본 뒤로 계속 머릿속을 떠나지 않아서 찾아보고 기록해두려고 한다.

 

- 문제 -

fetch 후 데이터를 활용한 모든 코드를 2번째 then 안에 넣을 수 밖에 없는가..?

fetch로 받아온 목데이터로 html 태그를 생성했는데 원래 html에 존재했던 태그는 fetch 밖에서 선언해 가져올 수 있었지만 데이터를 가지고 생성한 태그는 fetch 밖에서 접근하려고 하면 null이 들어왔다. 그래서 어쩔 수 없이 fetch 뒤에 2번째 then에 모든 코드를 다 넣을 수밖에 없었다. 이것보다 좋은 코드를 작성하는 방법에 대해서 생각해보게 되었다.

// 시험 때 제출한 코드

const sth1 = document.getElementById('something1');
const sth2 = document.getElementById('something2');
const sth3 = document.getElementById('something3');

fetch('./data.json')
.then((res)=>res.json())
.then((data)=>{

  ...
  대략 코드 100줄
  ...
  
})

 

 

- 생각한 방법 1

fetch를 async를 사용해서 동기적으로 실행한다.?

비동기하면 생각나는 async 키워드를 사용해서 fetch를 동기적으로 실행하면 되지 않을까 생각했다. 구글링을 해서 찾아본 결과(1, 2, 3) fetch를 async를 사용한 함수에 넣고, 함수 실행 결과에 then을 붙여서 사용하는 방법이 많았다.

이렇게 하면 위 방법과 별 다를 바 없다고 생각해서 a라는 변수에 data.users를 넣어서 사용하려고 했다. 하지만 콘솔을 찍어보니 내 생각과는 다르게 a는 1이었다. async를 붙인 함수는 다른 코드들과 다르게 비동기적으로 실행됐다.

let a = 1;

const fetchFunction = async () => {
  const response = await fetch('./data.json');
  const data = await response.json();
  return data;
};

fetchFunction().then(async (data) => (a = await data.users));

console.log('a : ', a); // a :  1

 

함수 실행결과 자체를 a에 담으면 되지 않을까 싶어서 함수 실행결과를 담아봤다. 그러나 a에 담기는 것은 promise 객체 자체였고 내가 원하는 데이터에 접근할 수 없었다. 검색해보니 then은 항상 promise객체를 리턴하기 때문에 함수 실행결과를 변수에 담으면 promise객체가 담기기 때문에 데이터에 접근하는 것은 불가능해 보였다. 결국 이 방법은 잘못된 방법으로 폐기되었다.👎

let a = 1;

const fetchFunction = async () => {
  const response = await fetch('./data.json');
  const data = await response.json();
  return data;
};

a = fetchFunction().then(async (data) => (a = await data.users));

console.log('a : ', a); // a :  Promise {<pending>}

 

 

- 생각한 방법 2

async 익명 함수로 모두 감싸서 순차적으로 실행한다..?

fetch가 비동기 함수라서 그 안에 구구절절 써야 한다면 async를 사용해서 fetch와 then 안에 넣었던 코드들을 같은 depth로 실행하는 게 낫지 않을까라는 생각이 들었다. 그래서 일단 async 익명 함수를 만들고 안에 fetch를 넣었다.

async () => {
  await fetch('./data.json')
    .then((res) => res.json())
    .then((data) => console.log(data.users));
}

 

그런데 함수가 실행이 되질 않았다. 찾아보니 바로 실행되도록 해줘야 했다.

(async () => {
  await fetch('./data.json')
    .then((res) => res.json())
    .then((data) => console.log(data.users)); // [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
})();

 

async 익명 함수 안에 긴 코드를 넣어주긴 했지만 then에 모든 걸 다 넣는 것보다는 depth가 줄어서 가독성이 좋아졌다는 생각이 들었다. 

const table = document.getElementById('myTable');

(async () => {
  let tableData;
  await fetch('./data.json')
    .then((res) => res.json())
    .then((data) => (tableData = data.users));
  const htmlData = tableData.map(
    (el) =>
      `<tr>
      <td>${el.id}</td>
      <td>${el.name}</td>
      <td>${el.email}</td>
    </tr>`
  );
  table.innerHTML = `
    <thead>
    <tr><td>id</td><td>name</td><td>email</td><tr>
    </thead>
    <tbody>
    ${htmlData.join('')}
    </tbody>
    `;
    
    const trs = [...document.getElementsByTagName('tr')];
    
    ...
    그리고 남은 긴 코드
    ...
})();

 

 

- 결론 -

일단은 async 익명 함수로 감싸는 걸로 만족!

then 뒤에 모든 코드를 다 넣었을 땐 depth가 깊어지면서 코드를 알아보기가 힘들었다. async 익명함수로 감싸서 fetch를 동기적으로 실행하니 나머지 코드들과 depth가 같아져서 가독성이 좋아진 것 같다. async/await 키워드를 '비동기를 동기적으로 실행할 때 사용한다'라고 알고 있었는데 async 비동기 함수 내부에서는 동기적으로 실행되나 그 함수와 같은 depth에 있는 동기적으로 작동하는 코드와 비교했을 때는 여전히 비동기적으로 실행된다는 것을 알게 되었다.

바닐라 js로 fetch를 이용하는 좋은 방법이 뭔지 아직 확실치 않지만 이번은 여기서 만족하고 또 바닐라 js로 fetch를 사용할 기회가 생긴다면 이 방법을 써야겠다. async/await을 흐린 눈으로 모른척했는데 조금 가까워진 것 같다! 😀

 

 

혹시 틀린 점이나 알면 좋을 부분이 있다면 알려주시면 감사하겠습니다~ 😀

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함