한글이 분해된다.
crdt 를 연동한뒤에 발생하는 문제이다.
이유는 block에 입력을 할때마다, crdt 통신이 일어난다. 즉, ㅎ
,ㅏ
,ㄴ
을 각각의 char로 인식해서 소켓연결이 되는거다.
sendCharDeleteOperation, sendCharInsertOperation가 char 단위로 이루어진다.
그렇다면, 먼저 여기서 isComposing 상태일때 소켓으로 insert되는걸 막아버리자.
그렇다면 어디서 소켓 insert를 처리해줘야할까? 이는 onCompositionEnd 를 이용하면 된다.
<div
ref={blockRef}
onKeyDown={onKeyDown}
onInput={handleInput}
onCompositionEnd={(e) => onCompositionEnd(block, e)} // ✅ 한글 처리를 위한 핸들러 등록
onClick={(e) => onClick(block.id, e)}
contentEditable
suppressContentEditableWarning
className={textContainerStyle({
type: block.type,
})}
onCompositionEnd은 기본으로 부착된 리스너로, 조합문자의 조합이 완료된후에 호출된다.
안녕하세요.
를 입력하고, 각각의 문자 길이를 출력해봤다. 예상되는것은 안
, 녕
, 하
, 세
, 요
가 조합문자로 출력되는것이다.
const handleCompositionEnd = (block: CRDTBlock, e: React.CompositionEvent<HTMLDivElement>) => {
const event = e.nativeEvent as CompositionEvent;
console.log("composition end", event.data, event.data.length);
}
그런데 결과에서는 .
까지 조합문자로써 들어가버린다. .
뿐만 아니라 ,
`` (공백)도 조합문자로 들어간다. 영어의 경우에는 조합문자가 아니기에 들어가지 않는다.
그래서 처리를 해줄때, 조합문자 char 1개만 처리하는게 아니라, 뒤에 따라올 문자도 같이 처리해줘야한다. 이는 반복문으로 돌렸다. 반복이지만, 사실 2개의 아이템만 순회할 것이다.
const handleCompositionEnd = (block: CRDTBlock, e: React.CompositionEvent<HTMLDivElement>) => {
const event = e.nativeEvent as CompositionEvent;
const characters = [...event.data];
const selection = window.getSelection();
const caretPosition = selection?.focusOffset || 0;
const startPosition = caretPosition - characters.length;
characters.forEach((char, index) => {
const insertPosition = startPosition + index;
const charNode = block.crdt.localInsert(insertPosition, char, block.id, pageId);
sendCharInsertOperation({
node: charNode.node,
blockId: block.id,
pageId,
});
});
block.crdt.currentCaret = caretPosition;
};