그순간

SEO 최적화 제대로 하는 법

김서연·2026년 10월 13일·16 조회

시리즈

Ready, GSM
  1. 1.SEO 최적화 제대로 하는 법← 현재
SEO 최적화 제대로 하는 법

웹 서비스를 개발하고 배포했다고 해서 사용자가 알아서 찾아오는 것은 아닙니다. 서비스가 아무리 잘 만들어져 있어도 검색엔진에서 발견하기 어렵다면, 필요한 정보를 찾고 있는 사용자에게 도달하기 어렵습니다.
특히 특정 학교의 학과 체험이나 입학 설명회처럼 사용자가 검색을 통해 정보를 찾는 서비스라면 검색엔진 최적화(SEO)가 중요합니다.

저도 광주소프트웨어마이스터고등학교의 학과 체험 신청 서비스인 Ready, GSM을 운영하면서 SEO를 개선했습니다. 페이지의 메타데이터를 설정하는 것부터 검색엔진의 크롤링 환경을 구성하고, 실제 검색 결과와 사용자 유입을 확인하는 과정까지 경험했습니다.

이번 글에서는 SEO가 어떤 원리로 동작하는지 알아보고, Next.js를 사용하는 웹 서비스에서 어떤 부분을 신경 써야 하는지 정리해 보겠습니다.

1. SEO는 왜 필요할까?

SEO(Search Engine Optimization)는 검색엔진 최적화를 의미합니다. 예를 들어 구글에서 사용자가 검색했을 때 웹사이트가 검색 결과에 잘 노출될 수 있도록 페이지의 구조와 콘텐츠, 기술적인 환경 등을 개선하는 작업입니다.
웹사이트를 배포하면 검색엔진이 바로 모든 페이지를 찾아 검색 결과에 노출해 줄 것 같지만, 실제로는 그렇지 않습니다. 🥲

Google을 기준으로 검색 결과가 만들어지는 과정을 간단하게 살펴보겠습니다.

  1. 크롤링(Crawling): 검색엔진이 링크와 사이트맵 등을 통해 페이지를 발견하고 콘텐츠를 가져옵니다.
  2. 색인 생성(Indexing): 가져온 페이지의 콘텐츠와 정보를 분석하고 검색 결과에 활용할 수 있도록 저장합니다.
  3. 검색 결과 제공(Serving): 사용자의 검색어와 페이지의 관련성 등 여러 요소를 고려해 검색 결과를 제공합니다.

이 세 과정은 서로 다른 단계이고 페이지가 크롤링되었다고 해서 반드시 색인에 등록되는 것은 아니며, 색인에 등록되었다고 해서 원하는 검색어에서 높은 순위로 노출되는 것도 아닙니다.

따라서 SEO를 개선할 때는 단순히 검색 결과에 사이트가 나타나는지만 확인할 것이 아니라, 검색엔진이 페이지를 발견할 수 있는지, 콘텐츠를 제대로 이해할 수 있는지, 실제 검색을 통해 사용자에게까지 접근이 되는지 확인해봐야합니다.

메타 태그만 설정하면 충분할까?

SEO를 처음 접하면 title이나 description 같은 메타데이터부터 떠올리기 쉽습니다. 물론 얘네들도 중요한 요소이지만 이것만으로 SEO가 완성되는 것은 아닙니다.

예를 들어 페이지의 제목과 설명이 잘 작성되어 있어도 검색엔진이 해당 페이지에 접근할 수 없다면 제대로 활용하기 어렵습니다. 반대로 크롤링 환경이 잘 구성되어 있어도 페이지의 콘텐츠가 불명확하거나 사용자가 찾는 정보와 관련성이 낮다면 검색 결과 성과가 좋지 않을 수 있습니다.
결국 SEO는 하나의 설정으로 해결되는 문제가 아니라, 여러 요소가 함께 작동하도록 구성하는 작업에 가깝습니다.

2. Ready, GSM에 SEO를 적용한 이유

Ready, GSM은 광주소프트웨어마이스터고등학교의 학과 체험 신청을 위한 웹 서비스입니다.
학생들이 본교의 학과 체험 프로그램을 확인하고 신청할 수 있도록 운영하고 있습니다.

