[SeSAC x 코딩온] 웹 풀스택 회고 12 | 동적 폼 전송

HyeKong·2023년 8월 22일
0
post-thumbnail

일반 폼 전송 vs. 동적 폼 전송

일반 폼 전송

form 태그 안에 button type="submit"
제출 되었을 때 다른 페이지로 이동

동적 폼 전송

form 태그 필요 없음
form 태그 안에서 button type="button"
form 태그에 method, action 안 쓰고 name 씀
제출 되었을 때 현재 경로에서 요청에 대한 결과를 받음

주의할 점들

1. 전송할 데이터 선언 시

전역변수로 하면 안 되고 전송 시마다 새로 선언해야 함

const data = {
          //서버에 보낼 데이터
          name: form.name.value,
          gender: form.gender.value,
        };
const { name, gender } = data;

이유는?

처음엔 중복된 코드를 줄이고 싶고, 같은 input의 value들을 매번 사용하니 전역변수로서 data를 선언했었다.

const data = {
          //서버에 보낼 데이터
          name: form.name.value,
          gender: form.gender.value,
        };
        const { name, gender } = data;
        
ajaxGet(){...}
axiosGet(){...}
axiosPost(){...}

.
.
.

이런식으로,,
그러나 착각하고 있는 것이 있었다.
전역 변수로서 data를 선언하면, 함수 실행 전에 미리 data가 할당되기 때문에(input 입력 전에), input에 새로운 값을 입력해도 그 때마다 재할당이 되지 않아 같은 값만 나오는 것이었다.
아래 움짤처럼....

따라서 버튼 클릭으로 인해 함수가 매번 실행될 때마다 data를 새로 할당해 버튼을 클릭할 당시의 input.value를 읽어오도록 함수 내에서 data 할당 및 선언을 해주어야 한다.


1-1. 여기서 의문점이 생겼다.

그럼 전역변수로 data를 선언한 상태에서, button의 onclick이 아닌, input 기준으로 input의 value가 변경될 때마다 함수가 실행된다면 괜찮지 않을까?
input의 값 변경에 따라 이벤트를 발생시킬 수 있는 트리거를 찾아보았고, oninput
관련 링크를 찾을 수 있었다.

  • oninput

    oninput은 input의 값이 바뀔 때마다 함수를 호출하는 속성이다.

onchange와의 차이는 다음과 같다.

  • oninput은 컨텐츠가 변경된 직후에 이벤트가 발생하고, onchange는 요소가 focus를 잃었을 때 이벤트가 발생한다.

1-2. input에 oninput 속성 주기

data를 함수 밖에 전역 변수로 선언한 후, 기존 버튼에서 onclick 속성을 빼고, 이름을 입력하는 input에 같은 함수 내용을 이름만 다르게 선언해서 oninput을 줘보았다.

 <input
        type="text"
        id="name"
        name="name"
        required
        oninput="ajaxGetOnInput()"
      />

함수 내용은 체크를 위해 console 창에서 data를 실시간으로 확인할 수 있게 되어있다.

function ajaxGetOnInput() {
        const data = {
          //서버에 보낼 데이터
          name: form.name.value,
          gender: form.gender.value,
        };
        const { name, gender } = data;
        $.ajax({
          type: "get",
          url: "/ajax",
          data: data,
          success: function (data) {
            console.log(data);
            rst.innerText = `GET /ajax 요청 완료! ${name}님은 ${gender}이시죠?`;
          },
        });
      }

전역변수로 data를 선언한 상태에서는, 움짤과 같이 input에 값이 입력되어도 data에 값이 들어오지 않는 것을 볼 수 있다.

따라서 함수 내에 data를 선언하자마자 움짤과 같이 함수가 잘 실행되는 것을 볼 수 있었다. (radio button

1-2. onchange

onchange도 사용해보고 싶어서 radio button에 onchange 속성을 사용했다.

성별
      <input
        type="radio"
        name="gender"
        value="m"
        id="male"
        required
        onchange="ajaxGet()"
      />
      <label for="male"></label>
      <input
        type="radio"
        name="gender"
        value="F"
        id="female"
        onchange="ajaxGet()"
      />
      <label for="female"></label>

잘 동작하고, 특이한 점은 name이 같아서 라디오 버튼 하나에만 onchange를 줘도 될 줄 알았는데 input마다 줘야했다.
그리고 라디오 버튼도 input이므로 oninput 역시 잘 작동한다.

=> 하지만, input마다 onchange, oninput을 주는 것은 비효율적이니 역시 button에 onclick 하나만 주는 게 가장 좋은 것 같다..

2. form 유효성 검사 시

조건문 내 반환값 잘 생각해야 함

//폼 유효성 검사
          //- name input 입력값이 없다면, "이름을 입력해주세요"
          //- gender radio btn 선택하지 않았다면, "성별을 선택해주세요!"
          //- 둘 다 입력이 잘 됐다면 axios로 back에 요청 날리기
          //조건문 작성시 반환값 잘 생각하기
          if (!form.name.checkValidity()) {
            rst.innerText = "이름을 입력해주세요";
            rst.style.color = "salmon";
          } else if (!form.gender[0].checkValidity()) {
            rst.innerText = "성별을 선택해주세요!";
            rst.style.color = "tomato";
          } else if (
            form.name.checkValidity() & form.gender[0].checkValidity()
          ) {
            const response = await axios({
              method: "get",
              url: "/axios",
              params: data,
            });

3. Axios의 GET과 POST

GET은 params를, POST는 data로 써줌

4. Fetch의 GET과 POST

GET은 options를 생략하므로 url에 쿼리스트링을 작성해야 함

 function fetchGet() {
        console.log("fetchGet 함수 호출");
        const form = document.forms["register"];
    //fetch는 dafault로 get 방식 작동. options 생략 가능
    fetch(`/fetch?name=${form.name.value}&gender=${form.gender.value}`)
      .then(function (response) {
        console.log(response);
        return response.json();
        // JSON 형태로 응답 데이터 전달받음. 응답(response) 객체는 json() 메서드 제공
        // 응답(response) 객체로부터 JSON 포맷의 응답 전문을 JS obj로 변환
      })
      .then(function (response2) {
        //response2: 직전 then 메서드의 반환값
        console.log(response2); //js obj
        const { name, gender } = response2;
        rst.innerText = `GET /fetch 요청 완료! ${name}님은 ${gender}이시죠?`;
      });
  }
> POST는 option을 필수 작성해 req.body를 통해 data를 전송하므로 쿼리스트링 x

function fetchPost() {
const data = {
name: form.name.value,
gender: form.gender.value,
};
const { name, gender } = data;
//fetch를 통해 post 요청 시 option 객체 반드시 필요
//1. method 키 post 지정
//2. headers 키 JSON 포맷 사용 선언
//3. body 키 서버로 보낼 데이터
fetch("/fetch", {
method: "POST",
header: {
"Content-Type": "application/json",
},
body: JSON.stringify(data), //직렬화
//data: js obj
//JSON.stringify(data) : js obj => json
})
.then((response) => {
console.log(response);
return response.json(); //역직렬화
})
.then(function (response) {
console.log("data: ", data);
//console.log(response); //{}
rst.innerText = POST /fetch 요청 완료! ${name}님은 ${gender}이시죠?;
});
}


### 5. from name속성과 서버 url
> 같으면 안 됨

app.get("/pr_rgstr", (req, res) => {
//a 태그 이어주기
res.render("pr_rgstr");
});
app.get("/pr_rgstrResult", (req, res) => {
//form name과 서버의 url이 같으면 안 됨
console.log(req.query);
res.send(req.query);
});

0개의 댓글