개발 slecs

메타 태그 생성 중 변수 선언 순서 버그 수정

목차

이번엔 꽤 흔하지만 놓치기 쉬운 버그를 잡았다. Astro 레이아웃 파일에서 origin 변수를 나중에 선언했는데, canonical URL이나 OG 이미지를 생성할 때 이미 그 변수를 참조하고 있었던 것. 결국 ReferenceError가 터지면서 페이지 빌드가 실패하는 상황이 생겼다.

Astro 페이지 생성과 메타 데이터 흐름

먼저 왜 이런 일이 벌어졌는지 배경부터 이해해야 한다. Astro는 빌드 시점에 페이지를 정적으로 생성하는데, .astro 컴포넌트의 프론트매터 섹션(---로 감싼 부분)에서 변수를 선언하고 템플릿에서 사용한다.

canonical URL이나 OG 이미지(ogImage)는 검색 엔진 최적화(SEO)에서 핵심적인 메타 데이터다. Canonical URL은 "이 페이지의 정식 주소가 뭐다"라고 검색엔진에 알려주는 것이고, OG 이미지는 소셜 미디어에서 공유될 때 보여줄 썸네일이다. 이 두 가지 모두 기본적으로 프로토콜과 도메인이 포함된 절대 URL 형태로 구성되어야 한다. 그래서 origin 변수(보통 https://example.com 같은 형태)가 필요했던 것.

문제: 변수를 쓰기 전에 선언하지 않음

전형적인 ReferenceError 상황이다. 코드상으로는 대략 이런 식이었을 것 같다:

// ❌ 잘못된 순서
const canonicalUrl = new URL(path, origin).toString()  // origin 아직 없음!
const ogImageUrl = `${origin}/og.png`  // 또 origin 없음!

// ... 나중에야
const origin = `https://${site.domain}`

JavaScript는 변수를 사용하기 전에 선언이 먼저 되어야 한다. Hoisting이 있긴 하지만(var와 function은 선언이 끌어올려짐), 변수 접근이 일어나는 순간 "이 변수가 뭐야?"라는 에러가 던져진다. Astro 빌드 과정에서는 이 에러가 바로 감지되고 빌드 실패로 이어졌던 것.

수정: 의존 관계에 맞춰 순서 정렬

해결책은 간단하다. origin을 먼저 선언하고, 그 다음에 이를 사용하는 canonicalUrlogImageUrl을 선언하는 것:

// ✅ 올바른 순서
const origin = `https://${site.domain}`
const canonicalUrl = new URL(path, origin).toString()
const ogImageUrl = `${origin}/og.png`

이건 마치 레시피를 따라 요리할 때 "밀가루를 계량하고 섞은 다음에 물을 붓는다"는 식의 순서 개념과 같다. 물을 먼저 붓고 나중에 밀가루를 섞으면 안 되는 것처럼.

회고: 왜 이런 버그가 생기나

개인적으로 느낀 부분은, 기능을 추가하거나 수정할 때 코드를 "아래 위로" 자유롭게 옮기다 보면 이런 일이 생긴다는 것이다. 특히:

  1. 리팩토링 중에 묶음 이동 — 함수나 로직을 블록 단위로 옮길 때 의존성 관계가 깨질 수 있다
  2. 다른 사람의 코드에 추가 작업 — 변수 선언 위치를 모르면 무심코 아래에 사용 코드를 덧붙일 수 있다
  3. 정적 생성 환경의 함정 — 일반 Node.js 앱과 달리 Astro 빌드는 순차적이고 엄격해서, 런타임 에러가 바로 노출된다

이런 버그는 코드리뷰 때 꼭 체크해야 할 것이다. 특히 다음 같은 패턴을 보면 의심해볼 필요가 있다:

  • 변수를 여러 번 조합해서 새 값을 만드는 경우
  • SEO/메타 데이터 관련 코드 (canonical, OG, JSON-LD 등)
  • 외부 도메인이나 URL 구성 로직
  • 빌드 타임에 실행되는 레이아웃/페이지 생성 코드

팀원들과도 이 부분을 공유했다. 작은 버그처럼 보이지만 "선언 → 사용"의 순서 의식을 갖는 것만으로도 꽤 많은 ReferenceError를 미리 막을 수 있다는 걸 강조했다. 특히 Astro처럼 정적 사이트 생성기를 다룰 때는 더욱.


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

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

댓글 0

첫 댓글 달아줘.