누구를 위한 도구인가
코드를 살린 채 API 문서를 Markdown으로 저장
Clean Web Clipper는 코드 블록의 클래스, 부모 요소, 구문 강조기의 마크업에서 언어를 읽어 코드 블록에 적습니다. 9페이지짜리 기술 코퍼스에서 언어 태그는 코드 블록 156개 중 73개에 남았고, 비교한 두 엔진은 20개와 0개였습니다.
클리핑한 문서를 다시 손봐야 하는 이유
문서는 대부분 코드이고, 대부분의 클리퍼가 버리는 것이 바로 코드입니다. 프레임워크 문서나 다시 찾을 답변을 저장해 노트에 붙여 넣으면 모든 코드 블록이 비어 있습니다. js도, bash도, sql도 없습니다. 색이 사라지고, 셸 명령과 JSON 본문을 한눈에 구분하는 가장 빠른 방법도 함께 사라집니다.
나머지 손상은 구조에서 생깁니다. 셀 하나에 코드 예제가 든 표는 한 줄로 무너집니다. 버전 선택기와 “이 페이지의 내용” 사이드바가 본문 한가운데 들어옵니다. 코드 위젯을 감싼 div가 마크업 그대로 남습니다. 이것을 손으로 고치는 데는 기억을 더듬어 노트를 새로 쓰는 것보다 오래 걸리고, 그래서 많은 사람이 문서 클리핑을 그만두고 낡을 때까지 탭을 열어 둡니다.
그 탭이 세 번째 문제입니다. 문서에는 버전이 있지만 URL에는 대개 없습니다. v4용으로 읽은 페이지가 어느새 v6이 되고, 플래그 이름은 바뀌고 옵션 하나는 사라졌는데, 북마크는 여전히 열립니다. 다른 텍스트로요. 노트 어디에도 실제로 어느 버전을 기준으로 개발했는지 남아 있지 않습니다. 머리글에 URL과 페이지 자체의 날짜가 적힌 파일은 1년 뒤에도 그 질문에 답하지만, 북마크는 한 번도 답한 적이 없습니다.
대신 노트에 들어가는 것
- 코드 블록에 태그가 붙어 나옵니다. 태그 없는 블록이 아니라 ```js이므로, 붙여 넣는 순간 Obsidian, VS Code, GitHub에서 구문 강조가 됩니다.
- 언어는 추측하지 않고 읽습니다. 사이트의 구문 강조기가 남긴 클래스에서 가져오므로, 태그는 원본 페이지만큼 정확합니다.
- 셀에 코드가 든 표도 온전하게 남습니다. 기술 코퍼스에서 15개 중 12개가 유지되었고, 비교한 엔진은 각각 7개였습니다.
- 참조 링크는
[^1]각주가 되고 정의는 끝에 모이므로, 명세서의 인용이 노트 안에서도 연결됩니다. - 사이드바와 버전 선택기는 변환되지 않고 잘려 나갑니다. 측정한 페이지 512개 전체에서 남은 HTML 태그는 0개였습니다.
- 추출은 렌더링된 DOM에서 실행되므로, JavaScript로 만든 문서 사이트도 보이는 그대로 캡처됩니다.
- Reddit 스레드는 구조와 댓글별 점수를 유지합니다. 라이브러리에 대한 실제 답변의 절반쯤은 거기에 있습니다.
extraction필드가 어떤 경로를 썼는지 알려 줍니다.dom, 또는 페이지가 텍스트를 구조화 데이터로만 보내고 렌더링하지 않았을 때는jsonld-articlebody.
The JSON API returns some data that looks like this:
```js
[
{ category: "Fruits", price: "$1", stocked: true, name: "Apple" },
{ category: "Vegetables", price: "$2", stocked: true, name: "Spinach" }
]
```
## Step 1: Break the UI into a component hierarchy문서용으로 설정하기
한 번 6분이면 되고, 그 뒤로는 단축키가 알아서 합니다. 기본값은 기사 읽기에 맞춰져 있습니다. 문서에는 다른 파일 이름, 저자 필드 없음, 이미지 없음이 맞습니다.
- 확장 프로그램을 설치하고 아이콘을 툴바에 고정합니다. 아이콘을 마우스 오른쪽 버튼으로 누르고 옵션을 골라 설정을 탭으로 엽니다.
- 아이콘 클릭 동작을 “폴더에 저장”으로 바꿉니다. 이렇게 해야 클립이 창 없이 키 한 번으로 끝납니다. 미리보기 창은 도구를 익히는 동안에는 쓸모 있지만 그 뒤로는 거추장스럽습니다.
- 폴더를 고릅니다. 작업 중인 저장소의
docs/clips처럼 이미 버전 관리하는 디렉터리를 지정하세요. 브라우저가 한 번 확인을 요청하고, 그 프로필에서는 허용을 기억합니다. - 파일 이름 템플릿을
{domain}-{title}로 설정합니다. 프레임워크 네 개가 모두 “Getting started”라는 페이지를 가지고 있어서, 이름에 도메인이 없으면 네 번째 문서는 조용히getting-started-4가 됩니다. - frontmatter 섹션에서
source와extraction은 켜 두고author는 끕니다. 문서에는 서명이 거의 없고, 모든 파일에 있는 빈 필드는 결국 지우게 될 잡음입니다. - 이미지를 제외로 설정합니다. 남의 IDE 스크린숏은 검색할 수 없고, 이미지 링크는 언젠가 옮겨질 CDN을 가리킵니다.
chrome://extensions/shortcuts를 열어Alt+Shift+M이 지정되어 있는지 확인합니다. 다른 확장 프로그램이 가져갔다면 여기서 되찾습니다.
개발자에게 맞는 설정
기본값에서 바꿀 만한 값과, 그 값이 일반적인 읽기가 아니라 문서에서 특히 중요한 이유입니다.
| 설정 | 값 | 여기서 이 값인 이유 |
|---|---|---|
| 아이콘 클릭 | 폴더에 저장 | 하루 스무 번 하는 클립이 스무 번 창을 열어서는 안 됩니다 |
| 폴더 | 저장소 안의 `docs/clips` | 클립도 코드와 같은 도구로 버전 관리, 리뷰, 검색됩니다 |
| 파일 이름 템플릿 | `{domain}-{title}` | 프레임워크 문서는 제목이 겹치지만 도메인은 겹치지 않습니다 |
| 이미지 | 제외 | 스크린숏은 grep할 수 없고, 그 URL은 텍스트보다 빨리 사라집니다 |
| frontmatter | `source`와 `extraction` 켬, `author` 끔 | URL과 경로는 필요하지만 문서 페이지에는 남길 만한 필자가 없습니다 |
| 사이트별 규칙 | `reddit.com` → 하위 폴더 `threads` | 포럼 답변은 공식 문서와 다르게 낡으므로 따로 두는 편이 좋습니다 |
| 단축키 | `Alt+Shift+M` | 키보드에서 손을 떼지 않고 클리핑할 수 있느냐가 하느냐 마느냐를 가릅니다 |
서버를 시작하기 전에 마이그레이션을 실행합니다. ``` ./bin/migrate --env production ``` ```sql SELECT id, created_at FROM sessions WHERE expires_at < now(); ``` 두 번째 블록에는 `class="language-sql"`이 있었습니다. 첫 번째 블록에는 아무것도 없었으므로, 추측한 태그를 붙이지 않고 비워 두었습니다.
세 가지 작업 장면
실제로 기준으로 삼은 버전 고정하기
프레임워크 문서의 v4 브랜치에서 v5에서 이름이 바뀐 설정 플래그 페이지를 읽고 있습니다. Alt+Shift+M을 누릅니다. 파일은 docs/clips에 example-dev-configuration-reference.md로 저장되고, source는 /v4/ URL을 가리키며 머리글에는 페이지가 밝힌 날짜가 있습니다.
8개월 뒤 운영 환경에서 그 플래그가 다르게 동작하는데, 왜 그렇게 설정했는지 아무도 기억하지 못합니다. 클립은 변경과 같은 커밋 범위에 저장소 안에 있고, 어떤 버전의 문서를 기준으로 결정했는지 알려 줍니다. 실제 URL은 이제 v6을 보여 주고 그 플래그는 아예 언급하지 않습니다.
실제로 문제를 해결한 포럼 스레드
공식 문서는 정상 경로만 설명하고, 내 경우의 해결책은 Reddit 스레드의 댓글 네 단계 아래에 있습니다. 채택된 답은 140점이고 그 위에 틀린 답이 30점으로 있습니다. 스레드를 클리핑합니다. 사이트별 규칙이 이를 threads로 보내고, 댓글 구조는 점수가 붙은 중첩 인용문으로 옮겨집니다.
다시 읽을 때 중요한 것은 점수입니다. 스레드를 그냥 복사해 붙여 넣으면 순서 신호가 완전히 사라지고, 커뮤니티가 어느 의견에 동의했는지 알 수 없는 다섯 가지 의견만 다시 읽게 됩니다.
변수 표를 풀 리퀘스트에 바로
배포 가이드에 환경 변수 18개가 담긴 표가 있고, 그중 셀 세 개에는 코드 예제가 있습니다. 페이지에서 표를 선택해 선택 영역을 클리핑하고, Markdown을 풀 리퀘스트 설명에 붙여 넣습니다. 스크린숏이 아니라 GFM 표이므로 GitHub가 표로 렌더링합니다.
표 15개짜리 기술 코퍼스에서 이 직렬화 방식은 12개를 유지했고, 비교한 엔진은 각각 7개였습니다. 범용 변환기를 깨뜨리는 셀이 바로 이런, 코드나 목록이 든 셀입니다.
흔히 쓰는 방법과 비교
아래 방법은 모두 작동하고, 지금 팀의 누군가가 쓰고 있는 방법입니다. 세 번째 열은 솔직한 비용이며, 이 확장 프로그램도 예외가 아닙니다.
| 지금 쓰는 방법 | 얻는 것 | 치르는 비용 |
|---|---|---|
| 탭을 열어 두기 | 페이지 그대로 | 다음 재시작 때 닫히고, 그사이 문서 버전이 바뀝니다 |
| 편집기에 복사해 붙여 넣기 | 텍스트, 가끔 사이드바까지 | 코드 블록은 태그 없이, 표는 한 줄로 들어옵니다 |
| PDF로 인쇄 | 페이지의 고정 레이아웃 사본 | `grep`으로 검색할 수 없고 diff도 안 되며, 쿠키 배너까지 들어갑니다 |
| 북마크 | 클릭 한 번으로 만드는 포인터 | 포인터는 페이지의 오늘 내용을 가리킵니다 |
| 다른 클리핑 확장 프로그램 | 덜 걸러진 Markdown | 109페이지 일대일 비교에서 중복 메뉴 줄 282~491개, 여기서는 102개 |
| Clean Web Clipper | 태그 붙은 코드 블록과 출처 머리글이 있는 Markdown | 한 번에 한 페이지, 크롤러 없음, 이미지 다운로드 없음 |
결과가 제대로 나오지 않을 때
코드 블록에 왜 언어 태그가 없나요?
페이지가 어떤 언어인지 밝히지 않았기 때문입니다. Clean Web Clipper는 사이트의 구문 강조기가 남긴 클래스에서 언어를 읽을 뿐, 코드를 보고 추측하지 않습니다. 클래스 없이 손으로 꾸민 예제는 태그 없는 블록이 되고, 그것이 정직한 결과입니다. 셸 코드에 추측으로 붙인 python 태그는 태그가 없는 것보다 나쁩니다. 구문 강조가 엉뚱한 곳을 자신 있게 칠하기 때문입니다.
가이드의 절반이 왜 빠졌나요?
거의 항상 탭이나 아코디언 때문입니다. 확장 프로그램은 브라우저가 실제로 렌더링한 것을 변환하는데, 클릭해야 내용이 들어가는 탭은 클릭하기 전까지 DOM에 없습니다. 탭을 열고 섹션을 펼친 뒤 클리핑하거나, 변형마다 한 번씩 클리핑하세요. 모든 탭을 렌더링해 두고 CSS로 숨기는 사이트라면 전부 차례로 옮겨집니다.
왜 기사가 없다고 하나요?
API 플레이그라운드, 검색 결과 페이지, 패키지 목록은 대부분 링크 텍스트이고, 확장 프로그램은 이런 페이지를 일부러 거절합니다. 추출된 글자의 약 4분의 1 이상이 링크 안에 있으면 항목 300개를 넘기는 대신 “기사 없음”을 알립니다. 이 거절 때문에 “유용한 텍스트” 비율 점수가 항상 무언가를 돌려주는 엔진보다 낮게 나옵니다.
파일의 extraction: "jsonld-articlebody"는 무슨 뜻인가요?
페이지가 기사 텍스트를 구조화 데이터로 보냈지만 DOM에 렌더링을 끝내지 않아서, 본문을 구조화 데이터에서 읽었다는 뜻입니다. 두 경로의 내용이 다를 수 있어서 숨기지 않고 기록합니다. 구조화 데이터 쪽이 이전 초안일 때도 있고, 유일하게 완전한 버전일 때도 있습니다. 이 값이 보이면 텍스트에 기대기 전에 원본을 한번 확인할 가치가 있습니다.
하지 않는 일
문서 사이트 전체를 크롤링하지 않습니다. 지금 보고 있는 페이지 하나씩 처리합니다. 이미지, 다이어그램 등 바이너리 자산은 내려받지 않으며 이미지 링크는 원래 사이트를 가리킵니다. 태그 없는 코드 블록의 언어를 추측하지 않으므로, 구문 강조기가 클래스를 남기지 않은 페이지에서는 틀린 태그 대신 빈 태그가 나옵니다. 그리고 API 플레이그라운드나 검색 결과처럼 기사 본문이 없는 페이지에서는 링크 300개를 넘기는 대신 “기사 없음”을 알립니다.