본문 바로가기
Issue

React) 자동 번역 기능 활성화 시 Failed to execute 'removeChild' on 'Node' 오류

by 박채니 2024. 11. 4.
SMALL

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.

# 상황

  • React 18
  • ChatGPT 채팅 웹사이트

Naver Whale에서 영어 → 한국어 자동 번역 기능을 키고

영어로 대화가 이루어진 A 채팅방 → B 채팅방 → A 채팅방 내용을 클릭 시 아래와 같은 오류가 발생했다.

🐛 오류 메세지

Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

💡 해결방안

채팅 메세지를 보여줄 때 react-markdown 패키지를 이용하였고, p 태그인 경우 아래와 같이 p 태그로 감싸 리턴해주었다.

p({ children }) {
    useEffect(() => {
        setIsCodeWriting(false);
    }, []);

    return (
        <p>{children}</p>
    );
},

 

아래와 같이 TextNode를 span 태그로 감싸주어 해결해주었다.

 

p({ children }) {
    useEffect(() => {
        setIsCodeWriting(false);
    }, []);

    // 기존에는 <p>{children}</p>로 메세지를 찍어주었는데, 이 경우 네이버웨일에서 자동번역을 켜고 번역할 내용이 있는 A 채팅방 -> B 채팅방 -> 다시 A 채팅방에 들어가면
    // Failed to execute 'removeChild' on 'Node' 오류가 발생하면서 흰 화면으로 아예 먹통이 됨
    // google translate가 작동하는 방식이 Element 내에 TextNode를 찾아서 font 태그로 변경해버리고 기존 TextNode는 없애버리는데, 다시 A 채팅방에서 이미 삭제해버린 TextNode를 찾아 removeChild를 하려고 하니까 발생하는 오류.
    // 따라서 TextNode를 span 태그로 감싸주어 React가 참조하는 Node가 font 태그로 대체되어도 DOM 트리에 남게해줘야 한다고 함(그래서 Element 내에 TextNode를 또 span으로 감싸주어 아래처럼 p 태그 내에 span 태그가 있음)
    // 참고사이트: https://github.com/facebook/react/issues/11538#issuecomment-390386520, https://martijnhols.nl/gists/everything-about-google-translate-crashing-react
    return (
        <p>
            <span>{children}</span>
        </p>
    );
},

🔥 원인

구글 자동 번역이 어떤 방식으로 작동하는지 먼저 파악할 필요가 있다.

 

[구글 자동 번역 작동 방식]

  1. TextNode를 찾는다
  2. 찾은 TextNode를 번역될 문장을 포함한 FontElement 로 대체한다.

예를 들어, <p>Hello</p>가 있다고 가정했을 때

  1. TextNode를 찾는다 TextNode: "Hello"
  2. 찾은 TextNode를 번역될 문장을 포함한 FontElement 로 대체한다. <p><font>안녕하세요</font></p>로 대체

위와 같은 과정을 거쳐서 번역된 문장이 보여지게 된다.

 

이 때, TextNode는 이미 지워져버렸기 때문에 마운트된 DOM에는 TextNode인 Hello가 없을 것이다.

따라서 이미 번역을 했던 페이지를 다시 로드할 경우, TextNode를 찾아서 remove를 해버리니까 removeChild를 할 수 없어요~ 라는 오류가 발생한다는 것!

 

이를 방지하기 위해 TextNode를 span 태그로 감싸주어 TextNode를 직접 삭제하지 못하도록 해준다.

 

span 태그로 감싼 TextNode를 쉽게 찾아주는 eslint-plugin-sayari 를 설치하여 처리해준다면 좀 더 수월할 것이다.

https://github.com/sayari-analytics/eslint-plugin-sayari

 

근데 정말 아이러니하게도.. Chrome에서는 해당 현상이 발생하지 않는다..😅

 

 

참고사이트 (⭐️ 아래 참조한 참고사이트를 정독한다면, 원인 파악 및 흐름을 이해할 수 있을 것이니 꼭! 정독해보길 추천한다.)

https://martijnhols.nl/gists/everything-about-google-translate-crashing-react

https://github.com/facebook/react/issues/11538#issuecomment-390386520

 

LIST