TRENDSHIFT 딥다이브 · 2026-06-08

sem 딥다이브
— "몇 번째 줄"이 아니라 "어떤 함수"가 바뀌었는지 말해주는 시맨틱 Git

Git 위에서 동작하는 시맨틱 버전 관리 (semantic version control, 줄 단위가 아닌 코드 의미 단위로 변경을 추적) 도구입니다. tree-sitter로 코드를 파싱해 함수·클래스·메서드를 엔티티로 추출하고, "lines 40~55 변경" 대신 "함수 authenticateUser 수정됨"이라고 알려줍니다. 31개 언어 지원, 설정 제로, MCP 서버 내장 — 코딩 에이전트의 코드 이해를 보강하는 도구로 주목받고 있습니다. (저장소: Ataraxy-Labs/sem · Rust · TrendShift 2위 · MIT/Apache-2.0)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 레포가 무엇을 하는 물건인가.

핵심 메시지

"Git은 글자의 변화를 보고,
sem은 코드의 의미 변화를 본다."

git diff는 코드를 그냥 텍스트로 취급합니다. sem은 같은 변경을 "함수 A 수정, 클래스 B 추가, 메서드 C는 이름만 바뀜(rename)"이라는 프로그래머의 언어로 번역합니다. 사람에게도 좋지만, 진짜 수혜자는 토큰이 아까운 코딩 에이전트입니다.

sem은 어떤 Git 저장소에서든 설치 직후 바로 동작합니다. tree-sitter (다양한 언어의 코드를 구문 트리로 파싱해 주는 라이브러리)로 소스를 분석해 함수·클래스·메서드 하나하나를 엔티티 (entity, 의미를 가진 코드 단위)로 등록하고, diff·blame·log·impact 같은 Git의 익숙한 동사들을 전부 엔티티 레벨로 다시 구현했습니다.

흥미로운 건 sem setup 한 방이면 git diff 자체가 sem 출력으로 바뀐다는 점입니다. 에이전트 설정을 하나도 안 건드려도, git diff를 호출하는 모든 도구(에이전트 포함)가 자동으로 의미 단위 diff를 받게 됩니다.

2왜 주목받는가

트렌딩 이유 · 경쟁 대비 장점.

코딩 에이전트 시대의 병목은 "에이전트가 변경 사항을 이해하는 비용"입니다. 줄 단위 diff는 노이즈가 많고(들여쓰기·이동·포매팅), 에이전트는 그걸 다 읽으며 토큰을 태웁니다. sem은 변경을 엔티티 목록으로 압축해 에이전트의 입력 토큰과 오해를 동시에 줄입니다. JSON 출력(--format json)과 MCP 서버가 기본 내장이라 "에이전트 우선" 설계가 분명합니다.

비교 항목git diff (줄 단위)sem (엔티티 단위)
변경 표현"+12줄 -8줄 @ 40~55행""함수 authenticateUser 수정"
리네임삭제+추가로 보임구조 해시로 리네임 감지
영향 분석없음sem impact — 의존 그래프로 파급 범위 추적
에이전트 연동텍스트 파싱 직접JSON·Markdown 포맷 + MCP 서버 + SKILL.md
기존 방식의 한계
줄 diff는 "무엇이 바뀌었나"를 말하지 못한다

함수를 파일 아래로 옮기기만 해도 git diff는 큰 변경처럼 보여줍니다. 코드 리뷰어도, LLM도 "실질적으로 뭐가 달라졌는지"를 텍스트 더미에서 다시 추론해야 합니다.

이 레포의 해결
구문 트리에서 엔티티를 뽑아 구조 해시로 비교

tree-sitter 구문 트리에서 엔티티를 추출하고 구조적 해시를 비교하므로, 위치 이동·공백 변경은 "변화 없음"으로, 시그니처 유지 + 본문 변경은 "수정"으로, 본문 유지 + 이름 변경은 "리네임"으로 정확히 분류됩니다.

같은 회사(Ataraxy Labs)가 엔티티 단위 git 머지 드라이버(weave), 시맨틱 코드 리뷰(inspect)까지 묶어 "에이전트 네이티브 개발 인프라" 스택을 밀고 있다는 점도 트렌딩의 배경입니다.

