한국어처럼 조합형 문자를 웹에서 입력할 때, 의도치 않게 중복 요청이 발생하는 경우가 자주 있다. 특히 React 환경에선 이 문제가 더 자주 보이는데, 원인과 해결 방법을 클라이언트, 훅, 서버 단에서 정리해봤다.
🧩 왜 한글 입력 시 중복 요청이 발생할까?
1. 조합형 언어의 특성
- 한글은 자음과 모음을 조합해 글자를 만든다. 예: ㄱ + ㅏ = 가
- IME(Input Method Editor)가 입력 중간 상태를 관리하면서 하나의 글자 입력에 여러 이벤트가 발생함
- 영어는 키보드를 누르면 바로 글자가 입력되지만, 한글은 조합 과정이 있어 조합 시작 → 변경 → 완료 등의 중간 단계를 거침
2. React의 이벤트 처리 방식
- React는 입력 이벤트를 상태 변화로 감지하고 리렌더링함
- 한글 입력 중간 상태에서도 이벤트가 발생해 의도치 않게 여러 번 렌더링 또는 요청이 발생할 수 있음
- 특히 Enter 키 입력과 한글 조합 완료 시점이 겹치면 중복 요청이 일어나는 현상이 자주 발생
🛡 중복 요청을 막는 방법
1. 클라이언트에서 방어 (메시지 전송, 검색 등)
const isSubmittingRef = useRef(false);
const handleSubmit = async () => {
if (isSubmittingRef.current) return;
isSubmittingRef.current = true;
await sendMessage();
setTimeout(() => {
isSubmittingRef.current = false;
}, 500);
};
- useRef로 요청 중 여부를 추적해 중복 요청 방지
- 빈 메시지는 아예 요청 자체를 막음
- 500ms 정도의 타임아웃으로 연속 요청 억제
2. useChat 훅에서 개선
- 최근 1초 이내에 동일한 메시지 전송 차단
- Content-Type을 application/json; charset=UTF-8로 설정해 한글 인코딩 문제 방지
- 전송 상태를 여러 ref로 분리 관리해 안정성 확보
- 디버깅을 위한 로그 추가로 문제 추적 용이
const existingMessage = chat.messages.find(
msg => msg.isUser &&
msg.message === message &&
Date.now() - new Date(msg.createdAt).getTime() < 1000
);
또한 나는 MSW를 사용하고 있어서, 핸들러(Mock Server)까지 개선해 주었다.
- 중복 메시지 감지 로직 추가
- 동일한 내용이 1초 이내에 들어오면 기존 응답을 재사용
if (existingMessage && existingMessage.modelReply) {
console.log('Detected duplicate message request, returning existing message:', existingMessage.message_id);
return HttpResponse.json({
user_message: existingMessage,
model_reply: existingMessage.modelReply
});
}
사용자의 연속적인 입력 중 마지막 입력 이후 일정 시간(예: 500ms) 동안 아무 이벤트가 없을 때만 요청을 보내는 방식으로
Debounce개념으로 처리해주었다. (마지막 입력 이후 일정 시간 대기 후 요청 허용)
한글 입력 중 중복 요청 방지엔 debounce 방식이 더 자연스럽고 적절하다.
throttle은 실시간 제어나 주기적 업데이트 등에 더 적합하다.
한글 입력 시 발생하는 중복 요청 이슈는 IME의 이벤트 처리 방식과 React의 상태 관리 방식 사이의 미묘한 차이에서 비롯된다. 조합형 언어의 특성을 감안하지 않으면 중복 요청, 중복 렌더링, 이상 동작이 발생할 수밖에 없다.
'웹' 카테고리의 다른 글
Google 소셜 로그인 뿌시기 (0) | 2025.06.10 |
---|---|
이미지 파일 관리시 메모리 피크 제어 (2) | 2025.02.17 |
Indexed DB 란??? [Chrome Extension을 개발하며] (0) | 2025.01.09 |
Enum을 사용하면 안되는 이유 (0) | 2024.09.02 |
Github Action build error 해결 (0) | 2024.07.24 |