콘텐츠로 이동

긴 HTML 문서 만들 때의 실용 팁

작가 교정 리포트(100+페이지 분량)를 Python으로 빌드하면서 부딪힌 두 가지 문제와 해결.

1. 한 줄에 수정 2건 이상 있을 때 — 태그 외부 매칭

문제 상황

교정 HTML에서 본문에 수정이 필요한 구(句)를 형광펜처럼 하이라이트한다. 작가가 "아, 여기 고치라는 거구나" 알아볼 수 있게.

단순 문자열 치환으로 처리하면:

text = text.replace("가면을 벗겨내고", '<span class="hi">가면을 벗겨내고</span>')
text = text.replace("무너지지 않도록", '<span class="hi">무너지지 않도록</span>')

문제: 두 번째 교정을 찾을 때 이미 <span class="hi">가면...</span>이 들어간 문자열 안에서 검색함. class="hi"라는 속성 문자열까지 검색 대상이 됨. 그래서 단순 "텍스트 안에 같은 하이라이트가 이미 있는지" 체크하는 로직을 넣으면 두 번째 교정이 False Positive로 스킵됨.

비유

형광펜으로 문장에 표시를 했는데, 그다음 다른 문장에 표시를 하려고 보니 이미 칠한 부분이 시야에 걸려서 어디 표시해야 할지 헷갈리는 상황. 눈은 "여기 이미 색칠된 거 같은데?" 하고 멈춰버림.

해결: 태그 외부에서만 찾기

문자 단위로 순회하면서 < 만나면 "태그 안쪽" 모드, > 만나면 "태그 바깥" 모드로 바꿔가며, 태그 바깥에서만 매칭 시도.

in_tag = False
i = 0
pos = -1
while i < len(text):
    if text[i] == '<':
        in_tag = True
    elif text[i] == '>':
        in_tag = False
        i += 1
        continue
    if not in_tag and text[i:i+len(target)] == target:
        pos = i
        break
    i += 1

if pos >= 0:
    text = text[:pos] + f'<span class="hi">{target}</span>' + text[pos+len(target):]

핵심은 "이미 태그로 감싼 영역은 통째로 건너뛰는 것". 형광펜 비유로 치면 이미 색칠된 부분은 스킵하고 하얀 부분에서만 표시 자리를 찾는 것.

언제 써먹나

  • 교정 HTML (한 문장에 수정 포인트 2개 이상)
  • 블로그 본문에 키워드 자동 하이라이트
  • 검색 결과에 검색어 강조 표시
  • 튜토리얼 문서에 코드 구문 강조

2. 긴 문서에서 현재 위치 사이드바에 표시 — 스크롤 스파이

문제 상황

교정 리포트가 15개 장 × 세로 스크롤 수천 줄. 사이드바에 장별 목차 있어도 지금 내가 몇 장을 보고 있는지 헷갈림.

비유

유튜브 영상에서 타임스탬프 목차 있을 때, 현재 재생 중인 챕터가 파란색으로 자동 하이라이트되는 걸 본 적 있을 거야. 그거랑 똑같은 기능을 긴 HTML 문서에 붙이는 것.

해결

스크롤 이벤트 감지 + 뷰포트 상단 120px 기준선보다 위에 있는 가장 마지막 섹션 = 현재 보고 있는 장.

function onScroll() {
    const y = 120;  // 기준선
    let current = targets[0];
    for (const t of targets) {
        const rect = t.getBoundingClientRect();
        if (rect.top <= y) current = t;
        else break;
    }
    setActive(current.id);
}
window.addEventListener('scroll', onScroll, { passive: true });

그리고 CSS로 활성화된 링크 스타일 지정:

nav a { transition: background 0.15s, color 0.15s; }
nav a.active { background: #3498db; color: white; font-weight: bold; }

보너스: 사이드바가 길어서 활성 링크가 스크롤 밖에 있으면 자동 스크롤로 중앙에 맞춰줌.

if (lr.top < nr.top || lr.bottom > nr.bottom) {
    link.scrollIntoView({ block: 'center' });
}

언제 써먹나

  • 긴 가이드 문서 (Docsify, MkDocs 같은 거 기본 내장)
  • 강의 자료 HTML
  • 이번처럼 자작 리포트 HTML
  • 블로그 긴 글의 목차 사이드바

정리

둘 다 "긴 HTML 문서를 사람이 보기 편하게 만드는 장치". 한 번 만들어두면 다음 리포트에서도 그대로 가져다 쓸 수 있음.

레퍼런스: 작업/30기 이은지 님/build_proofread.py (2026-04-20 기준) 관련 메모리: proofread_html_refinements.md