일상 및 경험 팁/일상 속 정보·경험·팁

HTML 설정 만으로 티스토리 자동 목차 생성하기 (별도 파일/서식 설정 X)

로브로브 2024. 11. 22. 00:50

한 번 세팅 만으로 목차 생성 신경끄고 싶은 분에게

HTML 설정 만으로 티스토리 자동 목차 생성하기

작성 계기 - 미래에 또 실수할 나를 위하여

 팁만 보실 분은 바로 목차에서 목차 생성하기 란으로 가시면 됩니다. 이 글의 작성 계기는 심플합니다. 저 또한 티스토리 글쟁이로서 목차 생성기를 세팅해두고 있었습니다. 다만, 글쓰는 것도 귀찮은데 하나하나 세팅하긴 귀찮아서 찾아보다가 어느 은둔의 티스토리에서 HTML 만으로 세팅하는 방법을 보았죠. 그 후로 약간 조악하지만 편하게 목차를 설정해서 신경 안 쓰고 살았습니다. ...만 며칠 전 사건이 터졌죠. 난생 처음 티스토리 스킨을 변경해 보았습니다. 북클럽 스킨이 참 이뻐 보이더군요. 그리고 목차 HTML 코드를 날려 먹었죠.  스킨을 바꾸면 부가적으로 변경한 HTML이 증발한다는 사실을 새로이 깨닫게 되었습니다.

그래서 다른 사람들 쓴 팁을 찾아봤는데

 제가 쓰는 방식이랑 영 안 맞습니다. 뭐를 깔아야하고, 파일 등록하고, 서식에서 갖다쓰고... 전 그런거 꾸미는 거 별로 안 좋아하는 공돌이라서요.. 생각보다 잘 적용되지도 않고요. 그래서 챗지피티한테 만들어 달라고 빌었습니다. 그러니 하나 만들어 주더군요. 여기서 글씨 크기 등을 손보고, 챗지피티의 제안에 따라 [숨기기] 버튼도 만들었답니다. 모바일 기기에서 볼 때도 문제없도록 반응형 디자인으로 만들었구요. 누군가에게 도움이 되길바라며, 언젠가 또 실수할 나를 위한 보험이 되기 위하여 기록을 남깁니다.

제가 작성한 다른 글에 적용된 목차 디자인


티스토리 자동메뉴 HTML 코드와 그 적용 방법 ★★★

  사실 이 것만 보러 오신 거 다 압니다. 시작하시죠.

 ※ 해당 HTML 코드는 " Book Club " 스킨 기준으로 작성되었습니다.

1) 티스토리 스킨 편집으로 이동

  1. 티스토리 관리자 화면에 로그인합니다.
  2. 왼쪽 메뉴에서 꾸미기 → 스킨 편집으로 이동합니다.
  3. HTML 편집 화면을 엽니다.

2) 코드 삽입

 1. HTML 편집 화면에서 다음을 찾습니다:  </body>, <head> 

  이 글에서는 2개의 태그를 삽입합니다. <script>와 <style> 입니다.

  • <script> 태그는 </body> 태그 바로 위에 삽입합니다.
  • <style> 태그는 <head> 태그 안 또는 CSS 파일 끝부분에 삽입합니다.
태그 권장 위치 이유
<script> </body> 태그 바로 위 DOM 요소가 모두 로드된 후 스크립트 실행 및 렌더링 차단 방지
<style> <head> 태그 안 또는 CSS 파일 끝 페이지 스타일 즉시 적용 및 커스터마이징 스타일 우선 적용

 

 ① <script>  스크립트 삽입:

아래의 스크립트를 HTML 파일의 </body> 태그 바로 위에 추가합니다.

