Course 페이지에 누락된 OG 아티클 메타 태그 추가로 SNS 공유
목차
Course 페이지 SEO 작업 중 OG 메타 누락을 발견해서 article:* 타입 태그를 추가했다.
왜 지금 이 작업이었나
OG 메타 태그는 기능 개발에 비해 우선순위가 계속 밀리는 영역이다. "동작은 하니까" 라는 이유로 적당히 뒤로 밀려 있다가, 어느 날 팀원이 SNS에 Course 페이지 링크를 공유하면서 제목도 이미지도 없이 URL 한 줄만 떡하니 나오는 걸 캡처해서 올렸다. 그게 트리거였다.
솔직히 말하면 og:title, og:description 정도는 진작 넣어뒀다. 근데 article:* 계열, 즉 article:published_time, article:modified_time, article:author, article:section 같은 태그는 빠져 있었다. 이게 없으면 Facebook이나 LinkedIn 같은 플랫폼에서 해당 페이지를 "기사/콘텐츠 게시물"로 인식하지 못하고 그냥 일반 URL로 처리해버린다. 특히 Course처럼 교육 콘텐츠를 다루는 페이지는 og:type을 article로 선언하는 게 훨씬 자연스럽고 검색 크롤러 친화적이다.
작업 내용
변경 파일은 backend/src/main/resources/templates/fragments/seo.html 하나다. 프로젝트가 Thymeleaf 기반 서버사이드 렌더링 구조인데, SEO 관련 메타 태그를 이 fragment 하나에 모아서 관리하고 있다. 파일 하나에 집중된 변경이라 리뷰하기 편하고, 사이드 이펙트 범위도 명확했다.
추가한 태그 패턴을 정리하면 아래 같은 형태다.
<!-- og:type 을 article 로 선언 -->
<meta property="og:type" content="article" />
<!-- article:* 메타 추가 -->
<meta property="article:published_time"
th:content="${course.createdAt}" />
<meta property="article:modified_time"
th:content="${course.updatedAt}" />
<meta property="article:author"
th:content="${course.authorName}" />
<meta property="article:section"
th:content="${course.category}" />
article:tag 는 Course의 태그 목록이 있으면 반복 렌더링으로 여러 개 심을 수 있는데, 이번엔 우선 핵심 4개만 추가했다. 태그 목록은 데이터 정합성 확인 후 다음 작업으로 이어갈 생각이다.
before / after 비교
| 항목 | before | after |
|---|---|---|
og:type |
미선언(기본값 website) |
article |
article:published_time |
없음 | Course 생성일 |
article:modified_time |
없음 | Course 수정일 |
article:author |
없음 | 강사명 |
article:section |
없음 | 카테고리 |
og:type이 website로 기본 처리되던 게 사실 가장 큰 문제였다. article 타입으로 바꾸면 크롤러가 이 페이지를 "발행된 콘텐츠" 로 이해하고, published_time 기반으로 신선도(freshness) 점수에 반영할 수 있다. SEO 관점에서 콘텐츠 페이지라면 이건 기본 중의 기본인데 지금까지 빠져 있었던 거다.
fragment 하나에 SEO 모아 두는 방식, 팀 입장에서는
Thymeleaf 프로젝트에서 SEO 메타를 fragment로 분리해서 관리하는 건 꽤 합리적인 패턴이다. 각 페이지 템플릿에서 th:replace로 끌어다 쓰는 구조면 수정이 한 파일에서 끝나고, 리뷰 범위도 분명해진다. 반면 페이지별로 메타를 흩어 놓으면 "이 페이지는 됐는데 저 페이지는 빠졌다" 는 식의 누락이 반드시 생긴다.
다만 주의할 점은, fragment 하나가 모든 페이지를 커버하다 보니 Course 전용 변수(course.createdAt 등)를 사용하는 조건부 렌더링을 신경 써야 한다. 해당 변수가 없는 페이지에서 fragment를 include하면 Thymeleaf가 null 참조로 에러를 뱉거나 빈값을 렌더링한다. 이번 코드에서도 th:if 조건으로 Course context에서만 article:* 블록이 출력되도록 감싸는 게 맞고, 그 부분은 실제로 챙겨서 처리했다.
팀 코드리뷰에서 나온 포인트
리뷰에서 한 가지 의견이 나왔다. article:author에 강사명 텍스트를 직접 넣는 것보다 프로필 페이지 URL을 넣는 게 더 정확하다는 것. Open Graph 스펙상 article:author 는 사람의 프로필 URL을 권장한다. 현재는 이름 텍스트를 넣었는데, 이건 스펙 엄밀히 따지면 틀린 건 아니지만 "프로필 URL이 있으면 URL을 넣는 게 낫다" 는 피드백이었다.
맞는 말이라 TODO로 남겼다. 프로필 페이지 URL 구조가 안정화되면 그쪽으로 교체할 계획이다.
SEO는 한 번에 완성하는 작업이 아니라 계속 채워나가는 작업이다. 이번 Course 페이지 article:* 추가는 그 흐름 위의 한 스텝이었고, 다음엔 article:tag 반복 렌더링이랑 author URL 교체가 이어질 것 같다.
끝.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.