본문 바로가기
Recap/bookshelf

lighthouse 점수 올리기 (접근성+SEO 개선)

by yerin.dev 2024. 3. 7.

프로젝트 마무리 후 lighthouse를 돌렸다.

  • performance
  • accessibility
  • best practices
  • seo
    에 관한 점수를 확인할 수 있다. 번들 사이즈 최적화를 통해 퍼포먼스 점수는 올렸고 이제 접근성과 SEO를 개선할 차례!

 

 

접근성

접근성 관련해서 개선한 점은 개발 도중 잠시 잊고 있던 img 태그의 alt 어트리뷰트! 이미지가 표시되지 않는 경우를 위해서도 있지만, 시각적으로 장애를 가진 사람들을 위해서 스크린리더가 읽어줄 텍스트가 되어주기도 한다. 모든 img 태그에 alt text를 열심히 달아주었다.

 

 

SEO

SEO와 관련해서는 할 일들이 훨씬 많았다.
리액트는 SPA이기 때문에 SEO와 관련해서 취약하다. react-helmet-async를 통해서 개선했다. 리액트 헬멧은 리액트에서 html의 head를 동적으로 변경할 수 있게 도와주는 라이브러리다. 리액트는 하나의 html 파일을 가지기 때문에 페이지가 변경되어도 html은 그대로인데, 이를 동적으로 변경해주는 것이다. 이를 사용하여 페이지의 메타데이터, 제목, 설명 등을 동적으로 설정할 수 있다.

 

npm install react-helmet-async

 

// main.tsx
import { HelmetProvider } from "react-helmet-async";


ReactDOM.createRoot(document.getElementById("root")!).render(
      <HelmetProvider>
        <App />
      </HelmetProvider>
);

 

import React from 'react';
import { Helmet } from 'react-helmet-async';

const MyComponent = () => {
  return (
    <div>
      <Helmet>
        <title>페이지 제목</title>
        <meta name="description" content="페이지 설명" />
      </Helmet>
      {/* 나머지 컴포넌트 내용 */}
    </div>
  );
};

export default MyComponent;

 

 

 

이런 식으로 각 페이지에 넣어줄 수도 있고, 아니면 따로 컴포넌트로 분리할 수도 있다.

 

 

 

import { Helmet } from "react-helmet-async";

export function SEOMetaTags({ title, desc }: { title: string; desc: string }) {
  return (
    <Helmet>
          <title>{title}</title>
          <meta name="description" content={desc} />
         <meta name="keywords" content="keywords" />
        <meta property="og:title" content="Open Graph 제목" />
        <meta property="og:description" content="Open Graph 설명" />
        <meta property="og:image" content="이미지 URL" />
        <meta property="og:url" content="페이지 URL" />
        <meta property="og:type" content="website" />

        {/* Twitter Cards 메타 태그 */}
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:title" content="Twitter 카드 제목" />
        <meta name="twitter:description" content="Twitter 카드 설명" />
        <meta name="twitter:image" content="이미지 URL" />

          <link rel="canonical" href="https://bookshelf-bay.vercel.app/" />
    </Helmet>
  );
}

 

 

 

twitter cards는 트위터로 링크 공유시 뜨는 사진, 설명 등.
og(오픈 그래프)는 그외 다른 소셜 미디어에 공유할 때 보여지는 부분을 담당.
canonical은 검색엔진 로봇에게 어떤 url이 원본 url인지 알려주는 것이다.

 

 

 

이미지 pre-load

 

 

import { useEffect } from "react";

type BookCoverImgProps = {
  bookCover: string;
};

export default function BookCoverImg({ bookCover }: BookCoverImgProps) {
  useEffect(() => {
    // Preload the image
    const image = new Image();
    image.src = bookCover;
  }, [bookCover]);

  return (
    <img
      width={200}
      height={300}
      src={bookCover}
      alt="book cover image"
      className="rounded-lg max-w-[200px] mx-auto  mb-8 object-cover"
    />
  );
}

 

 

이미지 프리로드하기 위해서 이미지 컴포넌트를 따로 분리하고, useEffect를 사용해서 이미지 객체를 생성한다. 이 객체는 이미지를 미리 로드해놓는 데에 사용된다. 새로 생성한 이미지 객체에 prop으로 전달된 url을 설정하여 이미지를 미리 로드할 수 있다.


이미지 프리로드를 사용하면, 웹 페이지가 로드되는 동안 필요한 이미지를 미리 로드하여 사용자가 해당 이미지를 요청했을 때 즉시 사용할 수 있게 된다.