<!-- 목차 자동 생성 스크립트 -->
<script>
document.addEventListener('DOMContentLoaded', function () {
    const postContent = document.querySelector('.tt_article_useless_p_margin'); // 본문 컨테이너 선택
    if (!postContent) return; // 본문이 없을 경우 실행 중지

    const tocContainer = document.createElement('div');
    tocContainer.id = 'table-of-contents';
    tocContainer.innerHTML = `
    <h2>Contents <button id="toggle-toc">[숨기기]</button></h2>
    <ul></ul>
`;

    const headings = postContent.querySelectorAll('h1, h2, h3'); // h1, h2, h3 태그를 탐색
    const ul = tocContainer.querySelector('ul');

    headings.forEach((heading, index) => {
        const id = `section-${index}`;
        heading.id = id; // 각 제목에 고유 ID 부여
        const li = document.createElement('li');
        li.classList.add(`toc-level-${heading.tagName.toLowerCase()}`); // 계층 구분 클래스 추가
        li.innerHTML = `<a href="#${id}">${heading.textContent}</a>`;
        ul.appendChild(li);
    });

    if (headings.length > 0) {
        postContent.prepend(tocContainer); // 본문 상단에 목차 삽입
    }

    // 숨기기/펼치기 버튼 기능
    const toggleButton = document.getElementById('toggle-toc');
    const tocList = tocContainer.querySelector('ul');
    toggleButton.addEventListener('click', function () {
        if (tocList.style.display === 'none') {
            tocList.style.display = 'block';
            toggleButton.textContent = '[숨기기]';
        } else {
            tocList.style.display = 'none';
            toggleButton.textContent = '[펼치기]';
        }
    });
});
</script>

 

 

② <style> 삽입:

아래의 스타일 코드를 HTML <head> 안에, 또는 CSS 파일 끝부분에 추가합니다.

  → 저는 <head> 와 </head> 사이에 붙여넣었습니다.

<!-- 목차 스타일 -->
<style>
#table-of-contents {
    border: 1px solid #ddd;
    padding: 15px;
    margin-bottom: 20px;
    background: #f9f9f9;
    font-size: 14px; /* 목차 내용 글씨 크기 */
    line-height: 1.6;
}

#table-of-contents h2 {
    font-size: 16px; /* 목차 제목 글씨 크기 조정 */
    margin-bottom: 10px;
    margin-left: 20px; /* 제목 앞 공백 추가 */
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #333;
}

#table-of-contents button {
    background: none;
    border: none;
    color: #007BFF;
    cursor: pointer;
    font-size: 0.9em;
    padding: 0;
}

#table-of-contents button:hover {
    text-decoration: underline;
}

#table-of-contents ul {
    padding-left: 20px;
    list-style: none;
}

#table-of-contents ul li {
    margin-bottom: 5px;
}

#table-of-contents ul li a {
    text-decoration: none;
    color: #007BFF;
}

#table-of-contents ul li a:hover {
    text-decoration: underline;
    color: #0056b3;
}

/* 계층별 들여쓰기 */
#table-of-contents .toc-level-h1 {
    font-weight: bold;
    margin-left: 0;
    list-style-type: disc; /* ● 표시 */
}

#table-of-contents .toc-level-h2 {
    margin-left: 15px;
    list-style-type: circle; /* ○ 표시 */
}

#table-of-contents .toc-level-h3 {
    margin-left: 30px;
    list-style-type: square; /* ■ 표시 */
}

/* 반응형 디자인 */
@media (max-width: 768px) {
    #table-of-contents {
        font-size: 12px;
        padding: 10px;
    }

    #table-of-contents ul li {
        margin-bottom: 3px;
    }
}
</style>

 

 

③ 저장 후 확인:

코드를 삽입한 후, 저장하고 블로그 글 페이지를 새로고침(F5)하여 목차가 표시되는지 확인합니다.


코드 구성 설명

 챗지피티가 어떤 구성으로 우리에게 이 코드를 제시했는지 설명한 부분입니다. 귀찮으시면 넘어가셔도 무방합니다.

 

2-1. 목차 자동 생성 스크립트

  • document.addEventListener: HTML 문서가 모두 로드된 후 스크립트를 실행합니다.
  • postContent.querySelectorAll('h1, h2, h3'): 본문에서 h1, h2, h3 태그를 검색해 목차 항목을 만듭니다.
  • postContent.prepend(tocContainer): 생성된 목차를 본문 상단에 삽입합니다.
  • 숨기기 버튼 기능: [숨기기] 클릭 시 목차가 접히고, 버튼 이름이 [펼치기]로 변경됩니다.

2-2. 목차 스타일

  • #table-of-contents: 목차 전체 스타일을 정의합니다 (테두리, 배경, 글씨 크기 등).
  • h2: 목차 제목(Contents)의 글씨 크기와 위치를 정의합니다.
  • ul 및 li: 목차의 계층 구조와 각 항목의 들여쓰기, 간격을 설정합니다.
  • 계층별 클래스:
    • toc-level-h1 → ●, toc-level-h2 → ○, toc-level-h3 → ■.

