개요
React로 폼을 개발하다가 꽤나 당황스러운 버그가 나타났다. 새로고침(F5)을 누르면 분명 State는 초기화되는데, Input에는 이전에 입력했던 값이 그대로 남아있는 것이다. 더 황당한 건 입력 값은 보이는데 Preview 영역에는 아무것도 표시되지 않는다는 점이었다. 처음에는 '내가 State 관리를 잘못한 건가?' 싶어서 코드를 여러 번 확인했다. 하지만 크롬에서는 문제없이 잘 작동했다. 문제는 Firefox와 Firefox 기반 브라우저(Floorp, Librewolf 등)에서만 발생했다.
문제 상황
구체적인 상황은 이랬다. ▼
- 사용자가 폼에 데이터를 입력
- 입력한 데이터가 Preview 영역에 실시간으로 표시됨
- 새로고침(F5) 실행
- React State는 정상적으로 초기화됨
- 그런데 Input/Textarea에는 이전 값이 그대로 남아있음
- Preview는 비어있는데 Input에만 값이 있는 상태 발생
React의 단방향 데이터 흐름을 깨뜨리는 상황이었다. State는 비어있는데 UI는 채워져 있는 기묘한 상황이 연출됐다.
원인 분석
결론부터 말하자면, 이건 Firefox의 유저 친화적 기능 때문이었다. Firefox는 유저 경험 개선을 위해 폼에 입력한 데이터를 자동으로 캐싱한다. 그리고 페이지를 다시 로드할 때 이 캐싱된 값을 복원해주는 것이다.
보통은 편리한 기능이다. 실수로 새로고침을 눌러도 작성하던 내용이 날아가지 않으니까. 하지만 SPA(Single Page Application)에서는 이게 문제가 된다. React는 새로고침 시 State를 완전히 초기화하는데, Firefox는 DOM 레벨에서 입력 값을 복원하니 둘 사이에 불일치가 생기는 것이다.
참고로 Chrome이나 Safari는 이런 동작을 하지 않는다. (둘 다 이런 기능이 있는데 동작 안하는 건지, 아예 없는 건지는 추가적으로 확인을 해봐야 한다.) 그래서 Firefox에서만 이 문제가 발생한 것이다. 스택 오버플로우에서도 같은 문제로 고민하는 개발자들을 많이 볼 수 있었다. ▼
Firefox keeps form data on reload
I have a big problem with the functionality in Firefox that keeps data that the user have filled in on reload F5. If i use Ctrl+F5 the forms are cleared and this is great. My problem is that not al...
stackoverflow.com
해결 방법
해결책은 생각보다 간단했다. `autoComplete="off"` 속성을 추가하면 된다.
// ❌ Firefox에서 문제가 발생하는 코드
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
// ✅ 수정한 코드
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
autoComplete="off"
/>
`textarea`도 마찬가지다:
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
autoComplete="off"
/>
이렇게 하면 Firefox가 폼 데이터를 캐싱하지 않게 되고, 새로고침 시 Input도 깔끔하게 초기화된다.
적용 시 고려사항
autoComplete의 원래 목적
원래 autoComplete 속성은 브라우저의 자동완성 기능을 제어하기 위한 것이다. 이름, 이메일, 주소 같은 개인정보를 브라우저가 기억했다가 자동으로 채워주는 그 기능 말이다. 우리가 해결하려는 캐시 복원 문제와는 약간 다른 맥락이지만, Firefox에서는 `autoComplete="off"`가 캐시 복원도 함께 막아준다.
선택적 적용
모든 Input에 무조건 `autoComplete="off"`를 넣을 필요는 없다. 상황에 따라 판단하면 된다:
// 검색 폼 - autoComplete 유지하는 게 좋음
<input
type="text"
placeholder="검색어를 입력하세요"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
// 게시글 작성 폼 - autoComplete off 권장
<textarea
placeholder="내용을 입력하세요"
value={content}
onChange={(e) => setContent(e.target.value)}
autoComplete="off"
/>
// 로그인 폼 - 상황에 따라 다름
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
autoComplete="current-password" // 구체적인 타입 지정도 가능
/>
임시적으로 사용 가능한 대안: Ctrl + F5
사실 Firefox에서도 Ctrl + F5(강력 새로고침)를 누르면 캐시가 초기화되면서 폼도 깨끗하게 비워진다. 하지만 일반 유저에게 "Ctrl + F5를 눌러주세요"라고 할 수는 없기에, 코드 레벨에서 해결하는 게 맞다.
비슷한 문제들
이런 류의 브라우저별 차이는 생각보다 자주 마주치게 된다:
- Safari의 날짜 Input 포맷: Safari는 `input[type="date"]`의 날짜 포맷이 다른 브라우저와 다르다
- IE의 Input 이벤트: (이제는 역사 속으로 사라졌지만) IE는 oninput 이벤트 동작이 달랐다
- 모바일 브라우저의 Viewport: iOS Safari와 Android Chrome의 뷰포트 처리 방식이 미묘하게 다르다
이런 문제들을 겪을 때마다 느끼는 건, 크로스 브라우저 테스트의 중요성이다. 개발할 때 크롬만 보고 잘 되네~하고 넘어가면 나중에 Firefox 유저들한테 버그 리포트를 받게 된다. (파이어폭스 사용자라면 대부분 개발자들일거라 엄청난 버그 리포팅을 받을지도 모른다.)
마무리
Firefox의 폼 캐싱 기능은 분명 좋은 의도로 만들어진 것이다. 하지만 React 같은 현대적인 프레임워크와는 잘 맞지 않는 부분이 있다. 이럴 때는 `autoComplete="off"` 로 간단히 해결할 수 있다.
이 문제를 겪으면서 다시 한번 느낀 건, 웹 개발에서는 '내 로컬에서는 되는데?'가 통하지 않는다는 것이다. 다양한 브라우저, 다양한 환경에서 테스트하고, 예상치 못한 동작에 대비하는 것이 중요하다. 특히 Firefox는 시장 점유율이 작다고 무시할 게 아니라, 오히려 이런 엣지 케이스를 발견하는 데 유용한 테스트 환경이 될 수 있다.
앞으로는 폼을 만들 때 처음부터 `autoComplete` 속성을 의식적으로 설정하는 습관을 들여야겠다. 작은 속성 하나가 큰 버그를 예방할 수 있으니까.
'Develop > Web' 카테고리의 다른 글
| [Web] div 수프를 끓이지 말아야 하는 이유 (0) | 2025.11.02 |
|---|---|
| [React][Error] tailwind css 설치 오류 (4) | 2025.10.05 |
| [NextJs] 하이아크 홈페이지 모노레포 적용기 (0) | 2025.09.23 |
| [React] 웹 프로젝트에서의 클린아키텍쳐 (0) | 2025.09.10 |
| [Web][Issue] 이중 인코딩으로 인한 사진 누락 (0) | 2025.07.17 |