코린이 개념잡기/비동기 자바스크립트

리퀘스트: 브라우저에서 리퀘스트 확인

폭주하는 세발자전거 2024. 12. 27. 02:23

네트워크 리퀘스트를 보내는 코드는 보통 웹 브라우저에서 실행된다. 웹 브라우저에서는 개발자 도구로 네트워크 액티비티를 확인 할 수 있다. (이번 포스팅의 목적 : 개발자 도구의 네트워크 기능 알아보기)

웹 개발을 할 때는 네트워크 리퀘스트를 보내는 부분에서 생각지 못한 버그가 발생할 수 있는데 이럴 때 개발자 도구가 굉장히 유용하게 쓰인다. 

<!-- index.html -->
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>네트워크 요청 데모</title>
        <style>
            body {
                font-family: Arial, Helvetica, sans-serif;
                margin: 16px;
            }
            div {
                margin: 8px 0;
            }
            span {
                margin-right: 8px;
            }
        </style>
    </head>
    <body>
        <h2>네트워크 요청 데모</h2>
        <input id="mbti" placeholder="MBTI" />
        <input id="colorCode" placeholder="#000000" />
        <button>리퀘스트 보내기</button>
        <div class="status"></div>
        <div class="data"></div>
        <script type="module" src="demo.js"></script>
    </body>
</html>
//demo.js
import { getColorSurvey, createColorSurvey } from './api.js';

const btn = document.querySelector('button');
const statusDiv = document.querySelector('div.status');
const dataDiv = document.querySelector('div.data');
const mbtiInput = document.querySelector('#mbti');
const colorCodeInput = document.querySelector('#colorCode');

btn.addEventListener('click', async function (e) {
    statusDiv.textContent = '로딩 중...'; //이 함수는 우선 status를 로딩중으로 설정해주고
    dataDiv.innerHTML = '';
    try {
        const survey = await getColorSurvey(3); //이렇게 리퀘스트를 보낸다. getColorSurvey함수를 실행하고 있는데
        statusDiv.textContent = '완료'; //리스폰스가 돌아오면 status를 완료로 바꾸고
        dataDiv.innerHTML = `<span>${survey.mbti}</span><span>${survey.colorCode}</span>`; //dataDiv 안에 설문 객체의 mbti 필드와 colorCode 필드를 보여준다.
    } catch (e) { //만약 리퀘스트를 보내는 부분에서 에러가 나면
        statusDiv.textContent = '오류'; //status를 오류로 바꾸고 
        dataDiv.innerHTML = `<span>${e.message}</span>`; //에러 메세지를 dataDiv 안에서 보여준다.
    }
});

위 코드 그대로 실행해본 화면

페이지에는 그냥 폼 요소랑 버튼, 그리고 텍스트가 있다. html에서 body태그 안에 class status는 네트워크 요청 상태를 보여줄 div이고 class data div는 네트워크 요청 결과를 보여줄 div이다. 그리고 html 파일은 demo.js 파일과 연결되어 있는데 demo.js 파일을 보면 일단 API 함수들을 임포트하고 페이지에 있는 각종 요소들을 가져오고 있다. 그리고 중요한 이벤트 영역이 있는데 버튼을 클릭하면 안에 있는 함수(async function (e)부터 dataDiv.innerHTML = `<span>${e.message}</sapn>`;}});까지)가 실행된다.

이벤트의 상세 내용에 대해선 위에 있는 demo.js의 코멘트를 확인해보자.

개발자 도구의 Network 탭을 들어가보면 보이는 화면

개발자 도구가 열려 있는 상태라면 네트워크 요청이 기록되는데 새로고침을 해보면 어떤 기록들이 생성된다.

스티커가 위치한 부분이 기록들이다.

이 기록들 하나하나가 다 리퀘스트이다. 각 리퀘스트의 상태 코드(status), 타입(type), 어디서 리퀘스트를 보냈는지(Initiator), 사이즈(size), 걸린 시간(time) 등을 볼 수 있고, 마지막 waterfall은 리소스를 가져오는 과정과 타이밍을 그림으로 그린 것이다. 200ms 400ms 600ms 등 써 있는 중간 부분은 전체적인 waterfall을 보여주는 것이다.

type이 fetch라고 쓰여있는 리퀘스트를 선택해보면 waterfall이 조금씩 바뀌는것을 확인할 수 있다. 

