마크다운 목차 링크가 안 눌리는 이유와 해결 방법

마크다운 목차 링크가 작동하지 않나요? 헤딩(제목)을 링크로 만드는 규칙이 GitHub, 벨로그, 티스토리 등 플랫폼마다 다르기 때문입니다. 앵커 슬러그 생성 원리를 이해하고 어떤 환경에서든 작동하는 목차를 만드는 법을 알려드립니다.

목차 링크가 안 눌리는 이유: 앵커(Anchor) 규칙이 달라서

분명히 마크다운으로 목차를 만들었는데, 링크가 먹통입니다. 미리보기에서는 잘 눌리던 것이 블로그나 GitHub에 올리고 나니 클릭해도 아무 반응이 없습니다. 또는 URL 주소창에 `#some-text`가 붙기는 하는데, 해당 위치로 스크롤되지 않습니다.

정확히 당신이 겪는 그 문제입니다. 결론부터 말하면, 당신의 잘못이 아니라 마크다운을 HTML로 변환하는 '엔진'이 플랫폼마다 다르기 때문에 생기는 현상입니다.

목차의 링크는 페이지 내부의 특정 제목으로 이동하는 '앵커(Anchor) 링크'입니다. `[이동할 제목](#anchor-slug)` 형태의 링크를 클릭하면, 페이지 안에서 `<h2 id="anchor-slug">이동할 제목</h2>` 처럼 같은 `id` 값을 가진 요소로 화면이 스크롤됩니다. 여기서 `#` 뒤에 붙는 고유 주소를 '슬러그(slug)'라고 부릅니다.

문제는 바로 이 '슬러그'를 만드는 규칙이 표준화되어 있지 않다는 점입니다. `## 나의 멋진 제목!` 이라는 마크다운 헤딩을 어떤 플랫폼은 `#나의-멋진-제목`으로 바꾸고, 다른 플랫폼은 `#%EB%82%98%EC%9D%98-%EB%A9%8B%EC%A7%84-%EC%A0%9C%EB%AA%A9`으로 바꿉니다. 또 다른 곳은 아예 상관 없는 `#h-123` 같은 ID를 붙이기도 합니다. 내가 만든 목차의 슬러그와 플랫폼이 실제로 생성한 슬러그가 다르니, 링크가 작동하지 않는 것입니다.

플랫폼마다 다른 앵커 슬러그 생성 규칙

GitHub의 슬러그 생성 규칙은 구체적으로 다음과 같습니다.

1. 모든 영문자를 소문자로 바꿉니다.

2. 한글, 영문자, 숫자, 공백, 하이픈(-)을 제외한 모든 특수문자를 제거합니다.

3. 연속된 공백을 하이픈(-) 하나로 바꿉니다.

4. 만약 동일한 슬러그가 이미 있다면, 뒤에 `-1`, `-2` 같은 숫자를 붙여 고유하게 만듭니다.

이 규칙을 알고 있으면 링크가 왜 깨지는지, 어떻게 고쳐야 할지 예측할 수 있습니다. 예를 들어 티스토리는 예측 불가능한 ID를 쓰므로, GitHub 스타일로 만든 목차는 당연히 작동하지 않습니다.

원본 헤딩 텍스트GitHub, NotionVelogTistory (구 에디터)
`## 한글 제목``#한글-제목``#한글-제목`고유 ID (`#h_1` 등)
`## Title with UPPERCASE``#title-with-uppercase``#title-with-uppercase`고유 ID
`## 특수문자!?& 포함``#특수문자-포함` (대부분 제거됨)`#특수문자-포함`고유 ID
`## 중복 제목` (첫 번째)`#중복-제목``#중복-제목`고유 ID
`## 중복 제목` (두 번째)`#중복-제목-1` (-1, -2... 접미사)`#중복-제목-1`다른 고유 ID

도구 없이 직접 확인하고 수정하기

가장 확실한 방법은 글을 올릴 플랫폼이 실제로 어떤 `id`를 생성하는지 직접 확인하고, 그 값으로 목차 링크를 수정하는 것입니다. 조금 번거롭지만 원리를 이해하는 데 도움이 됩니다.

  1. 글을 원하는 플랫폼(블로그, GitHub 등)에 먼저 발행하거나 임시저장합니다.
  2. 발행된 페이지에서 목차로 연결하고 싶은 제목을 찾습니다.
  3. 해당 제목에 마우스 커서를 올리고 오른쪽 버튼을 클릭한 뒤, '검사(Inspect)'를 선택해 개발자 도구를 엽니다.
  4. 개발자 도구에 해당 제목의 HTML 태그(h1, h2 등)가 보입니다. 태그의 `id` 속성값을 찾아 복사합니다. 이 값이 바로 해당 제목의 진짜 앵커 주소입니다.
  5. 마크다운 문서로 돌아와, 목차 링크를 `[제목](#여기에-id값-붙여넣기)` 형태로 수정합니다.
이 방법은 정확하지만 제목을 바꾸거나 글 순서를 편집할 때마다 매번 `id`를 다시 확인하고 수정해야 합니다. 특히 티스토리처럼 글을 저장할 때마다 `id`가 임의로 바뀌는 플랫폼에서는 사실상 유지보수가 불가능합니다.

