이번에 작업을 하는 중에 이벤트 게시판의 링크 기능에 대한 수정 사항이 발생했다. 지금 내가 개발하고 운영하고 있는 서비스의 경우 애플리케이션이기 때문에 일반 브라우저 환경의 웹과 다르다. 우리는 유니티 환경의 웹뷰를 사용하고 있기 때문에 그렇다. 그러다 보니 링크를 사용하는 경우에 앱의 웹뷰에서 곧장 그 링크로 접근해 버리기 때문에 기존의 우리 웹뷰 화면으로 돌아올 길이 없게 되었다.
그래서 결론적으로 새 창을 띄워 링크의 창이 종료될 때 원래 우리 화면으로 돌아오도록 구현해야 했다. 그런데 문제는 브라우저에서 사용하는 새 창을 띄우는 방식이 그 웹뷰에선 적용되지 않는다는 것이다. _black 옵션을 추가하거나 window.open을 이용해서 해봐도 새 창으로 화면을 열지 못했다.
링크를 클릭하는 이벤트를 단순히 url을 로딩하는 게 아니라 유니티와 미리 약속한 메시지를 유니티에게 던지는 이벤트가 필요했던 것이다. 그런데 또 생긴 다른 문제는 렌더링 돼야 하는 이벤트의 게시글이 api를 통해 응답받은 string 속성의 html 형식이라는 문제였다.
그때 사용한 방법이 바로 useEffect와 useRef이다.
import { useEffect, useRef } from 'react';
function MyComponent({ htmlData }) {
const contentRef = useRef<HTMLParagraphElement>(null);
useEffect(() => {
if (htmlData) {
const link = contentRef.current.querySelectorAll('a')
if (link) {
link.forEach((item: HTMLAnchorElement) => {
item.addEventListener('click', handleLinkClick)
})
}
return () => {
if (link) {
link.forEach((item: HTMLAnchorElement) => {
item.removeEventListener('click', handleLinkClick)
})
}
}
}
}, [htmlData])
return <div ref={contentRef} dangerouslySetInnerHTML={{ __html: htmlData }} />;
}
useEffect는 화면이 렌더링이 끝난 순간부터 작동하는 이펙트이기 때문에 데이터를 모두 렌더링한 후에 접근해서 처리를 할 수 있게 한다. 뿐만 아니라 useRef를 사용해서 내가 렌더링하는 html 데이터를 감싸는 엘리먼트를 ref를 통해 current를 가져올 수 있게 지정했다. 그리고 링크의 경우 a 엘리먼트를 사용하기 때문에 해당 엘리먼트를 찾는 querySelector를 다수의 엘리먼트가 올 수 있기 때문에 querySelectorAll을 활용했다.
나는 이렇게 드디어 엘리먼트에 접근할 수 있었고 addEventListener를 사용하여 그 엘리먼트의 특정 이벤트를 지정해 줬다. 물론 메모리 누수를 방지하기 위해 언마운트되는 순간 removeEventListener가 작동되어 이벤트가 삭제될 수 있도록 세팅했다.
그리고 마지막으로 handleLinkClick 함수를 아래와 같이 작성했다.
const handleLinkClick = (e: MouseEvent) => {
e.preventDefault();
const currentTarget = e.currentTarget as HTMLAnchorElement
const link = currentTarget.href
{ ... 유니티에 웹뷰가 새로 뜨도록 하는 메시지 던지기 ... }
}
이렇게 작성해 유니티에 메시지를 던져 원하는 웹뷰 처리를 가능하도록 했다. 그런데 a 엘리먼트의 default 이벤트가 이미 있기 때문에 e.preventDefault() 사용해서 이벤트를 막아줬다.
이렇게 해서 새 웹뷰를 띄워 원하는 링크 띄우고 이전 화면이 계속 살아있게 구현할 수 있었다. 나는 이번 기능을 고민하고 찾아보고 구현하면서 프론트 개발의 좀 더 깊은 면을 볼 수 있었다. 현재 내가 집중하고 있는 스택은 React인데, 결국 프론트 개발을 더 깊게 잘하기 위해서는 JavaScript가 아주 중요하다는 것을 느꼈다.
'React' 카테고리의 다른 글
HOC(Higher-Order Component) (0) | 2023.03.28 |
---|---|
React에서 html과 css 추출하기 (1) | 2023.03.24 |
Fragments (0) | 2023.03.23 |
Ref 전달하기 (0) | 2023.03.22 |
Error Boundary (0) | 2023.03.21 |