개발 slecs

마크다운 테이블·제목이 스타일 안 받던 버그 수정

목차

Astro 블로그를 쓰고 있는데, 마크다운에서 렌더링되는 테이블과 제목들이 정의해둔 CSS 스타일을 전혀 받지 않는 문제가 있었다. 처음엔 스타일 코드가 빠진 줄 알고 찾아봤는데, 결국 Astro의 CSS 스코핑(scoped styles)과 동적으로 주입되는 마크다운 HTML 사이의 충돌이었다.

문제 상황: 스타일이 아예 적용이 안 됨

Post 레이아웃에서 마크다운을 파싱한 결과물을 렌더링하는데, 테이블의 <table>, <tr>, <td> 같은 엘리먼트들이나 <h2>, <h3> 헤딩들이 레이아웃의 스타일시트에서 정의한 스타일을 받지 못하고 있었다. CSS 개발자도구로 확인해보면 스타일 규칙이 아예 적용되지 않은 상태였다.

겉으로는 마크다운 콘텐츠가 그대로 렌더링되기만 하고, 테이블 보더도 없고 헤딩의 폰트 크기 같은 것도 기본값 그대로였다. 사용자 입장에서는 블로그 글의 일관성이 깨져 보였을 것이다.

원인: Astro의 scoped CSS와 동적 콘텐츠

Astro는 기본적으로 .astro 컴포넌트에 정의된 CSS를 그 컴포넌트와 그 안의 자식 엘리먼트에만 한정한다. 각 스타일에 unique한 class 이름을 자동으로 붙여주는 방식이다. 이렇게 하면 서로 다른 컴포넌트의 스타일이 충돌하지 않는다는 장점이 있다.

문제는 마크다운 렌더러가 생성하는 HTML 엘리먼트들인데, 이들은 컴포넌트가 마운트된 이후에 동적으로 삽입되는 HTML이다. Astro의 scoped CSS는 이런 동적 콘텐츠까지 자동으로 처리해주지 않는다. 마크다운에서 나온 <table> 엘리먼트는 원래 Post 컴포넌트의 스타일 규칙에 명시적으로 속하지 않기 때문이다.

// Post.astro (문제 상황)
<style>
  table {
    border-collapse: collapse;
    width: 100%;
  }

  td {
    border: 1px solid #ccc;
    padding: 8px;
  }
</style>

<div set:html={markdownHtml} />

위의 <style> 블록에서 정의한 table, td 규칙은 Post 컴포넌트 내부의 정적 HTML에만 적용된다. set:html로 주입된 마크다운 HTML은 스코핑 대상이 아니므로 스타일이 먹지 않는다.

해결책: :global() 선택자로 스코핑 해제

:global() 선택자를 감싸면 Astro가 그 규칙을 전역으로 처리하도록 지시할 수 있다.

// Post.astro (수정 후)
<style>
  :global(table) {
    border-collapse: collapse;
    width: 100%;
  }

  :global(td) {
    border: 1px solid #ccc;
    padding: 8px;
  }
</style>

이렇게 하면 Post 컴포넌트의 스타일 블록에서 정의한 규칙이 전역 범위로 적용되고, 동적으로 주입된 마크다운 테이블도 스타일을 제대로 받는다. 헤딩(h2, h3), 인라인 코드(code), 링크(a) 같은 마크다운 엘리먼트들도 동일하게 처리하면 된다.

회고: 스코핑과 동적 콘텐츠의 트레이드오프

이 경험에서 배운 점은 몇 가지다.

먼저, CSS 스코핑은 기본적으로 정적 콘텐츠를 가정한다는 것이다. React의 CSS-in-JS, Vue의 scoped styles, Astro의 scoped CSS 모두 마찬가지다. 스타일과 DOM 구조가 컴포넌트 렌더링 시점에 확정되어 있어야 제대로 작동한다. 만약 런타임에 새로운 엘리먼트가 추가되면, 스코핑 메커니즘이 그것을 추적하기 어려워진다.

둘째, :global()은 신중하게 써야 한다. 모든 스타일을 :global로 감싸면 결국 BEM이나 네이밍 컨벤션에 의존하는 것과 같아진다. 충돌 가능성이 높아진다. 따라서 :global()은 다음 경우에 제한적으로 써야 한다:
- 마크다운, 사용자 입력 같은 동적 콘텐츠를 렌더링하는 부분
- 써드파티 라이브러리에서 생성한 HTML을 감싸는 경우
- 전역으로 적용되어야 하는 기본 스타일 리셋

셋째, 마크다운 스타일링은 초반부터 고려해야 한다. 만약 많은 마크다운을 렌더링하는 블로그라면, Post 레이아웃 설계 시점에 "마크다운에서 나오는 엘리먼트들을 어떻게 스타일할 것인가"를 먼저 결정해두는 게 좋다. 나중에 "어라, 테이블이 안 보인다"고 발견하고 수정하는 것보다는.

마지막으로, 개발자도구의 Elements 탭과 Styles 탭을 활용해 범위를 빠르게 파악할 수 있다. 어떤 스타일이 정말 적용되고 있는지, 어떤 규칙이 무시되고 있는지를 보면 문제가 훨씬 명확해진다.

이런 류의 문제는 특히 정적 사이트 생성(SSG) 프레임워크에서 자주 나타난다. 프레임워크 수준의 최적화가 런타임 유연성과 항상 맞아떨어지지는 않기 때문이다. 그럼에도 CSS 스코핑의 가치는 충분하니, 예외 케이스를 잘 관리하는 게 핵심이다.


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

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

댓글 0

첫 댓글 달아줘.