3기술 스택 전체 지도

Rust 워크스페이스 4개 크레이트 + 배포 채널.

레이어기술역할
코어Rust (sem-core)파서·엔티티 모델·diff 엔진·의존 그래프. 모든 로직의 본체.
파싱tree-sitter 31개 언어TS/JS·Python·Go·Rust·Java·C/C++/C#·Ruby… + Vue·Svelte·Markdown·YAML·JSON·LaTeX 플러그인.
CLIsem-clidiff·impact·blame·log·entities·context·setup 명령과 터미널/JSON/Markdown 포매터.
에이전트 연동sem-mcp + SKILL.mdMCP 서버로 에이전트가 도구처럼 호출. 스킬 파일도 동봉.
확장sem-plugin (WASM 프로파일)커스텀 파서 플러그인. 릴리스 프로파일에 WASM 크기 최적화가 따로 있음.
캐시SQLite (OS 캐시 디렉토리)엔티티 캐시를 저장소 밖에 둬서 작업 트리를 더럽히지 않음.
배포brew · npm 래퍼 · cargo · Docker · 바이너리5가지 설치 경로. npm 패키지는 postinstall로 네이티브 바이너리 다운로드.
용어
tree-sitter (트리시터 — 증분 파싱 라이브러리)
GitHub이 만든 파서 생성기. 언어마다 문법 정의만 있으면 코드를 구문 트리로 바꿔줍니다. 에디터의 구문 강조, 코드 접기에 널리 쓰이고, 최근엔 "LLM에게 코드 구조를 알려주는" 용도로 재조명되고 있습니다.

4아키텍처 심화 분석

sem diff 한 번이 거치는 길.

sem 전체 구조 ┌─────────────────────────────────────────────────┐ │ sem diff / impact / blame / log / context │ │ │ (sem-cli: 명령 파싱) │ │ ▼ │ │ ① git bridge ── 변경 전/후 파일 내용을 Git에서 추출 │ │ │ (jj 저장소도 지원) │ │ ▼ │ │ ② parser registry ── 확장자로 플러그인 선택 │ │ │ code(tree-sitter 31언어)·vue·svelte· │ │ │ markdown·yaml·json·csv·latex·fallback │ │ ▼ │ │ ③ entity extractor ── 함수·클래스·메서드 추출 │ │ │ (SQLite 캐시로 재파싱 회피) │ │ ▼ │ │ ④ differ ── 구조 해시 비교·리네임 감지· │ │ │ cosmetic 변경(공백 등) 무시 │ │ ▼ │ │ ⑤ formatter ── terminal / plain / json / md │ └─────────────────────────────────────────────────┘

대표 흐름 하나를 따라가 봅시다 — sem diff.sem-core/src/git/bridge.rs가 Git에 물어 변경된 파일의 전/후 내용을 가져옵니다. ② parser/registry.rs가 확장자를 보고 파서 플러그인을 고릅니다 — .py면 tree-sitter 코드 플러그인, .vue면 Vue 전용, 모르는 파일이면 fallback. ③ plugins/code/entity_extractor.rs가 구문 트리를 걸어 다니며 엔티티 목록을 만듭니다(이미 본 파일은 SQLite 캐시에서 바로). ④ parser/differ.rs가 전/후 엔티티 목록을 비교합니다 — 여기가 머리입니다. 구조 해시가 같으면 변화 없음, 이름만 다르면 리네임, 본문이 다르면 수정. ⑤ 포매터가 사람용(터미널 색상) 또는 기계용(JSON)으로 출력합니다.

sem impact는 ③ 다음이 다릅니다 — parser/import_resolution.rsgraph.rs가 파일 사이의 import를 풀어 의존 그래프 (dependency graph, 누가 누구를 부르는지의 지도)를 만들고, 특정 엔티티를 바꾸면 어디까지 흔들리는지(dependents)와 그 엔티티가 기대는 곳(deps), 영향받는 테스트까지 거꾸로 추적합니다.