하지만 서비스를 운영하면서 학생들이 검색을 통해 학과 체험 서비스를 찾기 어렵다는 문의가 있었습니다.
기존에는 검색엔진을 고려한 메타데이터와 크롤링 환경이 충분히 구성되어 있지 않아 검색 노출을 체계적으로 관리하기 어려웠습니다. 서비스를 운영하는 것뿐만 아니라, 필요한 학생들이 서비스를 발견할 수 있는 환경도 마련해야 한다고 판단했습니다.

이에 Next.js의 Metadata API를 활용해 페이지 메타데이터를 구성하고, Open Graph와 Twitter 카드 정보를 설정했습니다. 또한 JSON-LD, 사이트맵, robots.txt를 적용하고 Google Search Console과 Analytics를 연동해 검색 노출과 사용자 유입을 확인할 수 있도록 개선했습니다.

이 과정에서 중요하게 생각한 것은 단순히 설정 파일을 추가하는 것이 아니라, 검색엔진이 페이지를 발견하고 내용을 이해할 수 있도록 필요한 요소를 함께 구성하는 것이었습니다.

3. 페이지의 목적을 명확하게 전달하기

title과 description 설정하기

검색 결과에서 사용자가 가장 먼저 접하는 정보 중 하나가 페이지 제목과 설명입니다.
이 정보가 페이지의 실제 콘텐츠를 제대로 설명하지 못하면 사용자는 어떤 정보를 제공하는 서비스인지 파악하기 어렵습니다.

예를 들어 HTML에서는 일반적으로 다음과 같은 메타데이터를 사용합니다

<head>
  <title>Ready, GSM | 학과 체험 신청</title>
  <meta
    name="description"
    content="광주소프트웨어마이스터고등학교의 학과 체험 및 입학 설명회 정보를 확인하고 신청해 보세요."
  />
</head>

title은 페이지의 주제를 나타내고 description은 페이지에 어떤 내용이 담겨 있는지를 설명해주면 됩니다.
여기서 중요한 것은 단순히 검색 키워드를 많이 넣는 것이 아닙니다. 실제 페이지의 내용과 일치하면서도 사용자가 페이지의 목적을 이해할 수 있도록 작성해야 합니다.

예를 들어 학과 체험 신청 페이지라면 서비스 이름만 표시하는 것보다 학과 체험과 신청이라는 페이지의 목적을 함께 전달하는 편이 명확합니다.
또한 모든 페이지에 같은 제목과 설명을 반복하기보다는 페이지별 콘텐츠에 맞게 설정하는 것이 좋습니다. 서비스 소개 페이지와 신청 페이지, 자주 묻는 질문 페이지는 각각 제공하는 정보가 다르기 때문입니다.

Next.js Metadata API 활용하기

Next.js App Router에서는 metadata 객체를 사용해 메타데이터를 선언할 수 있습니다.

import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Ready, GSM | 학과 체험 신청',
  description:
    '광주소프트웨어마이스터고등학교의 학과 체험 및 입학 설명회 정보를 확인하고 신청해 보세요.',
  openGraph: {
    title: 'Ready, GSM | 학과 체험 신청',
    description:
      '광주소프트웨어마이스터고등학교 학과 체험 신청 서비스',
    url: 'https://www.ready.hellogsm.kr',
    siteName: 'Ready, GSM',
    type: 'website',
  },
};

Next.js는 이러한 설정을 바탕으로 페이지의 HTML에 필요한 메타데이터를 생성합니다. 따라서 프레임워크에서 제공하는 기능을 활용하면 메타데이터를 직접 문자열로 조립하는 방식보다 일관성 있게 관리할 수 있습니다.

다만 위 코드는 정적인 페이지를 위한 예시입니다. 페이지마다 콘텐츠가 달라지는 상세 페이지라면 generateMetadata를 활용해 데이터에 따라 제목과 설명을 생성할 수 있습니다.
여기서 한 가지 주의할 점이 있습니다. 메타데이터를 설정했다고 해서 검색 결과에 해당 제목과 설명이 그대로 표시된다고 보장할 수는 없습니다. Google은 검색어와 페이지 콘텐츠 등을 바탕으로 제목 링크나 설명을 다르게 구성할 수 있습니다.

