팀 프로젝트를 하던 중, 팀원이 스쳐 지나가며 이런 질문을 던졌습니다.
“혹시 form을 꼭 쓰신 이유가 있을까요?”
순간 멈칫했습니다. 입력과 제출을 처리하는 방법은 form만 있는 게 아니니까요.
그렇습니다. onSubmit 이벤트를 활용한 form도 있고, 단순히 div와 버튼의 onClick핸들러로도 구현할 수 있습니다.
그럼, 왜 굳이 form을 쓸까요? 아니면 div로 충분할까요?
서로의 장,단점을 알아보고 언제 무엇을 사용하면 좋을 지 알아볼까요?
장점
- 웹 표준 요소: 입력값을 서버로 제출하기 위해 태생적으로 설계된 태그
- onSubmit 이벤트 지원: 엔터키 입력 시 자동으로 submit이 트리거되어 UX가 자연스러움
- 기본 접근성: 스크린 리더, 브라우저 기본 기능(자동 완성, validation)과 잘 맞음
- 브라우저 기본 기능 연계: required, type="email" 같은 속성을 통해 별도 자바스크립트 로직 없이도 유효성 검증 가능
단점
- 기본 동작 제어 필요: 페이지 새로고침이 발생하므로 preventDefault()를 써야 할 때가 많음
- SPA 환경에선 불필요하게 복잡할 수 있음: API로 데이터를 보내는 구조에서는 단순 div+버튼도 충분히 가능
div + 버튼: 가볍고 단순한 대안
장점
- 자유도 높음: form의 기본 동작을 신경 쓸 필요 없이 오로지 자바스크립트 이벤트로 제어
- SPA에 적합: React, Vue 같은 프레임워크에서는 API 호출 → 상태 업데이트로 끝내는 경우가 많아 간단히 처리 가능
- 의도 명확: “이건 그냥 UI + 이벤트 처리”라는 걸 코드에서 바로 파악 가능
단점
- 접근성 한계: 엔터키 제출 지원이 기본적으로 없음 → 직접 이벤트 처리 필요
- 브라우저 기본 기능 손실: 자동 완성, validation 같은 form의 내장 기능을 쓰려면 직접 구현해야 함
- 표준 위반 소지: 시맨틱하게 “데이터를 제출하는 역할”이라면 form이 더 알맞음
- 로그인, 회원가입, 검색창처럼 “실제로 제출”하는 맥락이 있을 때
- 접근성(Enter 키 제출, 자동완성, 브라우저 validation)을 신경 써야 할 때
- 웹 표준/시맨틱 마크업을 중요하게 고려할 때
div 추천 상황
- 단순히 입력값을 받아 로컬 상태로만 활용할 때
- 내부 관리용 입력 UI, 모달 입력창 등 “서버 전송”이 필요 없는 경우
- 빠르게 이벤트 처리만 하고 싶을 때
SPA 환경에서의 문제
SPA(React, Vue, Next.js app router 등)는 페이지 전체를 리로드하지 않고 API 통신(fetch/axios)으로 데이터만 주고받고, 상태만 갱신해요.
근데 form을 그대로 쓰면?
- 기본 submit 시 페이지 리로드가 발생 → SPA 흐름이 깨짐
- 그래서 매번 e.preventDefault()를 써서 리로드를 막고 → JS 코드로 fetch/axios를 호출해야 함
즉, form의 “원래 목적(페이지 이동)”을 매번 무력화하고 JS로 새 동작을 덮어써야 하니까 “복잡하다”는 표현을 쓰는 거예요.
반대로 div + 버튼
div와 버튼은 브라우저가 기본적으로 하는 동작이 없음 → 그냥 클릭 이벤트만 처리.
- onClick={() => fetch("/api/todos")}
이렇게 바로 API 호출만 하면 끝.
- 별도로 preventDefault 같은 걸 신경 쓸 필요가 없음
즉:
- form은 원래 동작을 “막고 + 다시 정의”해야 함
- div는 애초에 동작이 없어서 “내가 원하는 로직만 작성”하면 됨
그래서 SPA에서는 div+버튼이 더 단순해 보이는 거예요.
마무리
form과 div는 결국 “어떤 맥락에서 입력값을 처리할 것인가?“에 따라 선택지가 달라집니다.
- 시맨틱하고 접근성을 살리고 싶다면 form
- 가볍고 단순하게 처리하고 싶다면 div