Show HN: Perspica – 코드를 검토하기 위한 의미론적 diff
요약
perspica는 코드의 의미론적 차이(semantic diff)를 검토하여 단순한 라인 비교가 놓치는 중요한 변경 사항을 파악하는 도구입니다. 리팩토링, 이름 변경, 로직 변화 등 실제 개념적 변화에 초점을 맞추어 PR 리뷰 효율성을 높여줍니다. 이는 tree-sitter 기반의 단일 로컬 바이너리이며, LLM 없이도 빠르고 정확하게 작동합니다.
핵심 포인트
- 단순 라인 비교를 넘어선 의미론적 코드 차이 검토가 가능합니다.
- tree-sitter를 사용하여 호출 관계 추적 등 깊은 분석을 수행합니다.
- LLM 사용 시 변경 사항의 의도를 그룹화하고 위험도를 평가할 수 있습니다.
- TypeScript, Python, Rust, Go 등 다양한 언어를 지원합니다.
[!NOTE]
perspica는 beta 버전입니다. 거친 부분이 있을 수 있으며, 0.x 릴리스 간에 동작이 변경될 수 있습니다. 뭔가 잘못된 것 같다면, issue를 열어주세요.
perspica는 실제로 무엇이 바뀌었는지(이름 변경, 새로운 매개변수 추가, 이동한 함수, 실제 로직 변경)를 파악하여 diff를 읽습니다. 이 과정에서 기계적인 노이즈(리포맷팅, 주석, 이름만 바뀐 라인, 변화 없는 이동, 생성된 파일)는 제외하고, 일반적인 diff가 숨기는 것들, 즉 더 이상 존재하지 않는 이름에 대한 참조, 새로운 시그니처에 맞춰 업데이트되지 않은 호출, 사용되지 않고 남겨진 코드를 지적합니다.
이 모든 과정에 모델은 필요하지 않습니다. perspica는 tree-sitter를 사용하여 두 버전을 파싱하고 그 사이의 호출 관계를 추적하므로, 일반적인 PR에서 수백 밀리초 만에 답변을 제공하는 단일 로컬 바이너리이며, 매번 동일한 답변을 주며, API 키가 필요 없습니다. LLM은 선택 사항이지만 유용합니다: 변경 사항을 의도별로 그룹화하고 각 그룹의 위험도를 평가하며 요약문을 작성해 줍니다. 그리고 요청하지 않는 한 아무것도 기기 외부로 나가지 않습니다.
이것은 TypeScript 및 JavaScript (TSX 및 JSX 포함), Python, Rust, Go, Java, Kotlin, Scala, C#, C, PHP, 그리고 Ruby (Rails 포함)를 이해합니다. 다른 언어로 된 파일들은 일반적인 라인 비교(line diffs)로 표시됩니다.
이 도구는 코딩 에이전트가 수행한 작업 검토를 위해 구축되었습니다. 만약 변경 사항이 Claude Code 또는 Codex 세션에서 발생했다면, perspica는 사용자가 요청한 내용을 사용자 자신의 말로 보여주고, LLM을 사용하여 어떤 부분이 사용자가 요청한 부분이고 어느 부분이 에이전트가 자체적으로 결정한 것인지 표시합니다.
또한 변경 사항이 사용자가 작업하지 않은 내용에 의존하는 경우, Learn 탭에서 이를 설명해 줍니다. 초점은 변경 사항에 중요한 몇 가지 개념이나 아키텍처 변경 사항에 맞춰져 있습니다. 도움이 되는 경우 짧은 강의, 다이어그램 또는 애니메이션을 제공하며, 이해했는지 확인할 수 있는 퀴즈도 제공합니다. 배울 것이 아무것도 없다면 그렇게 알려줍니다. Learn 데모 비디오 보기.
<a href="docs/media/perspica-demo.mp4"><img alt="perspica demo: an LLM analysis grouping the changes by intent, the summary, what to check before merging, the reading order with test reach, unified and split views, the agent-session view, and terminal output" src="https://raw.githubusercontent.com/sshah03/perspica/HEAD/docs/media/perspica-demo.gif"></a>
<sub>Reviewing pallets/click#3767 (분석, 읽기 순서, 터미널) 및 colinhacks/zod#6587 (요약, 확인 사항, 분할 보기). 에이전트 세션 예시는 설명용입니다. 고화질 비디오 (MP4).</sub>
**실제 풀 리퀘스트에서 확인하기**를 ripgrep, Flask, Spark 등에서 확인할 수 있습니다. 설치할 필요가 없습니다.
설치
cargo install perspica
또는 Homebrew로:
brew install sshah03/perspica/perspica
또는 바이너리를 ~/.local/bin에 배치하는 설치 스크립트로:
curl -fsSL https://raw.githubusercontent.com/sshah03/perspica/main/install.sh | sh
또는 Releases에서 macOS, Linux 또는 Windows용 바이너리를 다운로드하거나 소스에서 빌드할 수 있습니다:
git clone https://github.com/sshah03/perspica && cd perspica
cargo build --release # → target/release/perspica
사용법 (Use)
저장소 내부에서:
perspica # 현재 브랜치 검토: 커밋, 미커밋 및 추적되지 않은 파일
perspica --web # …브라우저에서
perspica --pr 123 --web # GitHub 풀 리퀘스트 (gh CLI 사용)
다른 대상:
perspica --branch develop # 다른 기본 브랜치 대비
perspica --staged # 스테이징된 변경 사항
perspica --git main...feature # 범위 (PR과 같은 merge-base)
...
위의 모든 기능은 단독으로 작동합니다. 선택적 LLM 분석(-s, 또는 뷰어에서 Analyze…)은 Claude Code, API 키 또는 Ollama를 통해 실행됩니다. 설정 방법은 LLM 분석을 참조하세요. 또는 코딩 어시스턴트에게 요청하여 대신 실행하게 할 수도 있습니다.
얻게 되는 것 (What you get)
노이즈 감소(Limited Noise). 서식 변경, 주석만 수정된 내용, 이름만 바뀐 라인, 변경 없이 이동된 코드, 생성 및 번들링된 파일은 태그가 지정되고 접혀서 표시되므로 실제 변경 사항을 담고 있는 라인이 눈에 띕니다. 테스트와 문서는 별도의 영역으로 분리됩니다.
모든 변경 사항 이름 명시. 리네임(심지어 본문이 수정된 경우에도), 시그니처 변경(새로 필수/선택 파라미터 추가), 모듈 및 심볼별 종속성 변경, 새 함수로 추출된 내용, 파일 내외 이동, 함수 및 메서드별 로직 변경.
diff가 숨기는 것.
- 저장소의 다른 곳에서 여전히 사용되는 이름이 리네임되거나 제거된 경우(메서드의 경우, 자신의 타입에 대한 호출만 하므로
Flush와 같은 일반적인 이름은 오탐을 일으키지 않습니다). - 업데이트되지 않은 변경된 함수에 대한 호출(실제로 호출자를 망가뜨릴 수 있는 변경 사항에 한해서만 해당).
- 변화로 인해 사용되지 않게 된 코드.
읽기 순서(A reading order). 코드를 진입점부터 변경된 함수까지 (누군가 당신에게 설명해주길 원하는 순서), 그리고 실제로 변경된 테스트 중 어떤 부분이 호출 경로와 함께 도달하는지를 보여줍니다.
<picture> <source media="(prefers-color-scheme: dark)" srcset="docs/images/reading-order-dark.jpg"> <img alt="pallets/click#3767의 읽기 순서: get_pager_file, 그리고 페이지 매거니저 컨텍스트 관리자 및 그것이 호출하는 페이지 매거니저들, 각각 도달하는 테스트 경로와 함께" src="https://raw.githubusercontent.com/sshah03/perspica/HEAD/docs/images/reading-order-light.jpg"> </picture>요청한 내용(What you asked for). 만약 변경 사항이 사용자의 기기에서 Claude Code나 Codex를 사용하여 만들어졌다면, perspica는 이 파일들을 편집했던 세션의 프롬프트를 보여줍니다. LLM 분석을 통해 각 변경 그룹은 *질문됨(asked)*으로 표시되며, 짧은 인용구가 사용자 프롬프트와 단어 그대로 확인됩니다. 또는 에이전트 호출(agent's call): 에이전트가 스스로 결정한 경우입니다.
의도, 위험 및 요약 (선택 사항). LLM을 사용하면 변경 사항이 목적별로 그룹화되며, 각 항목은 위험 수준과 검증할 내용, 그리고 요약 및 모델의 메모를 포함합니다. 이 정보는 perspica가 코드에서 발견한 것과는 분리되어 표시되며, 신뢰도가 낮음(less certain)으로 라벨링됩니다.
배경 개념 (선택 사항). LLM을 사용하면 Learn 탭에서 변경이 의존하는 아이디어를 설명하고 관련 퀴즈를 제공합니다. Learn을 참조하세요.
LLM 분석
선택 사항입니다. 터미널에서는 -s 옵션을, 뷰어에서는 Analyze… 버튼을 사용합니다 (모델 선택기 및 표준(Standard) 또는 정밀(Thorough) 깊이 설정 가능).
설정(Setup). 붙여넣을 키는 없습니다. perspica는 다음 중 사용 가능한 것을 사용합니다:
- Claude Code. perspica는 사용자의 Claude Code 로그인을 사용하므로 API 키가 필요하지 않습니다. 이미 사용하고 있다면 설정할 것이 없습니다. 처음이신가요? Claude Code를 설치하고
claude auth login을 실행하세요. 이렇게 분석하고 배운 내용은 다른 모든 Claude Code 요청과 마찬가지로 Claude 플랜의 사용량에 포함됩니다. - 환경 변수에 API 키를 추가합니다. 셸 프로필(
~/.zshrc,~/.bashrc)에 추가한 후 새 터미널을 열어 다음 명령어를 실행하세요:export ANTHROPIC_API_KEY=sk-ant-… # 또는 OPENAI_API_KEY - Ollama를 사용한 로컬 모델을 설정합니다. Ollama를 설치하고 모델을 다운로드한 후 Ollama가 실행 중이도록 유지하세요:
ollama pull gemma4:12b # 약 16 GB의 RAM 필요; qwen3-coder:30b는 32 GB 필요
perspica는 다운로드된 최고의 모델을 자동으로 선택하거나(뷰어에서 선택하거나, 또는 --model로 지정할 수 있습니다). 로컬 모델은 호스팅되는 모델보다 느리고 정밀도가 떨어집니다. M4 Pro에서 파일 10개짜리 PR을 분석하는 데 약 1분이 걸립니다. OLLAMA_HOST는 다른 머신을 가리킵니다.
만약 위 방법 중 아무것도 찾지 못하면, 뷰어의 **Analyze…**를 통해 이 단계를 확인할 수 있으며, Check again을 사용하면 재시작 없이 Claude Code 로그인이나 Ollama를 인식합니다. 여러 가지 옵션이 있는 경우 순서는 --api-key / --provider 또는 PERSPICA_API_KEY (및 PERSPICA_PROVIDER) 다음으로 ANTHROPIC_AUTH_TOKEN (게이트웨이), ANTHROPIC_API_KEY, OPENAI_API_KEY, Claude Code, Ollama 순서입니다. --provider ollama는 다른 모든 옵션보다 로컬 모델을 우선합니다. 환경 변수를 사용하는 것이 --api-key를 사용하는 것보다 선호됩니다. 후자는 키를 셸 히스토리에 남기기 때문입니다.
기본 Claude 모델은 claude-opus-5-5이며, --model claude-sonnet-5-5가 더 빠르고, claude-haiku-5-5(또는 이전 버전인 claude-haiku-4-5)는 빠른 1차 검토에 적합합니다. 전송되는 내용은 전체 파일이 아니라 분류된 변경 목록과 변경된 코드입니다 (Thorough의 경우 변경된 파일 아래의 정의 및 최대 200줄까지 읽을 수도 있습니다). 분석 결과는 .git/perspica/ 디렉터리에 diff별로 저장되므로, 다시 로드하거나 재실행해도 동일한 분석에 대해 비용을 지불하지 않습니다. --fresh 옵션은 재실행합니다. 최대 10만 자의 변경 코드가 전송되며 (로컬 모델의 경우 16,000자), 더 큰 변경 사항의 경우 **Analyze…**에서 크기를 알려주고 전체를 전송할지 제안하며, 터미널에서는 --full-context가 동일한 기능을 수행합니다. 그렇지 않으면 모델에게 볼 수 없는 파일을 알려줍니다.
학습 (Learn)
뷰어에서 Review 옆에 있는 학습(Learn) 탭은 이 변경 사항을 이해하는 데 필요한 개념들을 뽑아 보여줍니다. 아키텍처 변경이 먼저 제시되고, 그다음 알고리즘, 프로토콜 규칙 또는 그것에 의존하는 언어 기능 순으로 나옵니다. 작은 변경 사항은 하나의 개념만 제공하고, 더 큰 변경 사항은 최대 세 개의 개념을 제공합니다. 포맷팅, 이름 변경 등 배경 지식이 필요 없는 변경 사항에는 채우기 내용 대신
<sub>Flask의 pallets/flask#5818 (아키텍처 다이어그램), charmbracelet/lipgloss#591 (실습 조각 및 퀴즈), 그리고 encode/uvicorn#2985 (애니메이션 및 퀴즈)에서 학습할 수 있습니다. 전체 품질 비디오 (MP4).</sub>
Learn은 LLM 분석과 동일한 설정을 사용합니다. 즉, 탭을 열고 모델을 선택하면 perspica가 개념을 찾습니다. 각 레슨은 해당 개념을 처음 열 때 작성되며, 분석 내용과 함께 .git/perspica/에 저장되므로 한 번만 작성됩니다. 만약 레슨이 충분하지 않다면, **Rewrite…**를 사용하여 더 강력한 모델로 다시 작성할 수 있습니다. 레슨은 --format html 내보내기에 유지되어 공유된 검토가 해당 레슨과 퀴즈를 유지합니다.
개인 정보 보호 (Privacy)
- 모든 것은 초기에는 로컬에서 실행됩니다. 요청하지 않는 한 어딘가로 아무것도 전송되지 않습니다:
-s/ Analyze…, 또는 Learn의 Find concepts… (이후 개념을 열면 해당 레슨이 작성됨). - 에이전트 세션(
~/.claude/projects,~/.codex/sessions)은 본인의 변경 사항(커밋되지 않은 작업 또는 본인의 git ID로 작성된 커밋)에 대해서만 읽기 전용으로 사용되며, 다른 사람의 PR에 대해서는 절대 사용하지 않습니다. perspica가 이를 사용할 때 알려주며,--no-sessions를 사용하면 이 기능을 끌 수 있습니다. - 웹 뷰어는
127.0.0.1에서 리스닝하며 자신의 페이지에만 응답합니다: 다른 호스트(DNS rebinding) 및 다른 사이트의 요청은 거부됩니다. - Learn의 대화형 요소들은 모델에 의해 작성되므로, 네트워크나 페이지의 나머지 부분에 접근할 수 없는 샌드박스 프레임에서 실행됩니다.
언어 및 파일 역할 (Languages and file roles)
AI 자동 생성 콘텐츠
본 콘텐츠는 HN OpenAI Codex의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기