개발 공부한 것들/SeSSAC 웹 풀스텍 과정 회고록

[SeSSAC] 웹 풀스택 영등포 5기 과정_dynamic form

geograp 2023. 8. 19. 02:08

안녕하세요,,,

점점 메말라가고 있는 '전업 자녀'이자 '홈 프로텍터'입니다 ^_^

요새 진짜 너무 바빠가지고 ㅠㅡㅠ 속으로 엉엉 울면서 살고 있어요,,,,,,,,,

아무튼, 오늘 수업에서 다이나믹 폼에 대해 배웠는데 멘탈 다 나가고

바빠서 못했던 복습들을 어쨋든 해야겠다고 맘먹게 된 수업이었어요.

하루라도 빨리42과제 좀 밀어놓고 새싹에 집중해야할 때가 왔다는 걸 느꼇죠,,,

미래의 나 보고 있니?

 

< 동적 폼 전송 >

저번 시간에 배웠던 form 전송은 input이나 button의 타입이 submit인 것을 이용하여

전송 시 페이지 이동이 일어나는 것을 배웠죠.

 

그러나

비동기 방식(서버에 데이터를 보내고 응답을 기다리는 동안 다른 스레드 처리가 가능)을 통해

웹 문서가 정적으로 멈춰있는 것이 아니라 일부 내용만 실시간으로 반응하며 동적으로 변경되는 것

비동기 HTTP 통신이라고 새로 배웠습니다.

 

비동기 HTTP 통신에는 3가지 방법이 있습니다.

방법1. Ajax -  요즘에는 잘 사용 하지 않습니다.
방법2. Axios - 가독성과 유지보수성이 좋아서 잘 사용됩니다.
방법3. Fetch - 유연하여 최근 떠오르고 있는 방법입니다.

방법 1. Ajax

Asynchrounous JavaScript And XML

자바 스크립트를 이용하여 클라이언트와 서버 간에 데이터를 주고 받는 비동기 HTTP 통신

 

- GET 메서드로 요청 보내기

function ajaxGet(){
    console.log('ajaxGet 함수 호출!');
    const form = document.forms['register'];
            
    // 요청에 실어서 보낼 데이터 변수(서버에서 받은 정보)
       const data = {
           name: form.name.value,
           gender: form.gender.value,
       };
       
       // Ajax로 서버에 Get요청 보내기
       $.ajax({
            type: 'get', // 요청의 종류 (=form의 method 속성)
            url: '/ajax', // 요청의 경로 (=form의 action 속성)
            data: data, // 요청에 실어보낼 데이터(서버가 받게 될 데이터)
            success: function(data){
            // 요청이 성공적으로 수행되었을 때 실행할 함수
                console.log(data);
                resultBox.textContent = `Get/ ajax 요청 완료! ${data.name}님은 ${data.gender}이시죠?`;//jquery를 통해 div의 텍스트 바꿈
            },
        });
 }

복잡해 보이지만 사실 그냥 이 친구를 있는 그대로 존중해주는 태도를 가지면

마음이 좀 편합니다......

 

여기서 중요한 코드들을 한줄 한줄 뜯어 먹어 볼게요

const form = document.forms['register'];

form 이라는 변수에 dom으로 forms메서드를 이용하여

'register'라는 name을 가진 form태그를 가져와서 넣겠다는 의미입니다. 

여기 이 코드에는 안보이지만, 이 위에 많은 정보를 담고 있는 register라는 form이 있어요

 

const data = {
                name: form.name.value,
                gender: form.gender.value,
            };

data라는 객체에 name이라는 키 값을 가지고, 앞서 선언한 변수 form의 태그 중

name="name"인 태그의 value값을 가져오고

 

gender라는키 값을 가지고, 앞서 선언한 변수 form의 태그 중

name="gender"인 태그의 value값을 가져오겠다는 거예요!

 

 $.ajax({
          type: 'get', // 요청의 종류 (=form의 method 속성)
          url: '/ajax', // 요청의 경로 (=form의 action 속성)
          data: data, // 요청에 실어보낼 데이터(서버가 받게 될 데이터)
          success: function(data){
          // 요청이 성공적으로 수행되었을 때 실행할 함수
               console.log(data);
               resultBox.textContent = `Get/ ajax 요청 완료! ${data.name}님은 ${data.gender}이시죠?`;//jquery를 통해 div의 텍스트 바꿈
          },
});

이 코드를 통해 Ajax로 서버에 get 요청을 보낼 거예여.

$.ajax jQuery 라이브러리에서 제공하는 함수로, ajax요청을 보내고 응답을 처리하는 기능을 수행합니다.

$.ajax를 사용하면서 그 안에 들어갈 형식이 바로 type(필수), url(필수), data, success, error가 있습니다.

 


- POST 메서드로 요청 보내기