비유

git diff가 "책의 40~55번째 줄이 바뀌었다"고 말하는 교정자라면, sem은 "3장 2절의 '결제 처리' 단락이 수정됐고, 이 단락을 인용하는 7장도 영향을 받는다"고 말하는 편집자입니다. 같은 변경을 보지만 말하는 층위가 다릅니다.

설계 패턴
플러그인 레지스트리 (parser plugin registry)
"파일 타입마다 파서가 다르다"를 if-else 더미가 아니라 등록제로 풉니다. 새 언어 지원 = 플러그인 하나 추가. fallback 플러그인이 있어 모르는 파일도 죽지 않고 통과합니다. CLI의 context 명령은 이 위에 토큰 예산(budget)을 얹어 "LLM 컨텍스트에 꼭 들어갈 것만" 잘라줍니다.

5디렉토리 구조 해부

어떤 폴더가 무슨 일을 하나.

sem/ ├── crates/ Rust 워크스페이스 ★ │ ├── sem-core/ 엔진 본체 │ │ └── src/ │ │ ├── git/ Git/jj 브리지 (변경 추출) │ │ ├── model/ Entity·Change·Identity 타입 │ │ ├── parser/ differ·graph·import 해석· │ │ │ └── plugins/ code(31언어)·vue·svelte·md·yaml… │ │ └── utils/ 구조 해시·파일 스캔 │ ├── sem-cli/ 명령 + 포매터 (terminal/json/md) │ │ └── src/commands/ diff·impact·blame·log·entities· │ │ context·setup·graph·stats·update·cloud·files │ ├── sem-mcp/ MCP 서버 (에이전트용) │ └── sem-plugin/ WASM 플러그인 SDK ├── bin/sem.js + bin/ npm 래퍼 (바이너리 다운로드) ├── benchmarks/ 의존성 정확도·대형 JS 벤치마크 ├── bench/ 에이전트 정확도 실험 결과 JSON ├── SKILL.md 에이전트 스킬 정의 └── Formula/sem.rb Homebrew 포뮬라
위치주목할 점
sem-core/parser/differ.rs심장부 — 구조 해시 비교와 리네임 감지 로직.
sem-core/parser/plugins/"코드만"이 아니라 Markdown·YAML·CSV·LaTeX까지 엔티티화 — diff의 적용 범위를 문서로 확장.
sem-cli/tests/diff_no_cosmetics, setup_regressions 등 — 이름만 봐도 회귀 시나리오를 알 수 있는 17개 통합 테스트.
bench/agent-accuracy.py"sem을 주면 에이전트 정확도가 실제로 오르나"를 측정한 실험 — 도구 효과를 수치로 증명하려는 시도.

6학습 포인트 (기술별)

이 레포에서 배울 만한 것 + 어디를 보면 되는지.

포인트 1 — 파싱

tree-sitter로 31개 언어를 하나의 추출기로

plugins/code/languages.rs가 언어별 "어떤 노드가 엔티티인가" 매핑을 데이터로 들고, entity_extractor.rs 하나가 모든 언어를 처리합니다. 언어별 파서를 31번 짜는 대신 선언적 매핑으로 푸는 법을 배울 수 있습니다.

포인트 2 — 도구 설계

"에이전트 설정 없이" 끼어드는 sem setup

에이전트에게 새 도구 사용법을 가르치는 대신, git diff의 출력 자체를 바꿔치기합니다(commands/setup.rs). 기존 워크플로의 길목에 끼어드는 이 접근은 어댑터를 일일이 만드는 것보다 파급력이 큽니다 — 도구 보급 전략으로 배울 점.

포인트 3 — LLM 컨텍스트

토큰 예산이 일급 개념인 context 명령

sem context fn --budget 4000은 대상 엔티티+의존+피의존을 토큰 예산 안에 맞춰 잘라 주고, 대상조차 안 들어가면 target_omitted: true로 정직하게 보고합니다. "LLM에게 뭘 보여줄까"를 도구 레벨에서 푸는 설계.

포인트 4 — 배포

Rust 바이너리를 npm으로 파는 법