그리고 컬럼 헤더에 마우스를 올려 우클릭을 해보면 다른 정보도 볼 수 있다. 리퀘스트 Method도 볼 수 있게 Method를 선택해보자.

메소드를 선택하면 메소드 칸이 추가된다.

이제 리퀘스트를 선택해보면 여러 탭을 클릭할 수 있다. 

Headers에서는 리퀘스트와 리스폰스의 헤더를 확인 할 수 있다.

그리고 Response는 리스폰스의 바디를 확인할 수 있는데, 

아래쪽에 라이언 스티커 옆에 있는 중괄호 아이콘

중괄호 아이콘을 클릭하면 압축된 결과와 예쁘게 출력된 결과를 확인할 수 있다.

그리고 Preview 탭은 리스폰스 내용의 미리보기를 보여준다. 지금처럼 JSON의 경우 큰 차이가 없지만 리스폰스 내용이 HTML인 경우 HTML에 대한 화면을 보여준다.

HTML에 대한 화면을 보여준다.

디버깅(debugging 컴퓨터 프로그램 개발 단계에서 발생하는 오류나 비정상적인 연산(버그)을 찾아내고 수정하는 작업 과정)을 하다보면 헤더가 제대로 설정되고 있는지, 예상된 리스폰스가 돌아오고 있는지 등을 확인해야 하는 경우가 많은데 그럴 때 Network 탭으로 리퀘스트, 리스폰스의 모든 정보를 볼 수 있기 때문에 아주 유용하다.

import { getColorSurvey, createColorSurvey } from './api.js';

const btn = document.querySelector('button');
const statusDiv = document.querySelector('div.status');
const dataDiv = document.querySelector('div.data');
const mbtiInput = document.querySelector('#mbti');
const colorCodeInput = document.querySelector('#colorCode');

btn.addEventListener('click', async function (e) {
    statusDiv.textContent = '로딩 중...';
    dataDiv.innerHTML = '';
    try { //POST 리퀘스트 보내기
        const surveyData = {
            mbti: mbtiInput.value, //Input 필드의 값을 받아서 surveyData 객체를 만들고
            colorCode: colorCodeInput.value, 
            password: '0000',
        };
        const survey = await createColorSurvey(surveyData); //createColorSurvey 함수의 아규먼트로 surveyData를 전달 
        statusDiv.textContent = '완료';
        dataDiv.innerHTML = `<span>${survey.mbti}</span><span>${survey.colorCode}</span>`;
    } catch (e) {
        statusDiv.textContent = '오류';
        dataDiv.innerHTML = `<span>${e.message}</span>`;
    }
});

이렇게 코드를 작성해보면, 개발자 창으로 가봤을 때 새로고침이 되면서 과거 기록이 삭제되어 있을것이다. 만약 기록을 지우지 않고 남기고 싶다면 preserve log를 선택하면 된다.

폼에 잘못된 mbti 정보를 입력하고 리퀘스트를 보내보자. 

preflight 라는 리퀘스트는 브라우저가 자동으로 보내는 건데 지금은 무시해도된다. 오류가 발생한 POST 리퀘스트를 클릭해보면 400 상태 코드가 돌아온걸 확인할 수 있고, payload 탭에서는 리퀘스트 바디를 확인할 수 있다. 리스폰스 바디는 그냥 문자열이다.

그럼 제대로 된 mbti를 입력하고 다시 리퀘스트를 보내보면 어떨까?

이번엔 리퀘스트가 성공적으로 처리됐다.
성공한 리퀘스트의 헤더, 페이로드, 리스폰스

여기에 자주 사용하는 기능 두가지가 더 있는데 

Filter 인풋창 옆으로 쭉 있는 항목들이 필터이다.

위에 있는 Filter를 이용해서 원하는 리퀘스트 타입만 볼 수가 있다. 예를 들어 fetch를 클릭하면 

이렇게 fetch 리퀘스트만 모아서 볼 수 있다. 원하는 리퀘스트를 찾을 때 아주 유용하다. 그리고 그 위에 있는 throttling 기능도 많이 사용하는데

이걸 클릭하면 3G처럼 느린 인터넷 속도, 아니면 아예 오프라인 상태를 흉내낼 수도 있다. 지금은 리퀘스트가 하도 빨리 처리되서 중간에 로딩되는 상태를 보기가 어려운데 여기서 slow 3G를 선택하면 

로딩 중...

중간에 로딩이 되는 상태를 확실하게 확인해 볼 수 있다.

<네트워크 기능 참조>