LlamaIndex가 만든 오픈소스 프로젝트 LiteParse는 PDF에서 텍스트를 추출하는 Node.js CLI 도구입니다. 이 글에서는 LiteParse가 Node.js 환경에서 사용하는 라이브러리를 최대한 그대로 활용해, 브라우저에서도 완전히 동작하는 버전을 구현한 과정을 소개합니다.
반가운 점은 LiteParse가 AI 모델 없이 동작한다는 것입니다. 전통적인 PDF 파싱 방식을 사용하며, 텍스트 대신 이미지로 저장된 PDF의 경우 Tesseract OCR(또는 다른 플러그인 OCR 엔진)을 통해 처리합니다.
LiteParse가 해결하는 핵심 과제는, 제각각인 PDF 레이아웃에도 불구하고 텍스트를 올바른 순서로 추출하는 것입니다. LiteParse 팀은 이를 "공간 기반 텍스트 파싱(spatial text parsing)"이라 부르는데, 다단 레이아웃 같은 구조를 감지하는 영리한 휴리스틱을 활용해 텍스트를 자연스러운 선형 흐름으로 묶어 반환합니다.
LiteParse 문서에는 바운딩 박스를 활용한 시각적 인용(Visual Citations with Bounding Boxes) 구현 패턴이 소개되어 있습니다. PDF에서 질문에 답변할 때, 관련 이미지를 잘라내고 강조 표시해 함께 제공하는 방식은 RAG 기반 Q&A의 신뢰도를 높이는 훌륭한 방법이라고 생각합니다.
LiteParse는 에이전트가 사용할 수 있도록 설계된 순수 CLI 도구입니다. 사용 방법은 다음과 같습니다:
npm i -g @llamaindex/liteparse
lit parse document.pdf
저는 Claude와 함께 기능을 직접 탐색해보면서, 굳이 CLI 앱으로만 남아야 할 이유가 없다는 결론을 금방 내렸습니다. LiteParse는 PDF.js와 Tesseract.js를 기반으로 만들어졌는데, 두 라이브러리 모두 제가 예전에 브라우저 환경에서 비슷한 용도로 사용해본 적 있는 것들이었습니다.
LiteParse에 브라우저 전용 버전이 없었던 이유는 단 하나, 아직 아무도 만들지 않았기 때문이었습니다...
https://simonw.github.io/liteparse/에서 LiteParse 웹 버전을 직접 사용해보세요. 모든 처리가 브라우저에서 실행됩니다. 아래는 실제 화면입니다:

