Published on

SEO 이해 & 적용하기

SEO 란?

  • SEO(Search Engine Optimizization)은 웹 사이트가 검색 포털(구글, 네이버 등)에서 더 잘 노출되도록 최적화 하는 방식이다. 검색 포털에서 검색시 검색 엔진 봇인 웹 크롤러가 메타 데이터를 크롤링 한 결과로 사이트 노출 순위를 정하게 된다. 따라서, 웹 크롤러의 크롤링 가이드에 맞추어 개발하는 것이 SEO에서 중요하다. 또한 크롤링은 이미 완성된 html을 크롤링 하기 때문에 SSR로 생성된 페이지가 SEO에 더 유리하다.(대표적 react framework: NextJS)
웹 크롤러
- 스파이더 또는 검색 엔진 봇이라고 불리며, 자동화된 방법으로 인터넷 웹 페이지를 방문해 자료를 수집하는 컴퓨터 프로그램.
- 페이지의 사본, 메타데이터를 사용해 사이트 페이지를 검색하고 색인을 만듦.

SEO를 위한 작업들

  • Meta Tag(<meta>) 설정 : <meta> 웹 페이지에 대한 정보인 '메타 데이터'를 제공하는 태그.
    • <title>
      • 검색 결과에 노출되는 제목.
      • <head>
          <meta charset="utf-8" />
          <title>SEO 이해 & 적용하기 | huun's dev</title>
        </head>
        
      • Maple
    • description tag
      • 검색 결과에 노출되는 웹 페이지의 설명. 한 두줄의 키워드 중심의 요약된 문장으로 작성 권장.
      • <head>
          <meta name="description" content="SEO의 기본개념 이해하고, nextjs에 적용해보기." />
        </head>
        
    • robots tag
      • 검색 엔진 봇의 접근 여부를 설정할 때 사용.
      • robot content 속성 링크
      • <!-- 크롤링 O, 색인 O -->
        <head>
          <meta name="robots" content="index, follow" />
        </head>
        
    • canonical tag
      • 여러 URL을 가진 웹 페이지가 있을 때, 대표 URL을 설정하는 태그. 검색 봇이 크롤링시 중복 URL로 인한 패널티 방지를 위해 사용.
      • 캐노니컬 태그: 한 페이지, 또는 여러 페이지가 하나의 카테고리로 분류되어야할때 사용되는 대표 URL.
      • <head>
          <!-- https://www.example.com/feed  -->
          <!-- https://www.example.com/feed?page=1  -->
          <!-- http://m.example.com/feed?page=1  -->
          <link rel="canonical" href="https://www.example.com/feed" />
        </head>
        
    • og(open graph) tag
      • open graph 관련 태그이며 meta tage의 property="og:xxx" 속성으로 설정 가능.
      • open graph: 웹 페이지 링크로 공유시 노출될 메타 데이터.
      • <head>
          <meta property="og:title" content="SEO 이해 & 적용하기 | huuns dev 공유하기" />
          <meta
            property="og:description"
            content="SEO의 기본개념 이해하고, nextjs에 적용해보기. 공유하기"
          />
          <meta property="og:image" content="썸네일 이미지 path" />
          <meta property="og:url" content="https://huun-devlog.vercel.app/blog/web/seo" />
          <meta property="og:site_name" content="huun-devlog" />
          <meta property="og:type" content="website" />
          <meta property="og:image:width" content="800" />
          <meta property="og:image:height" content="400" />
        </head>
        
    • light house 점수 고점 유지.
      • 시맨틱 마크업: 시맨틱 태그를 용도에 맞게 적절히 사용.
        • 시멘틱 태그: header, footer tag 등과 같이 특정 의미가 부여된 html 태그.
      • 이미지 alt 속성 기재.
      • 모바일 사양 제공.

NextJS에 적용하기

NextJS 13 이후 도입된 app direction typescript에서 적용하는 방법을 소개한다. (src directory의 경우 상기 meta tag 선언을 _document.tsx에 선언하면 설정 가능.)