마크다운 목차 생성기로 한번에 해결하기

플랫폼별 규칙을 외우거나 매번 개발자 도구를 열어보는 것은 비효율적입니다. 그래서 필요한 것이 바로 앵커 링크 규칙에 맞춰 목차를 자동으로 만들어주는 도구입니다.

툴즈의 '마크다운 목차 생성기'는 가장 널리 쓰이는 GitHub의 규칙에 맞춰 앵커 링크가 포함된 목차를 즉시 생성합니다. GitHub Flavored Markdown을 지원하는 대부분의 환경에서 이 목차는 그대로 작동합니다.

사용법은 간단합니다. 마크다운 원문을 왼쪽에 붙여넣으면, 오른쪽에 바로 목차가 만들어집니다. 화면 하단의 '헤딩 구조' 표를 보면 각 제목(H1, H2...)이 어떤 '앵커 슬러그'로 변환되었는지 한눈에 확인할 수 있어, 링크가 깨졌을 때 원인을 파악하기도 쉽습니다.

만약 중복된 제목이 있다면 GitHub와 동일하게 슬러그 뒤에 `-1`, `-2`를 자동으로 붙여주며, '깊이' 옵션으로 H2~H3까지만 목차에 포함하는 등 세밀한 제어도 가능합니다.

툴즈의 목차 생성기는 GitHub 방식을 따릅니다. 만약 글을 올릴 플랫폼이 티스토리처럼 독자적인 앵커 규칙을 쓴다면, '앵커 링크' 옵션의 체크를 끄고 링크가 없는 텍스트 목록만 생성해서 사용하는 것이 좋습니다.

만든 목차가 잘 작동하는지 미리 확인하기

목차를 포함한 마크다운 문서를 작성했다면, 발행하기 전에 링크가 잘 작동하는지 테스트해보고 싶을 겁니다. 온라인 마크다운 편집기는 대부분 자체 미리보기 기능을 제공하며, 툴즈에도 이런 도구가 있습니다.

툴즈의 '마크다운 미리보기'에 목차와 본문이 모두 포함된 전체 마크다운을 붙여넣으세요. 오른쪽 '미리보기' 창에 렌더링된 결과가 나타납니다. 여기서 목차의 각 항목을 클릭했을 때 해당 제목으로 정확히 스크롤되는지 확인하면 됩니다.

이 미리보기 화면은 GitHub 방식 앵커를 기준으로 작동합니다. 만약 미리보기에서는 잘 되는데 내 블로그에 올렸을 때 안 된다면, 그것이 바로 당신의 블로그가 GitHub와 다른 앵커 규칙을 사용한다는 확실한 증거입니다. 그럴 때는 앞서 설명한 대로 해당 플랫폼의 `id`를 직접 확인하여 링크를 수정해야 합니다.

자주 묻는 질문

GitHub에서는 되는데 왜 Velog나 Tistory에서는 안 되나요?

앵커 링크(슬러그) 생성 규칙이 플랫폼마다 다르기 때문입니다. GitHub는 'my-title-1'처럼 예측 가능한 슬러그를 만들지만, Tistory는 'entry-long-id-cfile...-h-2'처럼 고유하지만 예측 불가능한 ID를 부여합니다. Velog는 GitHub와 거의 유사하지만 미세한 차이가 있을 수 있습니다. 따라서 한 플랫폼 기준으로 만든 목차가 다른 플랫폼에서 작동하지 않는 것은 흔한 현상입니다.

링크 없는 순수 텍스트 목차만 만들고 싶습니다.

툴즈의 '마크다운 목차 생성기'에서 '앵커 링크' 옵션의 체크를 해제하면 됩니다. 그러면 `[제목](#slug)` 형태의 링크 대신 '제목'이라는 순수 텍스트로만 목록이 생성됩니다. 생성된 목록을 복사해 수동으로 링크를 추가하거나, 단순 개요로 사용할 때 유용합니다.

한글 제목도 앵커 링크로 만들 수 있나요?

네, 문제없습니다. GitHub를 포함한 대부분의 최신 마크다운 플랫폼은 한글을 앵커 링크로 잘 처리합니다. 예를 들어 '## 안녕 세상'은 '#안녕-세상'과 같이 변환됩니다. 다만 아주 오래된 시스템에서는 한글 인코딩 문제로 링크가 깨질 수 있으나, 현재 널리 쓰이는 GitHub, Notion, Velog 등에서는 잘 작동합니다.

제목에 특수문자가 들어가면 링크는 어떻게 되나요?

대부분의 특수문자(!, ?, ., & 등)는 앵커 슬러그 생성 과정에서 제거됩니다. 보통 영문, 숫자, 한글, 공백, 하이픈(-), 밑줄(_) 정도만 남기고 나머지는 사라집니다. 예를 들어 '## Q&A 정리!'라는 제목은 '#qa-정리'와 같이 변환됩니다. 이 때문에 특수문자만 다른 여러 제목이 결국 같은 앵커 링크를 갖게 될 수 있으니 주의해야 합니다.