Open Graph와 Twitter 카드 설정하기

SEO를 이야기할 때 검색 결과만 생각하기 쉽지만, URL을 다른 사람에게 공유하는 상황도 고려해야 합니다.
메신저나 SNS에서 링크를 공유했을 때 제목과 설명, 미리보기 이미지가 적절하게 표시되면 사용자가 링크의 내용을 파악하기 쉬워집니다.
Open Graph는 이러한 미리보기 정보를 전달하기 위한 메타데이터 규약입니다. Next.js에서는 Metadata API를 통해 관련 정보를 설정할 수 있습니다.

export const metadata = {
  openGraph: {
    title: 'Ready, GSM',
    description: '광주소프트웨어마이스터고등학교 학과 체험 신청 서비스',
    url: 'https://www.ready.hellogsm.kr',
    siteName: 'Ready, GSM',
    images: [
      {
        url: '/og-image.png',
        width: 1200,
        height: 630,
        alt: 'Ready, GSM 학과 체험 신청 서비스',
      },
    ],
    type: 'website',
  },
  twitter: {
    card: 'summary_large_image',
    title: 'Ready, GSM',
    description: '광주소프트웨어마이스터고등학교 학과 체험 신청 서비스',
    images: ['/og-image.png'],
  },
};

이때 images에 지정한 이미지가 실제로 공개된 경로에서 접근 가능한지도 확인해야 합니다. 배포 환경에서 이미지가 404 오류를 반환하거나 잘못된 URL을 사용하면 의도한 미리보기가 표시되지 않을 수 있습니다.
또한 Open Graph와 Twitter 카드는 링크 공유 시 표시되는 정보를 위한 설정입니다. 검색 순위를 직접 높여 주는 설정으로 이해해서는 안 됩니다.

4. 검색엔진이 페이지를 발견할 수 있도록 구성하기

메타데이터를 설정했다면 다음으로 확인해야 하는 것은 검색엔진이 사이트의 URL을 발견하고 접근할 수 있는 환경입니다.
이때 자주 사용하는 것이 사이트맵과 robots.txt입니다. 두 파일은 함께 사용되는 경우가 많지만 역할은 서로 다릅니다.

Sitemap으로 주요 URL 알리기

사이트맵은 검색엔진에 사이트의 주요 URL을 알려주는 파일입니다. 검색엔진은 사이트맵을 통해 페이지를 발견할 수 있지만, 사이트맵에 URL을 추가했다고 해서 해당 페이지가 반드시 색인되는 것은 아닙니다.
Next.js App Router에서는 app/sitemap.ts 파일을 통해 사이트맵을 생성할 수 있습니다.

import type { MetadataRoute } from 'next';

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: 'https://www.ready.hellogsm.kr',
      lastModified: new Date(),
    },
    {
      url: 'https://www.ready.hellogsm.kr/faq',
      lastModified: new Date(),
    },
  ];
}

위 코드는 동작 방식을 설명하기 위한 예시입니다. 실제 서비스에서는 공개 대상인 페이지의 URL을 기준으로 구성해야 합니다.

예를 들어 로그인이 필요한 관리자 페이지나 검색 결과에 노출할 필요가 없는 페이지까지 무조건 사이트맵에 포함할 이유는 없습니다. 반대로 공개된 주요 페이지가 누락되어 있다면 검색엔진이 해당 페이지를 발견하는 데 불필요한 어려움이 생길 수 있습니다.
페이지가 많다면 URL 목록을 직접 관리하기보다 데이터에 따라 생성하는 방법을 고려할 수 있습니다. 단, 실제 콘텐츠가 존재하고 공개되어 있는 URL만 포함하는 것이 좋습니다.
lastModified 역시 매번 현재 시간을 넣는 것보다는 실제 콘텐츠가 수정된 시점을 반영하는 편이 정확합니다.

robots.txt 설정하기

사이트맵이 검색엔진에 URL을 알려주는 역할을 한다면, robots.txt는 크롤러가 접근할 수 있는 경로와 제한할 경로를 안내하는 역할을 합니다.
Next.js에서는 app/robots.ts로 구성할 수 있습니다.

