3계층 피드백 설계
contextlint는 같은 lint 엔진을 LSP / MCP / CI 라는 3가지 프로토콜에 실어서 배포합니다. 하나의 실행 수단으로 좁히지 않고, 굳이 3계층으로 나눈 것은 문서가 깨지는 시점과 검출하는 시점을 가능한 한 가깝게 한다 는 설계 판단 때문입니다. 이 페이지에서는 그 이유를 설명합니다.
3계층의 개요(시점과 대응 도구)는 Get Started에 표가 있습니다. 여기서는 왜 3계층으로 나누는가 를 중심으로 다룹니다.
문서가 깨지는 시점
섹션 제목: “문서가 깨지는 시점”문서의 정합성은 라이프사이클의 3가지 국면에서 무너질 가능성이 있습니다.
| 국면 | 무엇이 일어나는가 |
|---|---|
| 사람이 작성하고 있는 동안 | rename, ID 변경, 섹션 삭제 등 편집의 부작용으로 참조가 깨진다 |
| AI가 작성하고 있는 동안 | AI가 새 문서를 생성·편집할 때, 기존 파일 참조를 깨뜨리는 경우가 있다 |
| 여러 편집이 합류할 때 | branch를 병합한 순간, 독립적으로 작성된 2개의 변경이 조합되어 정합성이 무너진다 |
3계층 피드백은 이 3가지 국면 각각에 대응하는 체크 포인트 를 마련하기 위한 설계입니다.
각 계층의 역할
섹션 제목: “각 계층의 역할”| 계층 | 프로토콜 | 언제 실행되는가 | 대응 도구 |
|---|---|---|---|
| 작성하는 동안 | LSP | 에디터에서 입력 중 (debounce) | VS Code / Cursor / Neovim / Helix / JetBrains |
| AI가 작성하는 동안 | MCP | AI 에이전트가 문서를 편집한 직후 | Claude Code / Cursor Agent / Cline / Codex / Windsurf |
| 병합 전 | CLI | PR / pre-commit / push 시 | GitHub Actions / pre-commit / Husky / lint-staged |
3가지는 검출하는 시점 이 다를 뿐이며, 실행하는 엔진 은 같습니다. 규칙 정의, 설정 파일, 출력 포맷도 모두 공통화되어 있어, 계층 간에 어긋남이 생기지 않는 구조입니다.
왜 3계층으로 나누는가
섹션 제목: “왜 3계층으로 나누는가”하나의 계층만으로는 검출이 너무 늦거나, 너무 이르다
섹션 제목: “하나의 계층만으로는 검출이 너무 늦거나, 너무 이르다”CI에만 의존하는 경우의 문제점: 문서의 부정합은 PR을 열고 CI가 실행되기까지 누구에게도 보이지 않습니다. 알아챘을 때는 여러 커밋에 걸친 수정이 필요하게 되어 있고, 원인 특정에도 비용이 듭니다.
LSP에만 의존하는 경우의 문제점: 편집 중의 즉시 피드백은 강력하지만, 이를 빠져나간 채 PR이 병합될 가능성이 있습니다. 최종 가드가 없는 상태로 main 브랜치가 깨질 위험이 남습니다.
MCP에만 의존하는 경우의 문제점: AI 에이전트를 통한 편집은 커버할 수 있지만, 사람이 직접 에디터로 작성한 변경이나, CI에서 검출해야 할 부작용은 잡아낼 수 없습니다.
3계층을 조합함으로써, 각각의 “누락”을 다른 계층에서 받아낼 수 있습니다.
검출이 빠를수록 수정 비용이 낮아진다
섹션 제목: “검출이 빠를수록 수정 비용이 낮아진다”부정합은 검출이 빠를수록 고치기 쉽고, 늦을수록 영향 범위가 넓어집니다.
| 검출 시점 | 수정 비용의 기준 |
|---|---|
| 입력 중 (LSP) | 키 입력 1회분. 물결선이 나온 순간 고친다 |
| AI 편집 직후 (MCP) | AI가 스스로 수정안을 제시한다. 사람은 확인만 하면 된다 |
| PR 시 (CI) | 커밋을 가로질러 수정이 필요하다. 리뷰 왕복이 늘어난다 |
| 병합 후 | 별도 PR로 추가 수정. main이 일시적으로 깨진 상태가 된다 |
LSP는 “깨뜨리지 않는다”, MCP는 “깨지면 즉시 고친다”, CI는 “깨진 것을 통과시키지 않는다” — 각각 역할이 다르며, 같은 도구가 3가지 형태로 배포되는 의의가 있습니다.
표준 프로토콜에 실음으로써, 도구 선택의 자유를 유지한다
섹션 제목: “표준 프로토콜에 실음으로써, 도구 선택의 자유를 유지한다”3계층은 각각 개방형 표준 프로토콜 에 대응하고 있습니다.
- LSP (Language Server Protocol) — 에디터를 한정하지 않는다. VS Code / Cursor / Neovim / Helix / JetBrains에서 동일하게 동작
- MCP (Model Context Protocol) — AI 호스트를 한정하지 않는다. Claude Code / Cursor / Cline / Codex / Windsurf에서 동일하게 동작
- CLI (셸 명령) — CI / Git hook / 수동 실행 모두에서 사용 가능
contextlint는 표준 프로토콜을 채택함으로써, 사용자의 환경에 록인하지 않도록 하고 있습니다. 에디터를 갈아타도, AI 호스트를 바꾸어도, CI를 다른 서비스로 옮겨도, 같은 린터를 계속 사용할 수 있습니다.
같은 엔진을 3계층에 싣는 이점
섹션 제목: “같은 엔진을 3계층에 싣는 이점”3계층이 공통의 엔진을 사용하는 것에는, 운용상 중요한 이점이 있습니다.
- 결과가 일관된다 — 에디터에서 OK였던 것이 CI에서 에러가 되는 어긋남이 일어나지 않습니다
- 설정이 한 곳에 집약 —
contextlint.config.json을 저장소 루트에 두면, 3계층 모두에서 같은 규칙이 적용됩니다 - 규칙 추가가 즉시 전 계층에 반영 — 새 규칙을 작성하면, 그날부터 에디터·AI·CI 모두에서 검출 가능하게 됩니다
구현적으로는, lint 파이프라인을 @contextlint/core에 집약하고, @contextlint/cli / @contextlint/mcp-server / @contextlint/lsp-server가 각각 얇은 어댑터로서 core를 호출하는 구조로 되어 있습니다. 자세한 내용은 Graph API나 각 Integrations 페이지를 참조하세요.
다음 단계
섹션 제목: “다음 단계”- Context Graph — 3계층의 lint 엔진이 공통으로 사용하는 의존 관계 그래프
- Integrations — 각 계층을 실제로 통합하는 절차