OCR 실행 여부와 관계없이 사용할 수 있으며, 원하면 PDF 각 페이지의 이미지를 페이지 하단에 함께 표시할 수도 있습니다.
개발은 아이폰의 일반 Claude 앱에서 시작했습니다. LiteParse를 직접 써보고 싶어서, 마침 폰에 있던 PDF 파일을 업로드하고 다음과 같이 프롬프트를 입력했습니다:
Clone https://github.com/run-llama/liteparse and try it against this file
요즘 일반 Claude 채팅은 GitHub에서 직접 클론할 수 있고, 기본 설정상 대부분의 인터넷에는 접근할 수 없지만 PyPI와 npm에서 패키지를 설치하는 것은 가능합니다.
저는 이 방식을 새로운 오픈소스 소프트웨어를 빠르게 테스트하는 용도로 자주 활용합니다. 노트북을 꺼낼 필요 없이 폰으로 간단히 사용해볼 수 있어서 편리합니다.
전체 대화 내용은 공유된 Claude 대화록에서 확인하실 수 있습니다. 동작 방식에 대해 몇 가지 추가 질문을 하다가 이렇게 물어봤습니다:
Does this library run in a browser? Could it?
Claude의 답변이 충분히 구체적이어서 실제로 구현해볼 만하다는 확신이 생겼습니다. 곧바로 노트북을 열고 Claude Code로 전환했습니다.
GitHub에서 원본 저장소를 포크하고 로컬에 클론한 뒤, 새 web 브랜치를 만들고 Claude의 마지막 답변을 notes.md 파일에 붙여넣었습니다. 그런 다음 Claude Code에 이렇게 입력했습니다:
Get this working as a web app. index.html, when loaded, should render an app that lets users open a PDF in their browser and select OCR or non-OCR mode and have this run. Read notes.md for initial research on this problem, then write out plan.md with your detailed implementation plan
이런 종류의 프로젝트는 항상 계획 수립부터 시작하는 편입니다. Claude의 "플래닝 모드"를 쓸 때도 있지만, 이번엔 계획을 저장소에 아티팩트로 남겨두고 싶어서 plan.md 파일로 바로 작성하도록 했습니다.
이렇게 하면 Claude와 함께 계획을 다듬어 나갈 수 있습니다. 확인해보니 Claude가 PDF 이미지 스크린샷 생성을 건너뛰고 "canvas-encode swap"을 v2로 미루려 했습니다. 그래서 다음과 같이 프롬프트를 입력해 수정했습니다:
Update the plan to say we WILL do the canvas-encode swap so the screenshots thing works
몇 번의 짧은 추가 프롬프트를 거친 끝에, 실제 구현에 들어가도 되겠다는 판단이 선 plan.md가 완성됐습니다.
이렇게 프롬프트를 입력했습니다:
build it.
이후로는 Claude Code가 알아서 작업하도록 두고, 다른 프로젝트를 손보거나 Duolingo를 하면서 가끔씩 진행 상황만 확인했습니다.
작업 중에 프롬프트를 몇 개 더 추가했습니다. 내보낸 대화록에는 아직 표시되지 않지만, 해당 ~/.claude/projects/ 폴더에서 rg queue-operation --no-filename | grep enqueue | jq -r '.content'를 실행하면 추출할 수 있습니다.
주요 추가 프롬프트와 간략한 설명입니다:
When you implement this use playwright and red/green TDD, plan that too — 레드/그린 TDD에 대해서는 이 글에서 자세히 다뤘습니다.let's use PDF.js's own renderer (pdfium을 사용하려 했음)The final UI should include both the text and the pretty-printed JSON output, both of those in textareas and both with copy-to-clipboard buttons - it should also be mobile friendly — UI 동작 방식에 대한 새로운 아이디어가 생겼습니다small commits along the way — 아래 참고Make sure the index.html page includes a link back to https://github.com/run-llama/liteparse near the top of the page — 이런 프로젝트에서는 의존성 출처를 명확히 표기하는 것이 중요합니다!View on GitHub → is bad copy because that's not the repo with this web app in, it's the web app for the underlying LiteParse libraryRun OCR should be unchecked by defaultWhen I try to parse a PDF in my browser I see 'Parse failed: undefined is not a function (near '...value of readableStream...') — Chrome의 Playwright로 테스트하고 있었는데, Safari에서 버그가 발견됐습니다... oh that is in safari but it works in chromeWhen "Copy" is clicked the text should change to "Copied!" for 1.5s[Image #1] Style the file input so that long filenames don't break things on Firefox like this - in fact add one of those drag-drop zone UIs which you can also click to select a file — 사소한 UI 문제의 스크린샷을 첨부하는 방식이 생각보다 잘 통합니다Tweak the drop zone such that the text is vertically centered, right now it is a bit closer to the topit breaks in Safari on macOS, works in both Chrome and Firefox. On Safari I see "Parse failed: undefined is not a function (near '...value of readableStream...')" after I click the Parse button, when OCR is not checked — Safari에서 여전히 작동하지 않았습니다...works in safari now — 문제를 명확히 짚어주고 Playwright에서 해당 브라우저로 테스트하도록 하니 꽤 빠르게 수정됐습니다"중간중간 작은 단위로 커밋하기"를 습관적으로 요청하게 됐습니다. 나중에 코드를 파악하거나 리뷰할 때 훨씬 수월하고, 에이전트가 더 효율적으로 작동하는 데도 도움이 된다는 막연한 직감도 있습니다. 계획을 세우고 한 번에 하나의 문제에 집중하도록 유도하는 효과도 있고요.
작업 중에 진행 중인 버전을 직접 확인해보고 싶어졌습니다. 같은 디렉터리를 대상으로 별도의 Claude Code 세션을 열어 실행 방법을 물어봤더니 npx vite를 사용하라고 알려줬습니다. 실행하자 라이브 리로딩이 지원되는 개발 서버가 시작됐고, 디스크에 변경 사항이 저장될 때마다 결과를 즉시 확인하면서 추가 수정 요청을 이어갈 수 있었습니다.
마무리 단계에서 공개할 만한 완성도가 됐다고 판단했습니다. 새 Claude Code 인스턴스를 열고 이렇게 입력했습니다:
Look at the web/ folder - set up GitHub actions for this repo such that any push runs the tests, and if the tests pass it then does a GitHub Pages deploy of the built vite app such that the web/index.html page is the index.html page for the thing that is deployed and it works on GitHub Pages
몇 번의 추가 작업을 거쳐 완성된 GitHub Actions 워크플로는 Vite로 앱을 빌드하고 그 결과물을 https://simonw.github.io/liteparse/에 배포합니다.
이런 프로젝트에 GitHub Pages가 정말 좋은 이유는, 저장소 하나를 손쉽게(이번에는 Claude가) 웹 앱으로 배포할 수 있고, 필요한 빌드 단계도 자유롭게 설정할 수 있으며, 비용이 전혀 들지 않기 때문입니다. 비공개 저장소도 지원되므로, 비밀 URL만으로도 충분하다면 프라이빗 프로젝트에도 활용할 수 있습니다.
이런 종류의 프로젝트에는 항상 큰 위험이 따릅니다. 모델이 "꼼수"를 쓸 수 있다는 것입니다. 핵심 기능을 "TODO"로 남겨두거나, 초기 요구사항을 무시한 지름길을 택할 수도 있습니다.
이를 확실히 방지하려면 코드 전체를 직접 검토해야 하지만, 이번 프로젝트의 성격상 그런 방식은 맞지 않았습니다. 대신 GPT-5.5(프리뷰 접근 권한이 있었습니다)가 탑재된 OpenAI Codex를 열고 이렇게 입력했습니다:
Describe the difference between how the node.js CLI tool runs and how the web/ version runs
돌아온 답변만으로도 Claude가 프로젝트를 위협할 만한 지름길은 택하지 않았다는 확신을 가질 수 있었습니다.
그렇게 마무리됐습니다. "빌드하기" 단계에서 Claude Code를 사용한 총 시간은 59분이었습니다. claude-code-transcripts 도구로 전체 대화록을 읽기 좋은 형태로 내보냈으며, 여기서 확인하실 수 있습니다. 다만 추가로 입력한 프롬프트는 포함되지 않았는데, 이를 수정하기 위한 이슈를 열어두었습니다.
저는 바이브 코딩의 원래 정의에 꽤 엄격한 편입니다. AI를 활용해 코드를 작성하는 것이 모두 바이브 코딩은 아닙니다. 작성된 코드를 전혀 검토하지도, 신경 쓰지도 않고 AI에게 전적으로 맡기는 것이 바이브 코딩입니다.
제 기준으로 따지면, 이번 LiteParse 웹 버전 프로젝트는 거의 완벽한 바이브 코딩입니다! 이 프로젝트에서 작성된 HTML과 TypeScript 코드를 단 한 줄도 확인하지 않았고, 사실 이 글을 쓰다가 JavaScript를 썼는지 TypeScript를 썼는지 확인하러 직접 들어가봐야 했을 정도입니다.
그런데 묘하게도 다른 바이브 코딩 프로젝트들보다 덜 "바이브 코딩스럽게" 느껴집니다:
가장 중요한 건, 제 이름을 걸고 이 프로젝트를 추천할 수 있다는 점입니다. 대부분의 바이브 코딩 도구와 달리, 이번에는 엔지니어링에 더 많은 시간을 투자했더라도 초기 릴리스가 의미 있을 만큼 나아지지는 않았을 것이라고 생각합니다. 지금 이대로도 충분합니다!
원본 저장소에 PR을 올리지는 않았습니다. LiteParse 팀과 아직 논의하지 않았기 때문입니다. 이슈는 열어두었으니, 제 바이브 코딩 구현물을 더 공식적인 버전의 출발점으로 활용하고 싶다면 언제든지 가져가셔도 좋습니다.
블로그의 장문 아티클만 제공하고 있습니다. 모든 게시물을 받아보시려면 /atom/everything/을 구독하시거나, 다른 구독 옵션을 확인해보세요.