import type { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: '*',
      allow: '/',
    },
    sitemap: 'https://www.ready.hellogsm.kr/sitemap.xml',
  };
}

이 설정은 모든 크롤러에 대해 사이트 전체의 크롤링을 허용하고 사이트맵 위치를 안내하는 예시입니다. 실제 서비스에서는 크롤링을 제한해야 하는 경로가 있는지 확인한 뒤 정책을 정해야 합니다.
여기서 혼동하기 쉬운 부분이 있습니다. robots.txt에서 크롤링을 막는 것과 검색 결과에서 페이지를 제외하는 것은 같은 의미가 아닙니다.

검색엔진이 페이지를 크롤링하지 못하더라도 다른 페이지의 링크 등을 통해 URL을 발견할 수 있으며, 경우에 따라 페이지 내용 없이 URL이 검색 결과에 나타날 수 있습니다. 검색 결과에서 제외해야 한다면 noindex 등의 방법을 검토해야 하고, 검색엔진이 해당 지시를 확인할 수 있도록 페이지에 접근할 수 있어야 합니다.
따라서 관리자 페이지나 개인 정보가 포함된 페이지를 보호하기 위해 robots.txt만 사용하는 것은 적절하지 않습니다. 접근 권한은 서버에서 별도로 검증해야 합니다.

Canonical URL로 대표 URL 지정하기

같은 콘텐츠가 여러 URL로 접근 가능한 경우에는 검색엔진이 어떤 URL을 대표 주소로 취급해야 하는지 명확하게 전달할 필요가 있습니다.
이때 사용하는 것이 canonical URL입니다.

import type { Metadata } from 'next';

export const metadata: Metadata = {
  alternates: {
    canonical: 'https://www.ready.hellogsm.kr',
  },
};

위 예시는 해당 페이지의 대표 URL을 지정하는 방법입니다. 실제로는 페이지마다 올바른 대표 URL을 지정해야 하며, 모든 페이지가 무조건 홈페이지를 canonical로 가리키도록 설정하면 안 됩니다.
Canonical은 중복되거나 유사한 URL이 존재할 때 검색엔진에 대표 URL을 알려주는 신호입니다. 검색엔진이 이를 반드시 그대로 따르는 것은 아니므로 URL 구조와 내부 링크, 사이트맵도 함께 일관성 있게 관리하는 것이 좋습니다.

5. 검색엔진이 이해하기 쉬운 콘텐츠 만들기

기술적인 설정을 완료하더라도 페이지의 콘텐츠가 명확하지 않으면 충분하지 않습니다. 검색엔진이 페이지의 주제를 파악할 수 있도록 HTML 구조와 콘텐츠를 구성하는 것도 중요합니다.

시맨틱 HTML 사용하기

HTML 요소는 단순히 화면을 꾸미기 위한 용도로만 사용하는 것이 아닙니다. 각 요소가 가진 의미를 적절하게 활용하면 콘텐츠의 구조를 명확하게 표현할 수 있습니다.

예를 들어 제목은 h1, h2, h3 등으로 계층을 표현하고, 주요 탐색 영역에는 nav, 독립적인 콘텐츠에는 article과 같은 요소를 사용할 수 있습니다.

export default function Page() {
  return (
    <main>
      <h1>학과 체험 신청</h1>

      <section>
        <h2>학과 체험 안내</h2>
        <p>학과별 교육 과정과 체험 프로그램을 확인할 수 있습니다.</p>
      </section>

      <section>
        <h2>신청 방법</h2>
        <p>원하는 프로그램을 선택한 뒤 신청 정보를 입력합니다.</p>
      </section>
    </main>
  );
}

이때 h1을 반드시 하나만 사용해야 한다는 식으로 규칙을 단순화하기보다는, 페이지의 콘텐츠 구조를 논리적으로 표현하는 데 집중하는 것이 좋습니다.
또한 중요한 정보를 이미지 안에만 넣거나, 사용자가 실제로 접근할 수 없는 방식으로 제공하면 콘텐츠를 이해하기 어려워질 수 있습니다. 페이지의 핵심 정보는 실제 HTML 콘텐츠로 명확하게 전달하는 것이 좋습니다.