2-3. 반응형 디자인

  • @media (max-width: 768px): 화면 크기가 768px 이하일 때 목차의 글씨 크기를 줄이고, 여백을 조정합니다.

 


결과 예시

해당 코드 사용시 어떻게 나오는지 제시된 내용입니다. 실제 적용 사례는 글 처음에 사진으로 붙여두었죠.

PC 화면에서

Contents  [숨기기]
● 대제목 1
    ○ 중제목 1.1
        ■ 소제목 1.1.1
    ○ 중제목 1.2
● 대제목 2
    ○ 중제목 2.1

 

모바일 화면에서

- 글씨 크기와 여백이 줄어들어 화면에 최적화된 목차가 표시됩니다.

- 숨기기 버튼은 그대로 작동합니다.

 

 


유의점 및 해결 방안

 위 코드로 목차를 생성할 때 발생 가능한 문제점과 그 대응 입니다. 해당 문제 발생하였거나 수정 원할시 제가 올린 코드에서 해당 부분을 수정하거나 추가하시면 됩니다. 사실 미래의 저를 위해 남겨둔 내용입니다.

1. 스킨 구조에 따라 본문 클래스가 다를 수 있음 ☆

 티스토리에서 사용하는 스킨(블로그 디자인 템플릿)은 각 스킨마다 HTML 구조와 클래스명이 다릅니다. 목차 스크립트는 본문을 특정 클래스명(.tt_article_useless_p_margin)으로 선택해서 동작하는데, 사용하는 스킨의 본문 클래스명이 다르면 목차가 제대로 생성되지 않습니다.

 

문제의 원인

  1. HTML 구조가 스킨마다 다름:
    티스토리 스킨은 기본적으로 본문 영역을 포함하지만, 본문 영역을 감싸는 요소의 클래스명이 스킨마다 다릅니다.
    예) .tt_article_useless_p_margin / .article-content / .entry-content
  2. 선택자가 잘못된 경우 발생하는 문제:
    스크립트가 document.querySelector('.tt_article_useless_p_margin')를 사용하여 본문 컨테이너를 찾지만, 실제 스킨의 본문 클래스명이 다르면 스크립트가 동작하지 않음.

본문 클래스 확인 방법

Step 1: 블로그 글 화면 열기

  • 티스토리 블로그에서 목차를 적용하려는 글을 엽니다.

Step 2: 개발자 도구 열기

  • 브라우저의 개발자 도구(Developer Tools)*를 엽니다.
    • 단축키:
      • Chrome: Ctrl + Shift + I (Windows) 또는 Cmd + Option + I (Mac)
      • Edge/Firefox: F12

Step 3: 본문 영역 선택

1) 개발자 도구에서 돋보기 아이콘(Inspect Element)를 클릭합니다.


크롬으로 개발자 도구를 볼 경우
크롬으로 개발자 도구를 볼 경우 해당 버튼을 누르시면 됩니다.

2) 블로그 본문 영역 위로 마우스를 가져가면 HTML 요소가 강조 표시됩니다.

3) 강조된 HTML 태그를 확인합니다.

 

Step 4: 클래스명 확인

- 선택된 HTML 태그의 class 속성을 찾습니다. 예를 들어:

<div class="article-content">
    <h1>대제목</h1>
    <p>본문 내용...</p>
</div>

- 여기서 class="article-content"가 본문 클래스명입니다.

 본문 클래스 명을 확인하였으면, 코드 내의 [.tt_article_useless_p_margin] 부분을 해당하는 클래스 명으로 변경하여 줍니다.


2. 글에 제목 태그(h1, h2, h3)가 없을 경우 목차가 생성되지 않음

 제목 태그가 없으면 목차가 생성되기 어려운 건 다른 코드도 마찬가지이므로 제목 태그를 활용합시다. 티스토리에서 제목태그는 단순히 글 작성시 제목1/제목2/제목3 설정하시면 됩니다.

유의점:

  • 글에 h1, h2, h3 태그가 없다면 목차가 빈 상태로 표시되거나 생성되지 않습니다.

해결 방안:

1) 글 작성 시 제목 태그 사용:

 - 제목은 h1, h2, h3 태그로 작성합니다.

 - 예: 글 작성 화면에서 제목1, 제목2, 제목3 스타일을 활용합니다.

2) 태그 없는 경우 안내 표시 추가: - 스크립트에 목차가 없을 때 안내 문구를 표시하도록 수정합니다:

