Next.js 블로그 제작기 (8)

user profile img

신현호

TypeScript
Next.js

블로그 제작기

Post Thumbnail

목차

    서론

    오늘도 블로그 글이 잘 올라갔나 구글 서치콘솔과 네이버 서치 어드바이저를 열심히 돌아다녔는데, 이상한 걸 봐버렸습니다

    report

    meta 태그가 이상하다고..? 나 이거 설정 안했었나? 하고 바로 색인된 내용을 찾아보러 네이버로 허둥지둥 달려갔는데..

    박살난 메타태그

    그렇습니다.. 저는 이 블로그 운영한지 좀 됐는데 meta태그하고 OpenGraph 세팅을 아직 하지 않았던 것 입니다..
    지금은 잘 적용되어있고, 오늘은 이 업데이트 사항에 대해서 적어보도록 하겠습니다.

    변경점

    Meta태그의 적용

    우선 meta태그에 대해서 간단하게 설명을 하도록 하겠습니다. meta태그란 간단하게 해당 페이지에 대한 정보를 의미합니다.
    우리는 구글, 네이버와 같은 포털에서 검색 결과로 자체 서비스된 사이트 말고도 여러 사이트를 만나게 됩니다. 그리고 해당 사이트를 찾게되면 해당 사이트를 표현하는 제목과 그에 따른 설명이 적혀있습니다.
    포털 사이트에서 어떻게 해당 사이트에 정보를 얻을까요? 위의 내용과 함께 생각해본다면 포털 사이트들은 사이트들의 meta 태그를 통해서 우리에게 정보를 보여주고 있다는 것을 짐작할 수 있습니다! 실제로도 그렇구요

    그렇다면, Next.js에서는 이 meta 태그를 어떻게 사용할 수 있을까요?
    Next13부터 Next는 간단하게 Metadata 객체를 layout, page 컴포넌트에서 export 해줌으로써 해당 페이지에 대한 meta태그를 쉽게 적용할 수 있습니다.

    아래는 그 예시입니다.

    ts

    export const metadata: Metadata = {
      title: '신현호의 기술서재',
      description: '학습한 내용들을 기록합니다.',
      ...
    }
    
    export default function RootLayout() {
        ...
    }
    

    이런식으로 간단하게 export 한번만 해주면 해당 페이지에 정적으로 meta태그를 설정할 수 있습니다.
    저는 딱 여기까지만 해서 모든 페이지에 해당 제목과 설명만 적용된 것 입니다..

    따라서 해당 작업을 모든 페이지에 해줘야하는데.. 이러면 한 가지 생각이 듭니다.
    정적 페이지는 이렇게 하는데 동적으로 생성된 페이지에는 어떻게 meta태그를 적용시켜줘야하지?

    동적 meta태그 적용

    Next13 이전버전에서는 Meta태그를 어떻게 설정했는지 사실은 잘 모르지만 (저는 13버전부터 써왔습니다) Next13부터는 generateMetadata를 통해서 간단하게 설정해 줄 수 있습니다.

    ts

    import { Metadata } from 'next'
    
    // either Static metadata
    export const metadata: Metadata = {
      title: '...',
    }
    
    // or Dynamic metadata
    export async function generateMetadata({ params }) {
      return {
        title: '...',
      }
    }
    

    공식 문서에 따르면 이런식으로 generateMetadata를 export해주면 간단하게 적용할 수 있음을 알 수 있습니다.
    일반적으로는 paramssearchParams를 사용해서 meta태그를 재설정해주더라구요.

    저도 params를 통해서 다른 페이지들은 간단하게 적용을 시켜주었는데, 문제는 제 포스트 내부 페이지였습니다.
    저는 params에 간단하게 포스트의 id만 넣어주고 있었거든요..

    일반적으로는 포스트의 id를 파라미터에 넣어주기보단 그냥 포스트의 제목을 파라미터로 넣어주더라구요. (다그런건 아닙니다)
    저는 파라미터로 건져올게 없었기때문에 다른 방법이 필요했습니다.

    먼저 생각했던 방법은 querySelector로 타이틀의 정보를 가져오는 것 이었습니다..만 문제가 있었습니다.
    바로 meta태그의 생성 시점과 html 요소가 생성되는 시점은 다르다는 것 이었죠, meta태그가 생성될 때에는 아직 요소가 모두 렌더링된게 아니었던 겁니다.

    따라서 다른 방법이 필요했습니다. 어떻게하면 포스트의 정보를 가져올 수 있을까? 하고 생각해보니 저는 contentlayer를 사용하고있었습니다.
    그냥 간단하게 contentlayer를 사용해서 로직을 구성하면 되겠더라구요

    ts

    export const getSelectedPostDetail = (id: number) => {
      const selectedPost = getAllPost().find(
        ([idx]) => idx === getAllPostLength() - id
      ) ?? [0, { title: '', description: '', thumbnail: '' }]
    
      return {
        title: selectedPost[1].title,
        description: selectedPost[1].description,
        thumbnail: selectedPost[1].thumbnail,
      }
    }
    

    하여 이런식으로 title, description, thumbnail의 정보를 가져왔습니다. (thumbnail은 이후 OpenGraph에서 사용합니다)

    적용

    완성! 정상 적용된 모습입니다 😆

    OpenGraph의 적용

    이번에는 OpenGraph입니다. OpenGraph를 간단하게 설명해보자면

    적용

    링크를 올리니 아래 미리보기에 사진과 제목, 그리고 설명까지 표시되었죠? 이게 OpenGraph입니다.

    이 또한 Nextjs에서 쉽게 생성할 수 있고, 사실 앞에서 말한 meta 생성법에 몇가지만 추가하면 됩니다.

    ts

    export const metadata: Metadata = {
      title: '신현호의 기술서재',
      description: '학습한 내용들을 기록합니다.',
      openGraph: {
        title: '신현호의 기술서재',
        description: '학습한 내용들을 기록합니다.',
        url: 'https://caffhheiene.vercel.app',
        siteName: '신현호의 기술서재',
        images: [
          {
            url: 'https://caffhheiene.vercel.app/profile/Profile_sunglassed_icon.jpg',
            width: 850,
            height: 600,
            alt: '신현호의 기술서재',
          },
        ],
        type: 'website',
      },
    }
    

    openGraph 항목에 title, description, url, siteName, images와 같은 속성을 넣어주면 됩니다.

    동적 OpenGraph 적용

    이쯤되면 동적으로 적용하는것도 감이 오시죠?

    ts

    export const generateMetadata = async (
      props: Props,
      parent: ResolvingMetadata
    ): Promise<Metadata> => {
      const { title, description, thumbnail } = getSelectedPostDetail(
        Number(props.params.id)
      )
    
      return {
        title,
        description,
        openGraph: {
          ...(await parent).openGraph,
          title,
          description,
          url: `https://caffhheiene.vercel.app/posts/detail/${props.params.id}`,
          images: [
            {
              url: `https://caffhheiene.vercel.app${thumbnail}`,
              width: 850,
              height: 600,
              alt: `${title} / ${description}`,
            },
          ],
        },
      }
    }
    

    이전과 좀 차이가 있다면 parent인데, 이건 RootLayout에서 정의했던 default Metadata를 적용하겠다는 의미입니다.

    끝으로

    처음에는 이 generateMetadata를 어떻게 써야하는건지 좀 감이 안왔는데, 문서와 예제를 찾아보다보니 생각보다 쉽게 적용할 수 있더라구요!
    그냥 단순하게 export만 해주면 되는 것이라서 난이도도 그렇게 높지도 않았습니다!

    사이트가 잘 굴러가는것 같아도 봐주는 사람이 없으면 안되니까요 ㅠㅠ(저는 이미 몇달동안 그랬음) 여러분들은 꼭 OpenGraph와 Metadata 설정해주세요..

    참고

    Profile Image

    신현호

    Frontend Developer

    프론트엔드 개발자를 꿈꾸고 있는 대학생입니다. 끊임없이 배우고 성장하는 개발자가 되기 위해 노력하고 있습니다.

    블로그 제작기

    총 11개의 포스트가 존재합니다.