내부 링크와 이미지도 확인하기

검색엔진은 링크를 통해 다른 페이지를 발견할 수 있습니다. 따라서 주요 페이지로 이동할 수 있는 내부 링크를 제공하고, 링크의 목적이 명확하게 드러나도록 작성하는 것이 좋습니다.
이미지 역시 검색엔진이 콘텐츠를 이해하는 데 도움이 될 수 있도록 관리해야 합니다. 이미지의 내용을 설명하는 대체 텍스트(alt)를 제공하면 이미지가 표시되지 않는 상황에서도 정보를 전달할 수 있으며, 스크린 리더 사용자가 이미지의 의미를 이해하는 데도 도움이 됩니다.

다만 모든 이미지에 설명을 추가해야 하는 것은 아닙니다. 의미가 있는 이미지에는 적절한 대체 텍스트를 제공하고, 단순한 장식용 이미지에는 빈 대체 텍스트를 사용하는 것이 적절합니다.

JSON-LD 구조화 데이터 활용하기

구조화 데이터는 페이지의 콘텐츠를 검색엔진이 이해할 수 있도록 추가적인 정보를 제공하는 방법입니다. JSON-LD는 구조화 데이터를 표현할 때 사용할 수 있는 형식입니다.
예를 들어 실제 페이지가 학교 행사에 관한 정보를 제공하고, Google이 해당 콘텐츠 유형에 대한 검색 기능을 지원한다면 적절한 구조화 데이터 유형을 검토할 수 있습니다.

하지만 구조화 데이터는 페이지에 없는 정보를 만들어 넣는 용도로 사용해서는 안 됩니다. 실제 사용자에게 표시되는 콘텐츠와 일치해야 하며, 검색엔진이 지원하는 유형과 필수 속성도 확인해야 합니다.
구조화 데이터를 올바르게 추가하더라도 검색 결과에 별도의 확장 정보가 표시되거나 검색 순위가 상승한다고 보장할 수는 없습니다.

6. 성능 최적화도 함께 고려하기

SEO를 개선할 때는 검색엔진에 정보를 전달하는 것뿐만 아니라 실제 사용자가 페이지를 원활하게 이용할 수 있는지도 고려해야 합니다.
Google은 Core Web Vitals를 통해 로딩 성능, 상호작용 반응성, 시각적 안정성을 측정합니다.
대표적인 지표는 다음과 같습니다.

지표 의미 주요 개선 방향
LCP 주요 콘텐츠가 표시되는 속도 이미지 최적화, 서버 응답 개선
INP 사용자 상호작용에 대한 반응성 불필요한 JavaScript 작업 감소
CLS 페이지 레이아웃의 시각적 안정성 이미지 크기 지정, 동적 콘텐츠 공간 확보

Core Web Vitals는 사용자 경험을 평가하는 중요한 지표지만, 점수 하나만으로 검색 순위가 결정되는 것은 아닙니다. 콘텐츠의 관련성과 유용성 등 다른 요소도 함께 고려됩니다.

Lighthouse로 성능 확인하기

Chrome DevTools의 Lighthouse를 사용하면 Performance 점수와 주요 성능 지표를 확인할 수 있습니다.
Ready, GSM의 경우 Lighthouse Performance 점수 100을 기록했습니다. 이는 측정 당시 해당 환경에서 우수한 성능 점수를 얻었다는 의미입니다.
다만 Lighthouse 점수는 측정 환경에 따라 달라질 수 있으며, SEO 점수와 Performance 점수는 서로 다른 항목입니다. 따라서 성능 점수 100을 기록했다고 해서 검색엔진 최적화가 완성되었다고 판단해서는 안된다고 생각합니다.

성능 개선은 검색 노출 자체만을 목표로 하기보다 사용자가 페이지를 빠르게 이용하고 필요한 정보를 쉽게 확인할 수 있도록 한다는 관점에서 접근하는 것이 좋습니다.

7. 실제 검색 결과와 사용자 유입 확인하기

SEO는 설정을 완료한 순간 끝나는 작업이 아닙니다. 적용한 설정이 실제로 작동하는지 확인하고, 검색 결과에서 어떤 변화가 발생하는지 지속적으로 살펴봐야 합니다.
이를 위해 Google Search Console과 Analytics를 활용할 수 있습니다.

