2026. 6. 30.
React 폼 제출 후 새로고침될 때, 기본 동작을 막는 기준
AI가 만든 React나 Next.js 폼에서 제출 버튼을 누를 때 화면이 새로고침된다면 onSubmit 위치, button type, preventDefault, async 처리, 콘솔과 네트워크를 순서대로 확인해야 합니다.

AI가 만든 문의 폼이나 회원가입 폼에서 제출 버튼을 눌렀는데 입력값이 사라지고 페이지가 다시 로드되는 일이 있습니다. 초보자는 이때 API 연결, 상태 관리, 라우팅을 한꺼번에 고치려 하지만, 실제 시작점은 더 작습니다. 폼의 기본 제출 동작이 취소됐는지부터 봐야 합니다.
브라우저의 HTML 폼은 기본적으로 제출 동작을 가집니다. React 공식 문서도 onSubmit 이벤트 핸들러에서 직접 데이터를 처리할 때 브라우저가 현재 URL로 폼을 보내고 페이지를 새로 고칠 수 있으므로 preventDefault()로 그 동작을 막는 예를 제공합니다. 오늘 목표는 새 폼을 다시 만드는 것이 아니라, 제출 흐름이 어디에서 페이지 이동으로 빠지는지 증거로 구분하는 것입니다.
onSubmit이 form에 붙었는지 먼저 확인합니다
먼저 버튼부터 보지 말고 <form> 태그를 봅니다. 폼 제출 처리는 보통 버튼의 onClick보다 폼의 onSubmit에서 관리하는 편이 안전합니다. 사용자가 버튼을 클릭할 수도 있고, 입력창에서 Enter를 누를 수도 있기 때문입니다.
확인할 코드는 이런 모양입니다.
function ContactForm() {
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
console.log("submit");
}
return (
<form onSubmit={handleSubmit}>
<input name="email" />
<textarea name="message" />
<button type="submit">제출</button>
</form>
);
}
AI가 만든 코드가 아래처럼 버튼 클릭에만 연결돼 있다면 Enter 제출이나 브라우저 기본 제출 흐름을 놓칠 수 있습니다.
<form>
<input name="email" />
<button onClick={handleSubmit}>제출</button>
</form>
이 단계에서 AI에게는 전체 컴포넌트 재작성보다 작은 질문을 줍니다.
React 폼 제출 시 화면이 새로고침됩니다.
전체 구조를 바꾸지 말고 form 태그에 onSubmit이 붙어 있는지, button onClick만 쓰고 있는지 먼저 확인해 주세요.
Enter 제출까지 포함해 최소 수정 코드를 제안해 주세요.
button type을 명시해 버튼 역할을 나눕니다
MDN의 <button> 문서는 버튼의 type 값이 submit, reset, button으로 나뉜다고 설명합니다. 폼 안의 버튼은 의도하지 않게 제출 버튼으로 동작할 수 있으므로, 역할을 코드에 직접 적는 편이 좋습니다.
제출 버튼은 이렇게 씁니다.
<button type="submit">제출</button>
폼 안에 미리보기, 모달 열기, 인증번호 전송, 주소 검색 같은 보조 버튼이 있다면 이렇게 씁니다.
<button type="button" onClick={openPreview}>
미리보기
</button>
여기서 핵심은 폼 안의 모든 버튼 역할을 눈으로 읽히게 만드는 것입니다. AI가 만든 화면에는 버튼이 여러 개 들어가면서 type이 빠지는 경우가 있습니다. 제출 버튼이 아닌데 제출이 일어나면, 사용자는 "왜 새로고침되지?"라고 느끼지만 실제 원인은 보조 버튼이 폼 제출을 건드린 것입니다.
커스텀 버튼에서 type이나 onClick이 사라지는 상황은 기본 버튼은 되는데 커스텀 Button만 안 될 때 확인할 prop 전달 경로와 함께 보면 원인을 더 빨리 좁힐 수 있습니다.
짧은 점검표는 아래처럼 씁니다.
| 버튼 역할 | 권장 type | 새로고침 의심 지점 |
|---|---|---|
| 최종 제출 | submit | onSubmit에서 처리되는지 확인 |
| 미리보기, 모달, 주소 검색 | button | 누르는 순간 폼 제출이 되는지 확인 |
| 입력 초기화 | reset | 실수로 데이터가 지워지는지 확인 |
preventDefault가 제출 처리 시작점에 있는지 봅니다
폼 제출을 자바스크립트로 처리하려면 event.preventDefault()가 빠지지 않아야 합니다. MDN은 preventDefault()가 이벤트의 기본 동작을 막는다고 설명합니다. 폼 제출에서는 이 한 줄이 브라우저 기본 제출 흐름과 React 처리 흐름을 가르는 기준이 됩니다.
초보자가 볼 코드는 복잡하지 않습니다.
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const email = String(formData.get("email") ?? "");
const message = String(formData.get("message") ?? "");
console.log({ email, message });
}
여기서 event.currentTarget은 이벤트가 연결된 form 요소를 가리킵니다. new FormData(event.currentTarget)는 폼 안의 입력값을 모으는 방식입니다. 이 예시는 서버 저장까지 끝내는 코드가 아니라, 새로고침을 막고 입력값을 읽는 최소 확인 코드입니다.
AI에게 수정 요청을 할 때는 아래처럼 제한합니다.
handleSubmit 함수에서 폼 제출 후 새로고침이 발생합니다.
event.preventDefault()가 빠졌는지, 너무 늦게 호출되는지 확인해 주세요.
먼저 입력값을 console.log로 확인하는 최소 코드만 제안해 주세요.
API 호출과 라우팅 변경은 다음 단계로 미뤄 주세요.
async 처리와 상태 변경 순서를 분리합니다
preventDefault()를 넣었는데도 화면이 바뀐다면 다음은 비동기 처리 순서입니다. API 요청 뒤에 router.push(), window.location.href, location.reload() 같은 코드가 들어가면 새로고침처럼 보일 수 있습니다. 이때는 브라우저 기본 동작 문제가 아니라 제출 성공 뒤 화면 이동 코드일 수 있습니다.
확인할 이름은 아래와 같습니다.
router.push
router.replace
window.location
location.reload
form.reset
setState 초기화
예를 들어 성공 뒤 폼을 비우는 코드는 새로고침이 아니지만, 사용자는 입력값이 사라져서 같은 문제로 느낄 수 있습니다.
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
setStatus("sending");
await fetch("/api/contact", {
method: "POST",
body: new FormData(event.currentTarget),
});
setStatus("sent");
}
이 상태에서 값이 사라진다면 새로고침이 아니라 성공 처리나 상태 초기화가 원인일 수 있습니다. 그래서 테스트할 때는 console.log("submit start"), console.log("submit done")처럼 두 줄을 넣어 흐름을 나눕니다.
문서 요청 없이 입력값만 사라진다면 React 입력값이 새로고침 뒤 사라질 때 state와 저장소를 나누는 순서처럼 상태 초기화와 저장 위치를 별도 문제로 확인합니다.
제출 버튼을 누른 뒤 화면이 바뀝니다.
브라우저 기본 새로고침인지, API 성공 후 라우팅인지, setState 초기화인지 구분해 주세요.
router.push, window.location, location.reload, form.reset 사용 여부를 먼저 찾아 주세요.
Next.js에서는 클라이언트 컴포넌트 경계도 확인합니다
Next.js App Router에서 클릭, 입력, 제출 같은 상호작용을 컴포넌트 안에서 처리하려면 클라이언트 컴포넌트 경계를 확인해야 합니다. nextjs.org의 Next.js 공식 문서는 'use client' 지시어가 클라이언트에서 렌더링되는 컴포넌트의 진입점을 선언한다고 설명합니다.
폼 제출 핸들러가 있는 파일은 보통 아래처럼 시작합니다.
"use client";
import { useState } from "react";
export function ContactForm() {
const [status, setStatus] = useState<"idle" | "sending" | "sent">("idle");
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
setStatus("sending");
setStatus("sent");
}
return (
<form onSubmit={handleSubmit}>
<input name="email" />
<button type="submit">제출</button>
<p>{status}</p>
</form>
);
}
다만 'use client'를 아무 파일에나 붙이는 것이 답은 아닙니다. 제출 핸들러와 상태가 들어간 작은 폼 컴포넌트에만 붙이고, 페이지 전체를 클라이언트로 바꾸지 않는 편이 수정 범위를 줄입니다. AI에게는 "이 파일 전체를 클라이언트로 바꿔라"가 아니라 "제출 핸들러가 있는 컴포넌트 경계만 확인해 달라"고 요청해야 합니다.
React의 action prop이나 Next.js Server Action으로 제출을 처리하는 폼은 경로가 다릅니다. 이 경우 브라우저 기본 동작을 무조건 끊는 대신, 폼이 onSubmit 이벤트 핸들러 방식인지 action 방식인지 먼저 확인합니다. 이 글의 preventDefault() 점검은 클라이언트 이벤트 핸들러가 제출을 직접 처리하는 폼을 기준으로 합니다.
콘솔과 네트워크로 실제 새로고침인지 확정합니다
마지막 확인은 감으로 판단하지 않습니다. 브라우저 개발자 도구에서 두 곳만 봅니다.
- Console 탭에서
submit start가 찍히는지 확인합니다. - Network 탭에서
fetch요청이 나가는지 확인합니다. - 페이지가 다시 로드되며 콘솔 로그가 사라지는지 봅니다.
- 주소창 URL이 바뀌는지 확인합니다.
- 입력값이 지워진 시점이 제출 직후인지, 성공 처리 뒤인지 나눕니다.
이 다섯 가지를 적으면 AI 질문이 짧아집니다.
React/Next.js 폼 제출 문제를 확인했습니다.
- form onSubmit: 있음
- button type: submit
- preventDefault: handleSubmit 첫 줄에 있음
- Console: submit start와 submit done 모두 찍힘
- Network: /api/contact 요청 200
- 그 뒤 입력값이 비워짐
새로고침 문제가 아니라 성공 후 상태 초기화인지 확인하고, 최소 수정만 제안해 주세요.
반대로 이렇게 적히면 원인이 다릅니다.
- form onSubmit: 없음
- button onClick만 있음
- preventDefault: 없음
- Console: 아무 로그도 안 찍힘
- Network: 문서 요청이 다시 발생
이 경우에는 API 코드보다 폼 제출 기본 동작부터 고칩니다. 오늘 남길 결과물은 완성된 서버 저장 기능이 아니라 폼 제출 흐름 5칸 진단표입니다.
1. onSubmit 위치:
2. button type:
3. preventDefault 위치:
4. 제출 후 실행되는 async 코드:
5. Console/Network에서 본 증거:
이 다섯 칸을 채운 뒤 AI에게 맡기면, 새 화면을 통째로 다시 만드는 답변보다 작은 수정이 나올 가능성이 높습니다. 제출 버튼이 새로고침을 만든다면 먼저 폼의 기본 동작을 끊고, 그 다음에 API 저장과 화면 이동을 붙입니다.
참고 출처
- Event: preventDefault() method (MDN)
- HTMLFormElement: submit event (MDN)
<button>HTML element (MDN)<form>(React)use clientdirective (Next.js)
이 글은 AI 코딩과 개발 학습의 일반 정보 제공 목적입니다. 도구, 모델, 커리큘럼, 요금은 버전과 시점에 따라 달라질 수 있으므로 실습이나 도입 전 공식 문서와 최신 릴리스 노트를 확인하세요.
다음으로 읽을 기사
같은 흐름으로 이어 읽기 좋은 기사만 추려 보여줍니다.
첫 번째 댓글을 남겨보세요
여러분의 생각이 다른 독자에게 도움이 됩니다.
댓글 0
이 글을 읽은 독자들의 생각을 나눠보세요.