function ajaxPost(){
      console.log('ajaxPost 함수 호출!');

      const form = document.forms['register'];
      const data = {
            name: form.name.value,
            gender: form.gender.value,
      }
      $.ajax({
          type: 'post',
          url:'/ajax',
          data: data,
          success: function(data){
               console.log(data);
               resultBox.textContent = `POST/ ajax 요청 완료! ${data.name}님은 ${data.gender}이시죠?`;
          },
      });
}

앞서 GET메서드 활용법과 아주 크게 다르지 않습니다.

그저 $.ajax로 ajax를 활용해줄때 type설정을 get이 아니라 'post'로 적어주면 됩니다!


방법2. axios

Node.js와 브라우저를 위한 Promise API를 활용한다.

return이 Promise 객체로 온다!!!!!!

 

일단 axios를 활용하기 위해 모듈을 설치하거나 CDN을 불러와줘야합니다.

저는 헤더에 CDN을 불러와줬어요

 <!-- axios cdn -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

 

- GET 메서드로 요청 보내기

async function axiosGet() {
            console.log('axiosGet 함수 호출!');
            const form = document.forms['register'];
            const data = {
                name: form.name.value,
                gender: form.gender.value,
            };
            try{
            const response = await axios({
                method: 'get', // 요청 방식 (= form method 속성)
                url: '/axios', // 요청 경로 (= form action 속성)
                params: data, // 서버로 보낼 데이터 (query string)
            });
            const {name, gender} = response.data; // 객체 구조분해 할당
            resultBox.textContent = `GET /axios 요청 완료!! ${name}님은 ${gender}이시군요!`;
            } catch (error) {
                console.log('Error!', error);

            };               
        }

axios는 ajax보다 코드가 쫌 더 길어요, 암울합니다.

일단, axios요청의 결과는 Promise 객체로 리턴하므로 then, catch의 후속 메서드를 사용할 수도 있고,

async, await 메서드도 사용할 수 있습니다.

위의 코드는 async, await 매서드를 사용한 버전입니다. 

 

try{
     const response = await axios({
     method: 'get', // 요청 방식 (= form method 속성)
     url: '/axios', // 요청 경로 (= form action 속성)
     params: data, // 서버로 보낼 데이터 (query string)
});

 위에 변수 선언 부분을 건너뛰고 try부터 보자면 (try는 async,await 사용 시, try-catch구문으로 에러처리를 해줍니다)

response라는 변수에 axios로 받은 Promise를 넣을 겁니다.

어떤 Promise인지는 method, url, params를 통해 결정하게 됩니다. 

 

이 axiosGET()이라는 함수가 값을 불러오는 것에 성공해서 이 try구문을 넘어가면

response에 반환한 Promise를 담고 try 구문 다음에 있는 하기의 코드를 실행합니다.

const {name, gender} = response.data; // 객체 구조분해 할당
resultBox.textContent = `GET /axios 요청 완료!! ${name}님은 ${gender}이시군요!`;

저는 resultBox라는 곳에 저런 문구를 넣어서 출력하도록 하였습니다.

 

만약 axiosGET()함수가 값을 불러오는 것에 실패를 해서 catch 구문으로 넘어간다면

catch (error) {
     console.log('Error!', error);
     resultBox.textContent = `알 수 없는 오류 발생!`;
}

이렇게 에러처리를 하도록 해주었습니다 :)


 

- POST 메서드로 요청 보내기

async function axiosPost() {
       console.log('axiosPOST 함수 호출!');
       const form = document.forms['register'];
       const data = {
            name: form.name.value,
            gender: form.gender.value,
       };
       const response = await axios({
            method: 'post',
            url: '/axios',
            data: data,
       });
	   try {
          const {name, gender} = response.data; // 객체 구조분해 할당
           resultBox.textContent = `POST /axios 요청 완료!! ${name}님은 ${gender}이시군요!`;
       } catch (error) {
           console.log('Error!', error);
           resultBox.textContent = `알 수 없는 오류 발생!`;
       }
}

get과 다를바가 없는데, response에 담긴 method'post'라고 제시된 점이 다릅니다 :)

나머지는 똑같아요...

 


방법3. fetch

ES6부터 들어온 JavaScript 내장 라이브러리이며 axios처럼 Promise 기반입니다!

최신 기법이며 내장 라이브러리인 만큼 뭘 설치하고 불러올 필요가 없어 편리하지만

아직까진 axios의 기능을 따라오지 못하고 있다는데, 어쨋든 발전이 된다면 axios를 능가할 수 있을 것 같습니다.

 

- GET 메서드로 요청 보내기

function fetchGet (){
      console.log('fetchGet 함수 호출!');
      const form = document.forms['register'];
      // fetch는 get 방식이 기본으로 작동, 생략 가능
      fetch( `/fetch?name=${form.name.value}&gender=${form.gender.value}`, { method : 'get'}
      ).then(function (response) { // fetch도 promise로 반환
           console.log(response);
           return response.json();
            }).then(function(data) { // data = 직전 then 메서드의 return 값
                console.log(data);
                resultBox.textContent = `GET / fetch 요청 완료!! ${data.name}님은 ${data.gender}이시죠?`;
            });
        }