Google Search Console

Search Console에서는 Google 검색에서 발생한 노출수, 클릭수, CTR, 평균 게재순위 등을 확인할 수 있습니다.
또한 URL 검사 기능을 사용하면 개별 페이지의 색인 상태와 Google이 확인한 정보를 살펴볼 수 있습니다.
SEO를 적용한 뒤에는 다음 항목을 확인하는 것이 좋습니다.

  • 사이트맵이 정상적으로 제출되었는가?
  • 주요 페이지가 색인되었는가?
  • 크롤링 또는 색인 생성 과정에서 문제가 발생했는가?
  • 어떤 검색어에서 사이트가 노출되고 있는가?
  • 노출수와 클릭수가 시간에 따라 어떻게 변화하는가?

검색 결과에 나타나지 않는 페이지가 있다면 무조건 메타데이터부터 수정하기보다, URL 검사와 색인 상태를 먼저 확인하는 것이 효율적입니다.

Analytics로 사용자 행동 분석하기

검색 결과에서 페이지가 노출되는 것과 사용자가 실제로 서비스를 이용하는 것은 서로 다른 문제입니다.
Analytics를 활용하면 사이트에 방문한 사용자의 행동과 페이지 조회, 주요 이벤트 등을 분석할 수 있습니다. 검색을 통해 유입된 사용자가 어떤 페이지를 방문하고 어떤 행동을 하는지 살펴보면 개선 방향을 구체화하는 데 도움이 됩니다.
다만 Analytics만으로 Google 검색 결과의 노출수나 색인 상태를 정확하게 파악할 수 있는 것은 아닙니다. 검색 성과는 Search Console에서 확인하고, 사이트 내부의 사용자 행동은 Analytics에서 확인하는 방식으로 구분하는 것이 좋습니다.

8. Ready, GSM의 SEO 적용 결과

Ready, GSM에 SEO 관련 설정을 적용한 이후에는 실제 검색 결과와 서비스 이용 데이터를 확인했습니다.
운영 데이터 기준으로 다음과 같은 수치를 기록했습니다.

  • 활성 사용자 321명
  • 조회수 3,400+
  • 이벤트 6,400+
이미지

검색 결과에서 Ready, GSM 서비스가 노출되는 것도 확인할 수 있었습니다. 또한 Lighthouse Performance 점수 100을 기록하며 페이지 성능을 측정했습니다.
SEO의 효과를 더 정확하게 분석하려면 적용 전후의 Search Console 데이터를 비교해야 합니다. 예를 들어 검색 노출수와 클릭수, CTR, 자연 검색 유입량을 일정한 기간 동안 비교하면 실제 검색 성과가 어떻게 달라졌는지 파악할 수 있습니다.

이처럼 SEO는 구현 여부뿐만 아니라 적용 이후의 데이터를 확인하고 개선하는 과정까지 이어져야 합니다.

마무리

SEO를 공부하고 Ready, GSM에 적용하면서 느낀 점은 검색엔진 최적화가 단순히 메타 태그를 추가하는 작업은 아니라는 것입니다.

검색엔진이 페이지를 발견할 수 있도록 사이트맵과 크롤링 환경을 구성하고, 페이지의 목적을 명확하게 전달할 수 있도록 메타데이터와 HTML 구조를 정리해야 합니다. 여기에 실제 검색 결과와 사용자 유입을 확인하는 과정까지 함께 이루어져야 합니다.
또한 SEO는 한 번 설정하고 끝내기보다는 서비스의 콘텐츠와 구조가 바뀔 때마다 확인해야 하는 영역입니다. 페이지를 추가하거나 URL 구조를 변경했다면 사이트맵과 메타데이터가 올바르게 유지되는지 확인하고, 검색 성과에도 변화가 있는지 살펴보는 것이 좋습니다.

앞으로도 서비스를 개발할 때 기능 구현과 배포에만 집중하기보다, 사용자가 서비스를 발견하고 필요한 정보를 얻기까지의 과정도 함께 고려하고자 합니다.

목차