bin/sem.js + postinstall 다운로드 패턴으로, JS 생태계 사용자가 cargo 없이 npm i -D @ataraxy-labs/sem으로 설치합니다. esbuild·biome이 쓰는 표준 패턴의 작은 교과서.

7시스템 요구사항

돌리려면 무엇이 필요한가.

항목요구사항
설치brew install sem-cli 또는 npm/cargo/Docker/바이너리 — 5가지 경로.
전제 조건Git 저장소면 끝(설정 제로). Git 밖에서도 파일 2개 비교는 가능.
OSmacOS · Linux · Windows(테스트 워크플로 별도 존재).
주의GNU Parallel의 sem 바이너리와 이름 충돌 가능 — PATH 순서나 alias로 해결(README에 안내).

8직접 해볼 수 있는 실습 과제

난이도별로 손에 익히는 단계.

실습 1

내 프로젝트에서 첫 시맨틱 diff 난이도 ★☆☆ 입문

설치 후 작업 중인 저장소에서 sem diff·sem entities를 실행해 git diff와 출력을 나란히 비교해 봅니다. 함수 하나를 파일 아래로 옮긴 뒤 두 도구의 반응 차이를 관찰하세요.

실습 2

파급 범위 추적 난이도 ★★☆ 중급

자주 고치는 핵심 함수에 sem impact 함수명 --tests를 걸어 "이걸 건드리면 어떤 테스트가 영향받는지"를 뽑아보고, 실제로 그 함수를 수정해 테스트가 깨지는지 검증합니다.

실습 3

에이전트에 물려보기 난이도 ★★☆ 중급

sem setup으로 git diff를 교체한 상태에서 코딩 에이전트에게 리팩토링을 시켜 보고, 평소보다 변경 요약이 정확해지는지 비교합니다. MCP 서버(sem-mcp)를 직접 등록해 도구 호출로도 써보세요.

실습 4

파서 플러그인 읽고 흉내내기 난이도 ★★★ 고급

plugins/markdown.rs(가장 단순한 축)를 정독하고, 좋아하는 설정 파일 형식(예: ini)을 엔티티화하는 플러그인 스케치를 만들어 봅니다. 레지스트리 등록까지 따라가면 구조가 완전히 잡힙니다.

9관련 기술 심화 학습 로드맵

한 주씩 따라가는 계획.

주차주제학습 자료
1주차sem 명령 6종 손에 익히기, git diff와 비교README · 실습 1~2
2주차tree-sitter 기초 — 구문 트리·쿼리tree-sitter 공식 문서 · playground
3주차엔티티 추출·구조 해시 코드 정독entity_extractor.rs · differ.rs
4주차의존 그래프와 impact 분석graph.rs · import_resolution.rs
5주차MCP 서버 연동 + 에이전트 워크플로 실험sem-mcp · SKILL.md · 실습 3

10핵심 키워드 사전

본문에 나온 용어 빠른 참조.

용어의미
엔티티함수·클래스·메서드 등 의미를 가진 코드 단위. sem의 추적 단위.
시맨틱 diff텍스트 줄이 아니라 코드 의미 단위로 변경을 표현하는 비교 방식.
tree-sitterGitHub의 다중 언어 파서 생성기. 코드를 구문 트리로 변환.
구조 해시코드의 구조를 요약한 지문 — 공백·위치가 바뀌어도 동일하면 같은 코드로 판정.
리네임 감지본문은 같고 이름만 바뀐 엔티티를 "삭제+추가"가 아닌 "이름 변경"으로 식별.
의존 그래프엔티티 간 호출/참조 관계의 지도. impact 분석의 기반.
blast radius한 엔티티를 바꿨을 때 영향이 미치는 범위(피의존 엔티티들).
MCPModel Context Protocol — AI 에이전트가 외부 도구를 표준 방식으로 호출하는 프로토콜.
토큰 예산LLM 컨텍스트에 넣을 수 있는 분량의 상한. sem context의 1급 파라미터.
jj (Jujutsu)Git 호환 차세대 VCS — sem의 git 브리지가 함께 지원.

11참고 링크