본문으로 건너뛰기
개발 머꼬
개발 노트HTML
hohyeon.dev15

폼 안의 버튼을 눌렀더니 페이지가 새로고침된 이유

  • #Engineering Note
  • #Forms
  • #HTML

문제 발생

폼 안에 "이미지 추가" 버튼을 넣었는데, 누를 때마다 페이지가 새로고침되면서 지금까지 입력한 내용이 전부 사라졌습니다. 핸들러에는 제출 코드가 한 줄도 없었습니다.

<form action="/posts" method="post">
  <input name="title" />
  <button onclick="addImage()">이미지 추가</button>   <!-- 폼이 제출된다 -->
  <button>저장</button>
</form>

원인 분석

<button>type 기본값은 submit 입니다. <form> 안에 있거나 폼에 연결된 버튼에서 type을 적지 않으면(또는 빈 값·잘못된 값을 적으면) 제출 버튼이 됩니다.

그래서 "이미지 추가" 버튼은 클릭되는 순간 폼을 제출하고, 브라우저는 응답을 받아 페이지를 새로 그립니다. 입력 중이던 상태는 그 과정에서 사라집니다. MDN도 이 점을 경고합니다 — 제출 목적이 아닌 버튼에 type="button"을 지정하지 않으면 폼 데이터를 제출하려 시도하고 (존재하지 않는) 응답을 불러오면서 현재 문서 상태를 망가뜨릴 수 있습니다.

type의 세 값은 이렇습니다.

동작
submit폼을 제출한다 (폼에 연결된 버튼의 기본값)
reset모든 컨트롤을 초기값으로 되돌린다
button기본 동작 없음. 스크립트로만 반응한다

해결 방안

  1. 제출이 아닌 모든 버튼에 type="button"을 명시합니다. 예외 없이 적는 규칙으로 두는 편이 안전합니다 — 나중에 그 버튼이 폼 안으로 들어가도 동작이 바뀌지 않습니다.
<button type="button" onclick="addImage()">이미지 추가</button>
<button type="submit">저장</button>
  1. preventDefault()로 막지 않습니다. 동작하긴 하지만 원인이 아니라 증상을 가리는 방식입니다. 핸들러를 지우거나 다른 경로로 실행되면 다시 제출됩니다.
  2. React·Vue에서도 똑같습니다. JSX의 <button onClick={...}>도 폼 안에 있으면 제출됩니다. 이 저장소의 글쓰기 화면에서 서식 버튼과 취소 버튼에 전부 type="button"을 붙인 이유입니다.
  3. type="reset"은 거의 쓰지 않습니다. 사용자가 저장 버튼과 헷갈려 누르면 입력한 내용이 전부 사라집니다. MDN도 사용자를 짜증나게 하는 경향이 있다고 적어 둡니다.
  4. <a>를 버튼처럼 쓰지 않습니다. 반대 방향의 실수입니다 — 링크는 Enter로, 버튼은 Enter와 Space로 활성화되고 스크린리더가 읽는 역할도 다릅니다. 이동이면 <a>, 동작이면 <button>입니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.