HTML-CSS

Form 태그의 유용한 기능들

GoJay 2024. 11. 10. 12:30

form 태그에 이는 여러 기능들을 찾아보면서 사용해 봤다. 사용하면서 유용하다고 생각하게 된 몇 가지 기능들이 있어 내용 정리해 둔다.

reset()

로그인, 회원가입처럼 하나의 form 태그 안에 여러 input 창들이 있을 경우 submit 이벤트 후 창을 초기화하기 위해 모든 input 창들을 하나씩 선택해 ''으로 초기화해줘야 한다(form 태그의 기본 동작은 input에 들어온 값들을 바로 비워주는 것이지만, 로직 처리를 위해 e.preventDefault()를 사용한 상황을 가정한다).

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>example</title>
    </head>
    <body>
        <form id="form">
            <input class="input" type="text" />
            <input class="input" type="text" />
            <input class="input" type="text" />
            <button id="button" type="submit">submit</button>
        </form>
        <script>
            const $form = document.getElementById('form');

            $form.addEventListener('submit', (e) => {
                e.preventDefault();
                const inputs = document.querySelectorAll('.input');
                inputs.forEach((input) => {
                    input.value = '';
                });
            });
        </script>
    </body>
</html>

위의 예제에서 form 태그가 속성으로 가지고 있는 reset 메서드를 사용하면 손쉽게 input 창에 있던 값들을 초기화할 수 있다. 코드가 한결 간결해졌다.

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>example</title>
    </head>
    <body>
        <form id="form">
            <input class="input" type="text" />
            <input class="input" type="text" />
            <input class="input" type="text" />
            <button id="button" type="submit">submit</button>
        </form>
        <script>
            const $form = document.getElementById('form');

            $form.addEventListener('submit', (e) => {
                e.preventDefault();
                $form.reset(); // input 창들을 리셋
            });
        </script>
    </body>
</html>

action 속성

form 태그는 결과로 들어온 값을 원하는 api에 요청으로 보낼 수 있는 action 속성을 갖고 있다. 활용법은 아래와 같다.

<form id="form" action="${url}" method="${http method(e.g. get, post)}">
    <input class="input" type="text" name="name" />
    <input class="input" type="text" name="email" />
    <input class="input" type="text" name="password" />
    <button id="button" type="submit">submit</button>
</form>

최근엔 Fetch API나 axios 라이브러리 등으로 인해 자바스크립트로 요청을 보내는 것이 수월해져서 action 속성을 잘 사용하지 않는다고 한다. 대신, action 요청을 보낼 때 자동으로 생성되는 FormData 객체는 잘 알아두면 다양한 방식으로 활용할 수 있다.

FormData 객체

HTTP 요청을 보낼 때 body에 어떠한 값을 담아서 보내고 싶으면 직렬화(Serialization)가 필요하다. 흔히 JSON.stringify를 많이 사용한다. form 태그의 결과를 요청에 담아 보낼 때에도 마찬가지인데, form은 기본적으로 api 요청 시 보낼 결과 데이터를 직렬화한 값을 가질 수 있다. 바로 FormData 객체다.

action 속성을 사용하면 별도 처리 없이 form이 알아서 FormData 객체를 생성해 주지만, 임의로 값을 생성하기 위해선 생성자 함수 FormData를 사용해야 한다.

$form.addEventListener('submit', (e) => {
    e.preventDefault();
      const formData = new FormData(e.target) // FormData 생성자 함수로 결과 객체 생성
    $form.reset(); // input 창들을 리셋
});

FormData 생성자 함수를 console.dir로 콘솔에 찍어보면 아래와 같은 다양한 속성들을 지원하는 것이 확인된다.

그중 몇 가지만 살펴보겠다.

먼저, get 메서드를 사용하면 input 태그에 있는 값을 손쉽게 가져올 수 있다. get 메서드의 인자로는 input 태그에 정의한 name 어트리뷰트의 값을 전달하고, 결과로는 전달한 값을 name의 어트리뷰트로 갖는 input 태그에 입력된 값이 반환된다.

formData.get('name') // name="name"으로 설정된 input창의 값을 반환

만약에 같은 name 어트리뷰트 값을 가지는 input 태그가 여러 개라면 getAll 메서드로 여러 input창의 값을 한 번에 가져올 수 있다. 결과는 배열로 반환된다.

다음, get과 유사하게 keysvalues 메서드가 있다. keyinputname 지정된 값이, value에는 해당 input 태그에 입력된 값이 전달된다.

객체의 생성자 함수 Object에서 keyvalue를 가져오는 메서드와 이름이 동일하다. 유사하게, 해당 값을 아래와 같이 접근해서 사용하는 것이 가능하다.

for (let key of formData.keys()) {
  console.log(`key: ${key}`);
}

for (let value of formData.values()) {
  console.log(`value: ${value}`);
}

아래와 같은 사용도 가능하다(참고로, FormData 객체는 [key, value] 쌍을 반환하는 entries 메서드도 제공하지만, formData에 바로 [key, value]와 같이 배열 구조 분해 할당으로 값을 가져올 수도 있다).

for (let [key, value] of formData) {
  console.log(`key: ${key}, value: ${value}`)
}

해당 메서드들을 사용하면 form 태그 안에 있는 여러 input 태그들에 입력된 값을 손쉽게 가져올 수 있다.

이외에도 append(중복 name 이름 포함), set(중복 name 이름 미포함), delete(key-value 쌍 삭제) 등 form 태그 내부에 있는 input 태그의 결과를 처리하기 위한 다양한 메서드들이 제공된다.

결론

회원가입 UI를 구현하면서 총 4개의 input 태그에 있는 값을 가져오려고 4개의 input 창을 querySelector로 전부 다 직접 가져오는 코드를 썼었다. 당연히 같은 기능의 코드를 여러 번 반복해서 작성해야 했기 때문에 코드가 지저분해지는 문제가 있었다. 그러다 FormData 객체에 대해 알게 되었고, 훨씬 더 간결하게 코드를 처리할 수 있었다. 역시 사람들이 느끼는 불편은 비슷하고, 그에 대한 대응이 웬만한 건 다 이미 존재하는구나 싶었다.

form 태그에는 이외에도 다양한 기능이나 알아야 할 것들이 더 있다. 앞으로 더 공부해 가면서 하나씩 알아가고 잘 활용해 봐야겠다.