들어가며
이 글을 읽고나면 next-intl로 들어오면 번역언어의 HTML를 파싱하여 랜더링할 수 있게 됩니다.
대상 독자는 리액트 프로젝트로 다국어를 지원하는 개발자, 블로그 서비스를 마크다운으로 관리하는 개발자입니다.
문제 인식
이번 분기에 만들고 있는 제품을 홍보 및 가이드하기 위해 블로그 기능을 추가하였다. 다만 현재 제품은 11개의 언어로 번역되어 있고, 각각의 번역 파일은 구글 시트로 관리하며 자동화스크립트에 의해 프론트엔드 개발자가 사용할수 있도록 locale 별 json으로 떨어진다.
그리고 내부적으로 next.js를 사용하고 있고 i18n 라이브러리는 next-intl 를 사용하고 있었다. 여기까지 문제될건 없었다. 그런데 갑자기 특정 문자열에서 에러가 발생하기 시작했다.
저기 보이는 "blog_best_tips.post_0008_body" 는 blog_best_tips 로케일문서의 8번 post의 body를 가져오는 것이었다.
다른 문자열 예를 들어 "iPhone으로 손쉽게 고품질 녹음을 할 수 있습니다"는 blog_best_tips.post_0008_title 인데 제대로 번역되어 받아오는 모습을 확인할 수 있었다.
body는 마크다운 문서다. 그리고 이를 ReactMarkdown를 하여 랜더링 해주고 있었다. 그런데 마크다운 문서에 iframe이 들어가면서부터 에러가 발생하기 시작했다.
그런데 이 문서를 작성하는 동료는 이미 온라인 마크다운 편집기로 테스트를 해서 가져온다. (그러니깐 테스트서버로 배포했지~~). 그런데 여기에서 문제가 발생했던 것이었다.
문제 해결
우선 우리팀 시니어 개발자 챗형한테 물어봤다.
일반적으로 가능하다고 한다. 즉 마크다운 랜더러들이 별도로 지원하는 기능이라는 것으로 생각할 수 있었다. 그다음 개발자의 영원한 동반자 구글링을 해보자.
아주 매력적인 질문이 있다. react-markdown으로 HTML을 랜더링하는 어떤 방법이든 있는지 묻는 나와 같은 고민을 한 개발자의 피눈물을 찾았다.
댓글을 보니 rehype-raw 이거 깔면 된다고 한다.
rehype-raw
rehype-raws는 Rehype의 플러그인 중 하나로, 마크다운에서 HTML을 파싱할 때 HTML 태그를 처리하기 위해 사용된다. 보통의 마크다운 파서는 HTML 태그를 일반 텍스트처럼 처리하거나 무시하는데 이때 rehype-raw를 사용하면 실제 HTML 요소로 변환할 수 있도록 해준다. 이제 한번 해보자.
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
interface MarkdownRendererProps {
children: string;
className?: string;
}
const MarkdownRenderer = ({ children, className }: MarkdownRendererProps) => {
return (
<>
<ReactMarkdown rehypePlugins={[rehypeRaw]} className={className}>
{children}
</ReactMarkdown>
</>
);
};
export default MarkdownRenderer;
결과는~~
실패~~ (같은 사진아니다. 다른사진이다)
하.. 나한테는 이게 해답이 아닌건가 싶을때.. 한가지 의문점이 또 발생한다.
next-intl의 html markup
현재 제품에서 사용하는 next-intl에서는 i18n된 문서를 사용하기 위해 여러가지 추가기능을 제공하는데 그 중에 markup 예시도 있었다.
그래서 이것이 문제일까 싶어서 여러옵션을 뒤져보다가 하나를 더 찾았다.
next-intl의 Raw messages
갓챠~ 원래라면 dangerouslySetInnerHTML를 사용하여 div에 직접 넣어야하는데 현재 markdown 랜더러를 사용하고 있기에 이 기능을 통해서 값을 전달해줘야한다.
dangerouslySetInnerHTML 대신에 기능 content를 바로 랜더링하면 아래와 같은 결과가 나온다.
그리고 이 결과를 마크다운 랜더러에 한번더 전달하면
아주 깔끔하게 잘 나온다. 그리고 문제가 됬던 iframe를 확인해보면
결과물이 잘 나온다.
만약 여기에서 rehypeRaw를 제거하면 어떻게 보일까?
이렇게 깨져서 보인다.
마무리
이번 글에서는 react-markdown 내부에서 html를 제대로 랜더링하는 방법에 대해 살펴보았다. 중간에 끼어서 힘들게 했던 next-intl의 옵션을 살펴보고 rehype-raw, next-intl의 콜라보를 통해 결과물을 완성할 수 있었다.
번외로 우리 팀이 만들고 있는 서비스를 한번 소개해보고자 한다.
끝.
'개발 > 리액트' 카테고리의 다른 글
많은 데이터를 보여주는 방법에 대하여 (Tanstack query,table,react-virtual) (1) | 2024.01.21 |
---|---|
[상태관리] Zustand 조금 더 편하게 쓰기 ( snippet ) (1) | 2023.07.10 |
[리액트] Devtool로 확인하고 성능개선하기 (0) | 2023.02.08 |
[상태관리] 내가 Zustand를 선택한 이유 (over the Recoil) (8) | 2023.01.24 |
[React] 우리서비스를 더 널리, SNS 공유하기 (Navigator.share) (2) | 2022.11.22 |
댓글