나름 그래도 axios보다 코드 길이 자체는 좀 짧아요, 근데 먼가 콜백 함수마냥 함수가 좀 들어가 있죠?

fetch함수도 Promise기반으로 작동되어서 then, catch 후속 메서드가 사용가능하기에

then,catch를 활용하였습니다.  (당연히 async await 도 사용 가능합니다!)

 

 fetch( `/fetch?name=${form.name.value}&gender=${form.gender.value}`, { method : 'get'}
 	).then(function (response) { // fetch도 promise로 반환
           console.log(response);
           return response.json();
           }).then(function(data) { // data = 직전 then 메서드의 return 값
                console.log(data);
                resultBox.textContent = `GET / fetch 요청 완료!! ${data.name}님은 ${data.gender}이시죠?`;
            });

처음 보시는 분들은 fetch내에 있는 `/fetch?name=${어쩌고 저쩌고}......` 이 부분을 좀 생소하게 여기실 수 있는데,

지금 현재 fetch는 뒤에 보면 get method로 요청을 보내고 있으니 직접 경로를 추가해 준 것입니다.

그래서 get방식으로 fetch를 쓰는 공식은 이러합니다.

fetch( url, option)

여기서 option은 {method: 'get'}을 의미하는데 get이 디폴트 값이니 생략이 가능합니다.

 여기서 .then으로 패치가 된 Promise를 function내 response 변수값으로 넣게 됩니다.

그리고 여기서 return할 때 이 Promise를 json형식으로 바꿔줘요

 

그리고 그 json으로 바뀐 값을 다음 then의 functiond의 data 변수값으로 넣습니다.

그리고 이제 그 data 변수를 자유롭게 활용이 가능합니다.

이 then을 두 번 사용하여 return 값으로 json을 파싱해주는 방법을 사용하지 않으면

async, await 를 사용하거나, response를 text로 파싱해주고 다시 json으로 파싱하는 일을 더 만드는(?) 방법이 있습니다.


- POST 메서드로 요청 보내기

위에 같은 부분은 떼고  밑에 fetch부분만 발췌했습니다.

fetch( '/fetch',
      { method: 'POST',
        headers: {
                    'Content-Type': 'application/json',
                },
        body: JSON. stringify(data),
      }).then((response)=> {
            console.log(response);
            return response.json();
      }).then((response) => {
            console.log(data);
            resultBox.textContent = `POST /fetch 요청 완료!! ${data.name}님은 ${data.gender}이시죠?`;
      });

 

fetch를 이용하여 post 요청을 날릴 때에는

method키를 post로 지정
headers 키를 JSON 포멧으로 사용 선언
body 키는 서버로 보낼 데이터

이 세가지 옵션을 지켜야 합니다.

fetch의 기본 틀 ( fetch( url, option) )은 똑같지만 option에 들어가는게 좀 많아요

 

headers가 나오는데 {}로 묶어서 Content-Type이 json형식이라는 것을 선언함으로서

요청의 본문이 json형식이라는 것을 알려줍니다.

 

그리고 body에 데이터를 넣게 되는데 이 데이터 역시 stringify를 사용하여 json으로 변환해주고 있습니다.


그래서 여기서 든 의문점.

 

axios와 fetch함수 둘다 Promise 기반으로 반환하고 활용하는데 왜 axios는 json변환을 안하고 fetch는 해야하는 걸까?

 

chat gpt의 답입니다.

 

fetch()와 JSON 변환:

fetch() 함수로부터 반환되는 응답 객체(Response 객체)는 .json() 메서드를 제공합니다. 이 메서드를 호출하면 응답 데이터를 JSON 형식으로 변환한 Promise가 반환됩니다. 이것은 응답 데이터를 텍스트에서 직접 JavaScript 객체로 변환하는 작업을 간소화하는 장점을 제공합니다.
이렇게 JSON으로 변환하는 것은 비동기 작업을 처리하는데 유용하며, 특히 클라이언트에서 서버로 요청하고 응답을 받아 사용하는 과정에서 매우 일반적입니다.

axios와 JSON 변환:

axios는 자체적으로 응답 데이터를 JSON 형식으로 변환합니다. 즉, axios로 HTTP 요청을 보내면 응답 데이터는 이미 JavaScript 객체로 변환된 상태로 제공됩니다. 따라서 .json() 메서드를 따로 호출할 필요가 없습니다.
axios는 내부적으로 응답 데이터를 JSON으로 변환하고, 변환된 데이터가 Promise로 감싸져서 반환됩니다.
요약하면, fetch()는 응답 데이터를 JSON 형식으로 변환하는 작업을 개발자에게 맡기고 있습니다. 반면에 axios는 이 작업을 내부적으로 처리하여 변환된 데이터를 반환합니다. 두 라이브러리는 비슷한 목표를 가지고 있지만, 이러한 차이점으로 인해 사용 패턴이 약간 다를 수 있습니다.