ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React / 에러 핸들링] react-helmet, react-snap 안될때 해결 방법
    React 2022. 3. 4. 23:54

    사이드 프로젝트를 진행하면서 링크 공유 기능을 구현할 일이 생겼습니다.

    이때 OG태그를 사용하면서 생긴 에러를 써보려 합니다.

     

    메타데이터

    메타데이터는 데이터를 설명하는 데이터입니다.

    그중에서도 OG 태그라는 것이 있는데 Facebook이 웹 사이트에 더 풍부한 메타데이터를 제공하기 위해 발명한 메타데이터 프로토콜입니다.

    메타데이터들을 사용한다면 검색엔진에게 더 많은 데이터를 제공하므로 좋습니다.

    뿐만 아니라 og태그를 사용하게 된다면 링크를 공유했을 때 사용자에게 더 좋은 정보를 보여줄 수 있습니다.

     

    CRA와 meta data의 문제

    프로젝트의 기술 스택은 cra였습니다.

    해야 하는 일은 og태그를 사용하여 동적으로 url에 해당하는 이미지 및 사진을 보여주어야 합니다.

    하지만 csr은 index.html이 하나입니다. 때문에 동적으로 meta 데이터를 생성할 수 없습니다.

    ssr을 하게 된다면 정적인 페이지를 서버 사이드에서 만들어진 상태이기 때문에 쉽게 meta 데이터들을 적용할 수 있습니다.

     

    react-helmet 적용하기

    react-helmet을 적용하게 된다면 동적으로 meta데이터를 적용할 수 있습니다.

    import React from "react";
    import {Helmet} from "react-helmet";
    
    class Application extends React.Component {
      render () {
        return (
            <div className="application">
                <Helmet>
                    <meta charSet="utf-8" />
                    <title>My Title</title>
                    <link rel="canonical" href="http://mysite.com/example" />
                </Helmet>
                ...
            </div>
        );
      }
    };

    다음과 같은 방식으로 아주 편하게 사용할 수 있습니다.

    사실 helmet만을 사용해서 og태그를 설정하여도 원하는 결과는 나오게 됩니다.

    하지만 이왕 Meta data를 적용한 김에 seo까지 신경 써보기로 마음먹게 되었습니다.

     

    react-snap 적용하기

    여전히 빌드를 하게 되면 html파일이 index.html 하나만 존재하는 것을 확인할 수 있습니다.

    즉, helmet으로 meta 데이터를 적용한다고 하더라도 server side에서는 하나의 html만이 존재한다는 뜻입니다.

    따라서 js를 읽기 힘들어하는 seo는 metadata를 읽을 수 없습니다. 이러한 것 들을 해결해 주는 것이 react-snap입니다.

    react-snap의 문서를 보게 된다면 Pre-renders a web app into static HTML라는 말을 볼 수 있습니다. 사용하는 방식은 문서를 보게 된다면 자세히 나와 있습니다.

     

    에러 상황

    하지만 여기서 문제가 나타나게 됩니다.

    아무리 하여도 하나의 index.html파일만 나타나게 되는 것입니다.

    저의 폴더 구조는 App.tsx에서 react-router로 라우팅 처리를 선언하는 방식으로 사용하였습니다.

    구글링을 계속해보았지만, 다 공식문서에 나와있는 방식대로 설명한 글이었습니다.

    따라서 어쩔 수 없이 react-snap을 직접 까 보게? 되었습니다.

    react-snap의 코드를 보면

    if (!options.publicPath.startsWith("/")) {
        options.publicPath = `/${options.publicPath}`;
      }
      options.publicPath = options.publicPath.replace(/\\/$/, "");
    
      options.include = options.include.map(
        include => options.publicPath + include
      );
      return options;
    

    이런 부분을 볼 수 있습니다.

    options의 include 프로퍼티를 돌면서 publicPath와 include url을 더해주는 부분입니다.

    옵션은 reactSnap이라는 프로퍼티를 package.json에 정의함으로써 수정할 수 있는데 이는 공식문서에 나와 있습니다.

    따라서 저는 제가 prerender 하기 위해 필요한 url을 package.json에 명시해 주었습니다.

    "reactSnap": {
        "include":["/","/details"]
      }
    

    react-snap을 사용하면서 빌드 시 html 파일이 여러 개 생기지 않으셨던 분들은

    react-snap의 공식문서에 나와있는 대로 설정한 다음 package.json에 별도의 url을 설정하신다면 잘 해결됩니다.

    어떤 경우 이런 문제가 생기는지 더 테스트해본 결과 app.tsx에서 link태그 또는 데이터가 있는 상태에서 react-router로 outlet 설정을 한 경우, app.tsx에서 있는 링크들은 여러 개의 html로 잘 빌드가 됩니다.

    하지만 app.tsx에서 라우팅을 정의한 경우 다음과 같은 에러가 발생하는 것 같습니다.

     

     

    참고 문서

    https://developer.mozilla.org/ko/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML

    https://www.npmjs.com/package/react-helmet

    https://github.com/stereobooster/react-snap

    댓글

Designed by Tistory.