1. metadata 설정하기

  • 정적 메타 데이터: page params에 따른 변동이 없는 페이지에서 사용.(ex. 메인 페이지, post list 페이지 등)

    • 설정할 페이지의 page.ts 또는 해당 페이지의 layout.ts에서 metadata 선언으로 설정 가능.

      // page.tsx or layout.tsx
      import type { Metadata } from 'next';
      
      export const metadata: Metadata = {
        title: '...',
        description: '...',
      };
      
      export default function Page() {}
      
    • 상기 방식으로 설정 가능 하지만, 다수 페이지 관리시 중복 로직이 반복 되므로 metadata를 설정하는 function을 만들어 각 페이지에서 import 하는것이 바람직하다.

      // seo.tsx
      import { Metadata } from 'next';
      import siteMetadata from '@/data/siteMetadata';
      
      interface PageSEOProps {
        title: string;
        description?: string;
        image?: string;
        [key: string]: any;
      }
      
      export function genPageMetadata({
        title,
        description,
        image,
        ...rest
      }: PageSEOProps): Metadata {
        return {
          title,
          openGraph: {
            title: `${title} | ${siteMetadata.title}`,
            description: description || siteMetadata.description,
            url: './',
            siteName: siteMetadata.title,
            images: image ? [image] : [siteMetadata.socialBanner],
            locale: 'ko-KR',
            type: 'website',
          },
          twitter: {
            title: `${title} | ${siteMetadata.title}`,
            card: 'summary_large_image',
            images: image ? [image] : [siteMetadata.socialBanner],
          },
          ...rest,
        };
      }
      
      // page.tsx or layout.tsx
      import projectsData from '@/data/projectsData';
      import { genPageMetadata } from 'app/seo';
      
      // custom 필요한 metadate만 설정.
      export const metadata = genPageMetadata({ title: 'page title' });
      
      export default function Page() {}
      
    • 동적 메타데이터: page params에 따른 변동이 필요한 페이지에서 사용.(ex. post 상세 페이지 등)

      // app/dinamic-mata/[id]/page.tsx
      import siteMetadata from '@/data/siteMetadata';
      // 상기 동적 metadata 설정 function 함께 사용.
      import { genPageMetadata } from 'app/seo';
      
      export async function generateMetadata({ params }: {
        params: { company: string };
      }): Promise<Metadata> {
        return genPageMetadata({
          title: `dinamic meta ${company.toUpperCase()}`,
          description: `${siteMetadata.title} ${company} dinamic meta`,
          ...
        });
      }
      
      export default function Page() {}
      

2. sitemap 설정하기

  • 정적 sitemap.xml 방식

    <!-- app/sitemap.xml 경로에 파일 생성 -->
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <url>
        <loc>https://huuns-devlog.com</loc>
        <lastmod>2023-04-06T15:02:24.021Z</lastmod>
        <changefreq>yearly</changefreq>
        <priority>1</priority>
      </url>
      ...
      <!-- 페이지 리스트 -->
    </urlset>
    
  • sitemap 생성 방식

    // app/sitemap.ts 경로에 파일 생성
    import { MetadataRoute } from 'next';
    
    export default function sitemap(): MetadataRoute.Sitemap {
      return [
        {
          url: 'https://huuns-devlog.com',
          lastModified: new Date(),
          changeFrequency: 'yearly',
          priority: 1,
        },
        {
          /* 페이지 리스트 */
        },
      ];
    }
    

3. robots 설정하기

  • 정적 robots.txt 방식

    // app/robots.txt 경로에 파일 생성
    User-Agent: *
    Allow: /
    Disallow: /private/
    Sitemap: https://huun-devlog.com/sitemap.xml
    
  • robot 생성 방식

    // app/robots.ts 경로에 파일 생성
    import { MetadataRoute } from 'next';
    
    export default function robots(): MetadataRoute.Robots {
      return {
        rules: {
          userAgent: '*',
          allow: '/',
          disallow: '/private/',
        },
        sitemap: 'https://huun-devlog.com/sitemap.xml',
      };
    }
    

4. seo 적용 결과

구글 검색 결과

ref