개발 slecs

Thymeleaf SEO 메타 태그를 단일 프래그먼트로 통합

목차

5개 템플릿에 흩어져 있던 head 메타 블록을 fragments/seo.html 단일 호출로 통합했다.

왜 지금 이 리팩터링을 했나

Thymeleaf 기반 프로젝트에서 템플릿 파일이 늘어나다 보면 어느 순간 <meta name="description">, <title>, OG 태그 같은 SEO 관련 head 블록이 페이지마다 제각각으로 복붙되어 있는 걸 발견하게 된다. index.html, about.html, contact.html, courses.html, course-detail.html — 5개 파일을 열어보니 딱 그 상태였다. 어떤 파일은 OG 태그가 있고, 어떤 파일은 없고, description 내용도 미묘하게 달랐다.

이런 구조에서 SEO 정책이 바뀌면 — 예를 들어 canonical URL 형식을 변경하거나, twitter card 태그를 추가하거나, meta charset 위치를 조정하거나 — 5개 파일을 모두 열고 동일하게 고쳐야 한다. 한 곳을 빠뜨리면 바로 inconsistency. 그리고 팀 입장에서 코드리뷰할 때도 "이 페이지만 왜 이 태그가 없지?"를 매번 확인해야 하는 인지 비용이 생긴다.

결국 DRY(Don't Repeat Yourself) 원칙 위반 상태였고, 지금 해두지 않으면 파일이 더 늘어날수록 부채가 커진다고 판단해서 이번에 정리했다.

작업 내용

<!-- before: 각 페이지 <head> 안에 직접 박혀 있던 형태 -->
<meta charset="UTF-8">
<meta name="description" content="페이지별로 다른 설명 텍스트">
<meta property="og:title" content="...">
<meta property="og:description" content="...">
<title>페이지 제목</title>
<!-- after: fragments/seo.html 단일 호출 -->
<th:block th:replace="~{fragments/seo :: seo(
    title='페이지 제목',
    description='페이지 설명'
)}"></th:block>

fragments/seo.html에 공통 구조를 정의하고, 페이지별로 달라야 하는 title, description 등은 파라미터로 넘기는 방식이다. OG 태그, canonical, charset 같은 고정 구조는 fragment 안에서 한 번만 관리한다.

변경 대상이 된 파일과 각각의 역할을 정리하면 이렇다.

파일 역할
index.html 메인 랜딩 페이지
about.html 서비스/팀 소개 페이지
contact.html 문의 페이지
courses.html 강좌 목록 페이지
course-detail.html 개별 강좌 상세 페이지

course-detail.html은 동적 데이터(강좌명, 강좌 설명)가 title/description에 들어가야 해서 파라미터 바인딩을 조금 더 신경 써야 했지만, 그 외 4개는 비교적 단순하게 교체됐다.

리팩터링 후 얻은 것, 그리고 주의할 점

이번 작업으로 얻은 건 명확하다.

  • SEO 정책 변경 시 수정 포인트가 fragments/seo.html 한 곳으로 집중됨
  • 신규 페이지 추가 시 head 메타 구조를 처음부터 짤 필요 없이 fragment 호출만으로 해결
  • 코드리뷰 시 "이 페이지 OG 태그 빠졌어요" 류의 지적이 구조적으로 사라짐
  • 팀원이 새 템플릿 파일을 만들 때 fragments/seo 패턴을 따라가기만 하면 되므로 온보딩 부담 감소

다만 fragment 방식으로 통일하면서 주의해야 할 트레이드오프도 있다. fragment에 너무 많은 로직이 몰리면 그 파일 자체가 비대해지고, 페이지별 예외 케이스를 파라미터로 다 커버하려다 보면 파라미터 수가 폭발하는 경우가 생긴다. "공통화하면 무조건 좋다"는 함정인데, 이번 케이스처럼 title/description 정도의 변동만 있는 SEO 메타는 fragment 통합이 깔끔하게 맞아떨어지는 편이다.

템플릿 파일이 5개를 넘어서 본격적으로 늘어나는 시점 전에 이 정리를 끝낸 게 잘한 결정이었다고 본다. 나중에 하려 했으면 분명히 "지금 건드리면 영향 범위가 너무 크다"는 이유로 미뤄졌을 거다.


다음은 fragment 구조 자체의 버저닝이나 테스트 커버리지 쪽을 볼 생각이다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.