[NextJs 지도 개발 #5] SEO성능 개발하기

김유진·2023년 4월 24일
0

Nextjs

목록 보기
8/9

lighthouse를 통하여 현재 완성된 지도 앱의 성능을 살펴보자.
개발환경에서는 성능 측정이 다른 결과를 낼 수 있으므로
yarn build를 통하여 빌드를 수행한 이후에 prod 환경으로 접근해서 확인해보자.

성능에서는 좋은 점수를 얻었지만, 검색엔진 최적화는 그다지 좋은 점수를 받지 못하였다. SEO 관련된 코드를 개선해서 좋은 점수를 얻을 수 있도록 리팩토링을 진행해보자.

1. 성능 개선하기

현재 Largest Contentful Paint에서 시간이 오래 걸린다. 이 부분을 개선해 보도록 하자.

Warning 처리하기

sizes

현재 지도에서 마커를 클릭하면 이미지 로드에 대한 경고 메세지가 뜬다.
경고 메세지에서 의미하는 것은 다음과 같다.
fill 속성을 사용하면서 size를 지정하지 않았다는 경고 메시지이다.
size와 관련된 next의 공식문서를 읽어보면 아래와 같은 문구가 있다.

A string that provides information about how wide the image will be at different breakpoints. The value of sizes will greatly affect performance for images using fill or which are styled to have a responsive size.

중단점마다 size를 결정해주는 것은 성능에 매우 큰 영향을 미친다. 만약 fill만을 사용하는 데에는 사이즈를 최적화된 것으로 맞추어 주는 데 있어서 오랜 시간이 걸린다는 것이다.

지도 서비스에서 최대로 가져오고 싶은 이미지의 너비는 120px이니, 이미지를 불러오는 곳에 해당 props를 추가하여 Warning 메시지를 없애 보도록 하자.

 <Image
  src={image}
  alt=""
  fill
  style={{ objectFit: 'cover' }}
  sizes="120px" //새롭게 추가
  placeholder="blur"
  blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mO0WhFsDwADzwF2mLYSJgAAAABJRU5ErkJggg=="
  priority
/>

그럼 이제 콘솔에 Warning이 사라지며, 불러오는 이미지에 대한 용량이 작아진다. 기존에 이미지의 크기를 정해 주지 않았기 때문에 네이버 서버에서 가로 길이가 1200px인 큰 이미지를 가지고 오고 있었는데, 120px이라고 정해 준 덕분에 380px정도밖에 안되는 작은 이미지를 사용하게 되었기 때문에 최적화가 되었다고 볼 수 있는 것이다.

priority

priority 속성은 간단히 말하면 이미지를 불러오는 데 있어서 높은 우선순위를 부여한다는 것이다.
만약 이미지가 Largest Contentful Paint(LCP)라고 판단될 경우에는 priority 속성을 부여하는 것이 좋다.

2. 접근성 개선하기

맥과 윈도우 모두 스크린 리더라는 기능을 제공한다.
맥의 경우에는 command + F5 를 통하여 실행할 수 있다.
현재 만든 페이지는 보이스오버 기능을 사용하게 되면 알아들을 수 없는 배너, 링크 등의 단어를 이야기한다. 접근성을 높이기 위하여 보이스오버 기능을 사용하였을 때에도 전달하고자 하는 의미가 잘 전해지도록 특정 네이밍을 정해 주도록 하자.

const HeaderComponent = ({onClickLogo, rightElements}: Props) => {
  return (
    <header className={styles.header}>
      <div className={styles.flexItem}>
        <Link 
          href = "/" 
          className =  {styles.box} 
          onClick = {onClickLogo}
          aria-label = '홈으로 이동'
        >
            <Image src = "/inflearn.png" width ={110} height = {20} alt="인프런 로고"/>   
        </Link> 
      </div>
      {rightElements && <div className = {styles.flexItem}>{rightElements}</div>}
    </header>
  );
};

aria-label이라는 속성을 이용하여 네이밍을 정해줄 수 있는 것이다.

 <div className={styles.header}>
      <button
        className={`${styles.arrowButton} ${expanded ? styles.expanded : ''}`}
        onClick={onClickArrow}
        disabled={!currentStore}
        aria-label={expanded ? '매장 정보 접기' : '매장 정보 펼치기'}
      >
...

이렇게 각각의 라벨을 개선하여 주면 접근성이 개선된 것을 알 수 있다.

3. SEO 개선하기

이 두가지를 개선해보자.

문서에 title 및 meta 요소가 없음

구글을 검색하면 나오는 검색 결과에 표시한 것이 바로 title이고, 그에 대한 설명이 description이다.
NextJS에서 이것을 작성하는 것을 _document에 작성하는 것이다. 이에 대한 자세한 설명은 공식문서에서 확인할 수 있다. 전역적인 html 문서에 대하여 수정해야 할 때 사용할 수 있다.

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <title>Next.js지도</title>
        <meta name = 'description' content = 'Next.js 지도입니다.'/>
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

이렇게 title요소와 설명요소를 추가해보자.

이렇게 html요소에 title과 설명요소가 추가된 것을 볼 수 있다. 하지만 페이지마다 title 요소가 바뀔 수 있는데, 전역적으로 Next.js지도라고 하나의 Title을 결정해버렸기 때문에 eslint 에러가 뜬다. 이 부분을 수정해보자.
title은 각각의 페이지마다 들어가서 next/head를 이용하여 개별로 작성하여 주는 것이 더욱 좋다.

const Home: NextPage<Props> = ({stores}) => {
  const { initializeStores } = useStores();

  useEffect(() => {
    initializeStores(stores);
  }, [initializeStores, stores]);

  return (
    <Fragment>
      <Head>
        <title>Next.js 맛집 지도</title>
      </Head>
      <Header/>
      <main style ={{ position : 'relative', width :'100%', height: '100%', overflow:'hidden'}}>
            <MapSection/>
            <DetailSection/>
      </main>
    </Fragment>
  )
}

하지만 이렇게 일일이 작성하게 되면 오타의 가능성도 높아지고 중복되는 코드가 많아서 복잡해진다.
이럴때는 Meta 태그를 관리할 수 있는 라이브러리의 도움을 받자!

next-seo 이용하기

yarn add next-seo

위의 명령어로 라이브러리를 설치하여 준다. 그리고 아래와 같이 작성해보자.

const Home: NextPage<Props> = ({stores}) => {
  const { initializeStores } = useStores();

  useEffect(() => {
    initializeStores(stores); 
  }, [initializeStores, stores]);

  return (
    <Fragment>
      <NextSeo //NextSeo 이용
        title = "매장 지도"
        description = "매장 지도입니다."
      />
      <Header/>
      <main style ={{ position : 'relative', width :'100%', height: '100%', overflow:'hidden'}}>
            <MapSection/>
            <DetailSection/>
      </main>
    </Fragment>
  )
}

이러면 자동으로 title과 Meta 태그가 별 문제 없이 생성된 것을 확인할 수 있다.

그리고 og:title 을 통하여 비슷한 역할을 하는 메타태그를 자동으로 만들어주는 것을 확인할 수 있다.
이제 전역적으로 seo를 관리하기 위하여 파일을 하나 생성하고 아래와 같이 입력해보자.

export default {
    titleTemplate: '%s - Next.js 시작하기',
    openGraph: {
      type: 'website',
      site_name: 'Next.js 시작하기',
      images: [
        { url: 'https://nextjs.org/static/blog/next-13/twitter-card.png' },
      ],
    },
    additionalLinkTags: [
      {
        rel: 'shortcut icon',
        href: '/favicon.ico',
      },
    ],
    additionalMetaTags: [
      {
        name: 'naver-site-verification',
        content: '7bd885b384be0f905aad30d00607e0481d4be908',
      },
      {
        name: 'google-site-verification',
        content: 'O0r_20aU1JVk1sbI7E50r6RXiTRFrN8jG_a3uSeG4A0',
      },
    ],
  };
  

titleTemplate속성을 이용하여 title이 가져야 하는 문자열을 지정해줄 수 있다. %s에는 각 페이지마다 들어가게 될 title이 들어간다.
그리고 og 속성을 정해주어야 하는 것은 openGraph 속성에 작성해준다. 다음 additionalLinkTags에는 파비콘이미지를 정해주었으며, 해당 사이트에서 이용하고 있는 meta태그들을 정리해주었다.

이 전역적으로 설정한 seo를 세팅하기 위해서는 _app에서 마무리 지어주면 된다.

import '@/styles/globals.scss'
import type { AppProps } from 'next/app'
import { DefaultSeo } from 'next-seo'
import SEO from '../seo.config';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <DefaultSeo {...SEO}/>
      <Component {...pageProps} />
    </>
  );
}

이제 할 수 있는 개선은 많이 진행하였고 마무리되었다.

0개의 댓글