if (headings.length === 0) {
    tocContainer.innerHTML = `<h2>Contents</h2><p>목차를 생성할 제목이 없습니다.</p>`;
    postContent.prepend(tocContainer);
}

3. 긴 목차로 인해 디자인이 깨질 수 있음

유의점:

  • 제목이 너무 많거나 길면 목차가 페이지 디자인을 넘어가거나 가독성이 떨어질 수 있습니다.

해결 방안:

 

1) 목차 스크롤 기능 추가:

#table-of-contents ul {
    max-height: 300px; /* 최대 높이 설정 */
    overflow-y: auto; /* 스크롤 추가 */
}

 

2) 긴 제목 줄임 표시: 제목이 너무 길 경우 텍스트를 생략 표시(...)로 처리합니다:

#table-of-contents ul li a {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

4. 모바일에서 목차가 작동하지 않거나 보기 어려움

 반응형 디자인을 추가하시면 됩니다. 제가 공유드린 코드엔 이미 적용되어 있습니다.

 

유의점:

  • 모바일 화면에서 목차가 화면에 맞게 조정되지 않을 수 있습니다.
  • 숨기기/펼치기 버튼이 너무 작게 보일 수도 있습니다.

해결 방안:

 1) 반응형 디자인 추가 : CSS에 모바일 전용 스타일을 추가합니다:

@media (max-width: 768px) {
    #table-of-contents {
        font-size: 12px; /* 글씨 크기 축소 */
        padding: 10px;
    }
    #table-of-contents ul {
        max-height: 200px; /* 스크롤 높이 제한 */
    }
}

 

 2) 숨기기 버튼 크기 조정숨기기 버튼 크기를 키워 터치가 용이하도록 수정합니다:

#table-of-contents button {
    font-size: 1em; /* 버튼 크기 조정 */
    padding: 5px 10px;
}

 


5. SEO(검색 엔진 최적화)와의 충돌

유의점:

  • 목차에 추가한 ID가 검색 엔진 최적화(SEO)에 영향을 미칠 수 있습니다.
  • 중복된 제목으로 인해 동일한 ID가 여러 번 생성될 가능성도 있습니다.

해결 방안:

1) ID 중복 방지: ID를 생성할 때 제목 텍스트를 포함해 고유하게 만듭니다.

const id = `${heading.textContent.replace(/\s+/g, '-').toLowerCase()}-${index}`;
heading.id = id;

 

2) SEO 최적화 확인: 목차가 SEO에 긍정적인 영향을 줄 수 있도록 제목과 목차 링크의 내용이 일치하도록 작성합니다.


6. 특정 스킨에서 목차 디자인이 어울리지 않음

유의점:

  • 목차의 색상, 글씨 크기, 배경 등이 스킨의 디자인과 조화롭지 않을 수 있습니다.

해결 방안:

1) 목차 스타일 커스터마이징: CSS에서 색상과 스타일을 수정합니다:

#table-of-contents {
    border: 2px solid #ccc; /* 테두리 색상 조정 */
    background: #fff;      /* 배경색 조정 */
    color: #000;           /* 글씨 색상 조정 */
}

 

2) 목차 숨김 설정: 목차를 기본적으로 숨겨두고 버튼 클릭 시 표시되도록 설정합니다:

#table-of-contents ul {
    display: none;
}

7. 특수문자 포함 제목의 링크가 잘못 동작

유의점:

  • 제목에 특수문자(예: &, %, !)가 포함되면 목차 링크가 제대로 작동하지 않을 수 있습니다.

해결 방안:

 - 특수문자 제거 후 ID 생성: 제목에서 특수문자를 제거하고 ID를 생성합니다: 

const id = `section-${index}-${heading.textContent.replace(/[^a-zA-Z0-9가-힣]/g, '')}`;
heading.id = id;

8. 목차 생성 성능 문제

유의점:

  • 글의 제목이 많거나 페이지가 길면 목차 생성에 시간이 오래 걸릴 수 있습니다.

해결 방안:

1) 대상 태그 제한: h2, h3만 포함하도록 태그를 제한합니다: 

const headings = postContent.querySelectorAll('h2, h3');

2) 페이지 로드 속도 확인: 목차가 표시되는 데 오래 걸린다면 스크립트를 최적화하거나, 목차 생성을 비동기적으로 처리합니다.