# Claude Code LSP 설정: 플래그 없이 플러그인과 언어 서버, 안 될 때 해결법

> Claude Code LSP는 플래그가 아니라 직접 설치한 언어 서버와 공식 코드 인텔리전스 플러그인으로 켭니다. 진단 줄이 안 뜨면 대개 공식 마켓플레이스 미등록이나 PATH 문제입니다.

- URL: https://blog.laozhang.ai/ko/posts/claude-code-lsp
- Published: 2026-11-02
- Updated: 2026-11-02
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ko/about)
- Topic: Claude Code
- Tags: Claude Code, LSP, 코드 인텔리전스, 언어 서버, 플러그인

---
Claude Code에서 LSP를 쓰려면 이제 설정 파일에 플래그를 넣을 필요가 없습니다. 2026년 11월 2일 기준 최신인 Claude Code 2.1.316에서 LSP는 Anthropic 공식 마켓플레이스의 **코드 인텔리전스 플러그인**과, 그 플러그인이 실행할 **언어 서버** 프로그램을 내 컴퓨터에 따로 설치하는 두 가지로 이루어집니다. 플러그인은 "어떤 확장자에 어떤 언어 서버를 띄울지"만 담은 설정이고, 실제로 코드를 분석하는 것은 언어 서버입니다.

TypeScript라면 터미널에서 `npm install -g typescript-language-server typescript`로 언어 서버를 설치하고, Claude Code 안에서 `/plugin install typescript-lsp@claude-plugins-official`을 실행한 다음 새 세션을 엽니다. Python은 `pyright-lsp`와 `pyright`, Go는 `gopls-lsp`와 `gopls`처럼 언어마다 짝이 정해져 있습니다. Claude가 파일을 고친 뒤 대화에 `Found 1 new diagnostic issue in 1 file (ctrl+o to expand)` 같은 진단 줄이 보이면 연결된 것입니다.

설치 명령이 `Plugin "typescript-lsp" not found in marketplace "claude-plugins-official"`로 실패하면 공식 마켓플레이스가 아직 등록되지 않은 상태이므로 `/plugin marketplace add anthropics/claude-plugins-official`부터 실행합니다. 2026년 11월 2일 새 설정 디렉터리에서 직접 설치해 보았을 때 실제로 이 오류가 났고, 오류 문구가 권하는 `marketplace update`로는 해결되지 않았습니다. 클라우드 세션에서는 언어 서버가 아예 시작되지 않으므로 이 설정은 로컬 터미널 세션에서만 효과가 있습니다.

## Claude Code LSP가 하는 일: 편집 후 진단과 LSP 탐색 도구

Claude Code에 언어 서버를 연결하면 Claude가 얻는 것은 서로 다른 두 가지입니다. 하나는 Claude가 해당 언어 파일을 만들거나 고칠 때마다 언어 서버가 보고하는 타입 오류, 누락된 import, 문법 오류가 자동으로 대화에 들어오는 **편집 후 진단**이고, 다른 하나는 텍스트 검색 대신 기호(symbol)로 정의와 참조를 찾는 `LSP` 탐색 도구입니다. 진단은 Claude가 아무것도 요청하지 않아도 들어오지만, 탐색 도구는 Claude가 필요하다고 판단할 때만 부릅니다.

[Claude Code 공식 코드 인텔리전스 플러그인 문서](https://code.claude.com/docs/ko/plugins/code-intelligence)에 따르면 `LSP` 도구는 읽기 전용이고, 컴파일러를 돌리지 않고도 Claude가 자기가 만든 오류를 볼 수 있게 하는 것이 진단의 목적입니다. 2.1.316에서 확인한 `LSP` 도구의 작업은 `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, `outgoingCalls`의 아홉 가지입니다. 파일 3개짜리 TypeScript 테스트 프로젝트에서 서버가 준비된 뒤 호출하면 `goToDefinition`은 `Defined in src/price.ts:1:17`, `findReferences`는 `Found 5 references across 3 files`, `hover`는 `(alias) priceWithTax(amount: number, rate: number): number`처럼 위치와 타입을 돌려줍니다.

LSP는 MCP 서버와도 다릅니다. 언어 서버는 Claude Code가 플러그인 설정을 보고 직접 띄우는 코드 분석기이고, 외부 서비스나 도구를 붙이는 MCP는 [Claude Code MCP 추천: 용도별 첫 서버 선택과 설치 확인](https://blog.laozhang.ai/ko/posts/claude-code-best-mcp-servers)에서 작업별로 고르는 편이 맞습니다.

## Claude Code LSP 설정 순서: 언어 서버, 플러그인, 진단 줄 확인

설정은 언어 서버 설치, 플러그인 설치, 진단 줄 확인의 순서로 진행합니다. 플러그인에는 언어 서버가 들어 있지 않기 때문에 순서를 바꿔 플러그인만 설치하면 아무 일도 일어나지 않고, Claude도 그 사실을 알려 주지 않습니다. Claude Code 자체가 아직 없다면 [Claude Code 설치 방법: 전 플랫폼 완벽 설정 가이드 (2026)](https://blog.laozhang.ai/ko/posts/claude-code-install)부터 진행합니다.

1. 아래 언어별 표에서 내 언어의 언어 서버를 설치합니다. TypeScript는 `npm install -g typescript-language-server typescript`입니다.
2. `claude`를 실행할 셸에서 언어 서버가 PATH에 있는지 확인합니다. macOS와 Linux는 `which typescript-language-server`, Windows PowerShell은 `Get-Command typescript-language-server`가 경로를 출력해야 합니다.
3. 그 셸에서 `claude`를 시작하고 `/plugin install typescript-lsp@claude-plugins-official`을 입력합니다. `typescript-lsp` 부분은 표의 플러그인 이름으로 바꿉니다. 바로 설치되지 않고 플러그인 상세 화면이 열리면, 나만 쓸 때는 **Install for you**(사용자 범위)를 고릅니다.
4. 설치 요약에 `Run /reload-plugins to apply.`가 나오면 새 세션을 엽니다. 이 세션에 LSP 도구가 새로 추가되는 경우라 그냥 `/reload-plugins`는 경고만 띄우고 적용하지 않으며, 현재 세션에서 꼭 적용하려면 `/reload-plugins --force`를 씁니다. 그다음 **Installed** 탭이나 셸의 `claude plugin list`에서 Status가 enabled로 나오는지 확인합니다.
5. Claude에게 해당 언어 파일에 일부러 타입 오류를 넣었다가 고쳐 달라고 요청하고, 대화에 `Found N new diagnostic issues in M files (ctrl+o to expand)` 줄이 나오는지 봅니다.

언어 서버는 Claude가 그 확장자의 파일을 처음 편집하거나 읽을 때 시작되므로, 세션을 열자마자 아무 표시가 없는 것은 정상입니다. VS Code 확장이나 데스크톱 앱에서는 3번의 명령 대신 각 앱의 플러그인 화면에서 같은 플러그인을 설치합니다.

![Claude Code LSP 설정 5단계: 언어 서버 설치, PATH 확인, 플러그인 설치, 새 세션, 진단 줄 확인과 각 단계의 명령](https://blog.laozhang.ai/posts/ko/claude-code-lsp/img/claude-code-lsp-setup-steps.webp)

상세 화면의 **Install for all collaborators on this repository**는 저장소의 `.claude/settings.json`에 플러그인을 켜 두는 프로젝트 범위 설치인데, 협업자에게 플러그인을 내려받아 주지는 않으므로 각자 `claude plugin install typescript-lsp@claude-plugins-official --scope project`를 한 번 실행해야 하고, 언어 서버도 각자 설치해야 합니다. **Install for you, in this repo only**는 `.claude/settings.local.json`에 기록되는 로컬 범위이며, 범위가 겹치면 로컬, 프로젝트, 사용자 순으로 우선합니다. 터미널의 `/plugin` 화면에서 플러그인을 고르고 설치를 확인하는 흐름은 [Claude Code 스킬 추천: 작업별 첫 선택과 설치·확인 방법](https://blog.laozhang.ai/ko/posts/claude-code-best-skills)에서도 같은 방식으로 쓰입니다.

## 언어별 플러그인과 언어 서버: Python, Java, C#, Kotlin 등 13개

공식 마켓플레이스에는 2026년 11월 2일 기준 13개 언어의 코드 인텔리전스 플러그인이 있고, 각 플러그인은 정해진 언어 서버 하나를 실행합니다. 플러그인 이름과 언어 서버 이름이 다른 경우가 많으니(Python 플러그인은 `pyright-lsp`, 실행 파일은 `pyright-langserver`) PATH 확인은 언어 서버 열의 이름으로 합니다. 설치 명령은 공식 마켓플레이스에 있는 각 플러그인 README(2026년 10월 30일 커밋 기준)에 적힌 그대로입니다.

| 언어 | 플러그인 | 언어 서버(실행 파일) | 설치 명령(플러그인 README) |
| --- | --- | --- | --- |
| TypeScript, JavaScript | `typescript-lsp` | `typescript-language-server` | `npm install -g typescript-language-server typescript` |
| Python | `pyright-lsp` | `pyright-langserver` | `npm install -g pyright`, `pip install pyright`, `pipx install pyright` 중 하나 |
| Go | `gopls-lsp` | `gopls` | `go install golang.org/x/tools/gopls@latest` |
| Rust | `rust-analyzer-lsp` | `rust-analyzer` | `rustup component add rust-analyzer` (brew, apt, pacman도 가능) |
| Java | `jdtls-lsp` | `jdtls` | `brew install jdtls`, Java 17 이상 JDK 필요. Linux는 대부분 수동 설치 후 `jdtls` 래퍼를 PATH에 둠 |
| Kotlin | `kotlin-lsp` | `kotlin-lsp` | `brew install JetBrains/utils/kotlin-lsp` |
| C# | `csharp-lsp` | `csharp-ls` | `dotnet tool install --global csharp-ls`, .NET SDK 6.0 이상 필요 |
| C, C++ | `clangd-lsp` | `clangd` | `brew install llvm`, `sudo apt install clangd`, `winget install LLVM.LLVM` |
| PHP | `php-lsp` | `intelephense` | `npm install -g intelephense` |
| Ruby | `ruby-lsp` | `ruby-lsp` | `gem install ruby-lsp` |
| Lua | `lua-lsp` | `lua-language-server` | `brew install lua-language-server` (snap, pacman, dnf도 가능) |
| Swift | `swift-lsp` | `sourcekit-lsp` | Swift 툴체인에 포함. Xcode 또는 `brew install swift`, Linux는 swift.org 배포판 |
| Liquid | `liquid-lsp` | `shopify` | Shopify CLI에 포함. 이 플러그인만 Shopify가 관리 |

Java와 Kotlin은 서버가 뜨는 데 오래 걸릴 수 있어 마켓플레이스 설정에 시작 대기 시간(`startupTimeout`)이 120000밀리초, 즉 2분으로 잡혀 있습니다. 플러그인 폴더에는 README와 LICENSE만 있고 실제 서버 실행 설정은 마켓플레이스 항목(`lspServers`)에 들어 있어서, 예를 들어 TypeScript 플러그인은 `typescript-language-server --stdio`를 `.ts`, `.tsx`, `.js`, `.jsx`, `.mts`, `.cts`, `.mjs`, `.cjs` 파일에 연결합니다. 표에 없는 언어(YAML, Svelte 등)는 뒤에서 설명하는 `.lsp.json` 플러그인을 직접 만들어 붙입니다.

## `ENABLE_LSP_TOOL`(LSP 도구 활성화)은 이제 필요 없습니다

`ENABLE_LSP_TOOL`은 2.1.316에서 켜든 끄든 아무 효과가 없으므로, 예전 가이드의 "LSP 도구 활성화" 단계는 건너뛰고 `settings.json`에 남아 있다면 지워도 됩니다. 2026년 11월 2일 같은 테스트 프로젝트에서 플러그인을 설치한 채 `ENABLE_LSP_TOOL=0`을 주어도 LSP 도구가 제공되고 진단도 들어왔으며, 반대로 플러그인을 끄고 `ENABLE_LSP_TOOL=1`을 주면 LSP 도구가 없고 로그에 `Total LSP servers loaded: 0`이 찍혔습니다. LSP를 켜고 끄는 것은 플러그인입니다.

[Karan Bansal의 2026년 2월 28일 Claude Code LSP 설정 글](https://karanbansal.in/blog/claude-code-lsp/)은 이 플래그를 GitHub 이슈 #15619에서 발견된 비공식 우회법이라고 소개하며 지금도 `"env": {"ENABLE_LSP_TOOL": "1"}`을 첫 단계로 안내합니다. 하지만 같은 방식을 3월에 소개했던 Scott Spence는 [2026년 10월 10일 Claude Code LSP 재검토 글](https://scottspence.com/posts/revisiting-lsp-in-claude-code)에서 플래그를 지운 뒤에도 2.1.296에서 LSP가 그대로 동작한다고 정정했습니다. Claude Code 공식 환경 변수 문서에도 이 이름은 없습니다.

## `not found in marketplace` 오류: 공식 마켓플레이스부터 추가

설치가 `Plugin "typescript-lsp" not found in marketplace "claude-plugins-official"`로 실패하면 `/plugin marketplace add anthropics/claude-plugins-official`(셸에서는 `claude plugin marketplace add anthropics/claude-plugins-official`)로 공식 마켓플레이스를 등록한 뒤 다시 설치합니다. 오류 문구가 권하는 `claude plugin marketplace update claude-plugins-official`은 등록되지 않은 마켓플레이스를 갱신하려는 것이라 실패합니다.

2026년 11월 2일 macOS에서 대화형 세션을 한 번도 연 적 없는 새 설정 디렉터리로 셸에서 `claude plugin install typescript-lsp@claude-plugins-official`을 실행하면 위 오류와 함께 "로컬 사본이 오래되었을 수 있으니 `claude plugin marketplace update claude-plugins-official`을 해 보라"는 안내가 나왔습니다. 안내대로 실행하자 `Marketplace 'claude-plugins-official' not found. Available marketplaces: anthropic-plugin-directory`가 나왔고, `marketplace add`를 실행해 `Successfully added marketplace: claude-plugins-official`을 받은 다음에야 설치가 `typescript-lsp@claude-plugins-official (scope: user)`, 버전 1.0.0, 활성 상태로 끝났습니다.

[Claude Code 플러그인 문제 해결 문서](https://code.claude.com/docs/ko/plugins/troubleshooting)에 따르면 공식 마켓플레이스는 보통 터미널에서 대화형 세션을 처음 시작할 때 자동 등록됩니다. 따라서 VS Code 확장만 써 왔거나, 조직 정책이 이 소스를 막았거나, `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL`이 설정되어 있거나, 이전 등록 시도가 실패해 재시도를 기다리는 중이라면 아직 없을 수 있습니다. 문서는 `claude plugin` 셸 명령이 공식 마켓플레이스를 대신 등록해 주지 않는다고도 적고 있어서, 셸에서 바로 설치부터 시도하는 경우에 이 오류를 만나기 쉽습니다.

## 진단 확인: 진단 줄과 Claude가 받는 `new-diagnostics` 블록

동작 확인은 대화에 나오는 `Found N new diagnostic issues in M files (ctrl+o to expand)` 줄로 하고, 그 아래 내용은 **Ctrl+O**로 펼쳐 봅니다. 2026년 11월 2일 대화형 세션(tmux)에서 Claude가 타입 오류가 있는 `.ts` 파일을 쓰게 했을 때, 이 줄은 파일을 쓴 행 바로 아래가 아니라 그다음 도구 행("Ran 1 shell command") 아래에 표시되었습니다. 진단은 비동기로 전달되기 때문에 한 줄 늦게 보일 수 있으니 바로 아래만 보고 실패로 판단하지 않습니다.

Claude Code가 모델에게 보내는 요청을 그대로 기록하는 로컬 mock 엔드포인트로 같은 과정을 실행해 보면(실제 모델은 호출하지 않음), 진단은 파일 쓰기 도구의 결과 안에 있지 않고 다음 턴에 별도의 시스템 메시지로 들어갑니다. 언어 서버는 초기화에 69ms, 파일을 연 뒤 진단 발행까지 약 0.58초가 걸렸고, 모델이 받은 원문은 다음과 같았습니다.

```text
<new-diagnostics>The following new diagnostic issues were detected:

checkout.ts:
  ✘ [Line 3:43] Argument of type 'string' is not assignable to parameter of type 'number'. [2345] (typescript)</new-diagnostics>
```

오류를 고친 뒤에는 언어 서버가 진단 0건을 보냈고 Claude Code는 이를 건너뛰었습니다. 즉 오류를 고쳐도 "해결됨" 메시지는 따로 오지 않습니다. 그렇다고 진단이 없다는 것이 곧 파일에 오류가 없다는 뜻은 아닙니다. 진단은 다음 턴에 오기 때문에 편집이 대화의 마지막 동작이면 오류가 보고되지 않을 수 있습니다. Scott Spence도 같은 글에서 짧은 세션 두 번은 타입 오류가 보고되지 않았고 긴 세션에서는 약 30초 뒤에 도착했다고 적었으므로, 작업을 끝내기 전 타입 검사 명령을 한 번 돌리게 하는 편이 안전합니다. 그의 테스트에서는 Claude가 셸(Bash)로 이미 열려 있던 파일에 줄을 덧붙인 변경도 언어 서버에 반영되지 않았고, 그가 인용한 Claude Code 이슈에는 `git checkout`이나 포매터로 바뀐 파일에서도 같은 일이 생긴다고 적혀 있습니다.

`LSP` 탐색 도구는 처음부터 도구 목록에 있지 않습니다. 같은 기록에서 Claude가 `.ts` 파일을 처음 쓰거나 읽은 뒤에야 "ToolSearch로 쓸 수 있는 지연 로드 도구"로 `LSP`가 안내되었고, 도구 정의는 Claude가 ToolSearch로 불러온 다음에 전달되었습니다. 그래서 Claude가 LSP를 한 번도 안 쓴 세션이라도 설치가 잘못된 것은 아닐 수 있고, 연결 여부는 진단 줄로 판단하는 것이 가장 확실합니다.

## Claude Code LSP가 안 될 때: 증상별 원인과 해결

"설치했는데 아무 변화가 없다"는 증상은 원인이 여럿이지만, 대부분은 `/plugin`의 **Errors** 탭이나 `claude --debug` 로그 한 줄로 구분됩니다. 2026년 11월 2일 테스트에서 언어 서버가 PATH에 없을 때와 프로젝트에 `typescript` 패키지가 없을 때 모두, 모델은 진단도 오류 문구도 받지 못한 채 `LSP` 도구 안내만 받았습니다. Claude가 "LSP가 고장 났다"고 말해 주지 않으므로 아래 표의 확인 위치를 직접 봐야 합니다.

| 증상 | 어디서 보이나 | 원인 | 해결 |
| --- | --- | --- | --- |
| 설치 명령이 `Plugin "typescript-lsp" not found in marketplace "claude-plugins-official"`로 실패 | 설치 명령 출력 | 공식 마켓플레이스 미등록 | `/plugin marketplace add anthropics/claude-plugins-official` 후 다시 설치 |
| 설치는 됐는데 이번 세션에서 반응 없음 | 설치 확인 메시지(권장 창에서 설치했다면 `installed · restart to apply`) | 현재 세션에 아직 로드되지 않음 | 새 세션 시작 또는 `/reload-plugins --force` |
| 진단 줄이 안 뜨고 Claude도 아무 말 없음 | `/plugin` Errors 탭에 `Executable not found in $PATH: "typescript-language-server"` | 언어 서버가 없거나 `claude`를 띄운 셸의 PATH에 없음 | 언어 서버 설치, `which`로 확인, 그 셸에서 새 세션 |
| TypeScript에서 진단 줄이 안 뜨고 PATH 오류도 없음 | `claude --debug` 로그의 `Could not find a valid TypeScript installation` | 프로젝트에 `typescript` 패키지가 없어 서버가 초기화 중 종료 | 프로젝트에서 `npm install -D typescript` |
| LSP 호출이 `server is starting` 오류로 끝남 | 도구 결과 | 첫 편집 직후 서버가 아직 시작 중 | 몇 초 뒤 다시 호출 |
| 세션 첫 `findReferences`가 정의 1건만 돌려줌 | 도구 결과 `Found 1 reference` | 프로젝트 로딩이 끝나기 전에 응답 | 다시 호출하거나 grep으로 대조, TypeScript는 아래 `useSyntaxServer` 우회 |
| `No LSP server available for file type: .md` | 도구 결과 | 그 확장자를 맡은 플러그인이 없음 | 해당 언어 플러그인 설치, 없으면 `.lsp.json` 작성 |
| 플러그인이 있는데 LSP 도구, 진단, 권장 창 모두 없음 | `/plugin`의 Installed 탭이나 `claude plugin list`에서 Status가 disabled | 플러그인이 꺼져 있음 | `/plugin enable typescript-lsp@claude-plugins-official`(셸에서는 `claude plugin enable typescript-lsp@claude-plugins-official`) 후 새 세션 |
| 클라우드 세션에서 진단, 탐색 모두 없음 | 표시 없음 | 클라우드 세션은 플러그인 언어 서버를 시작하지 않음 | 로컬 터미널 세션에서 작업 |
| 모노레포에서 내부 패키지 import를 못 찾는다는 진단 | 진단 내용 | 언어 서버가 그 워크스페이스에 맞게 설정되지 않음 | Claude Code 쪽에서 고칠 것은 없고, 이 진단은 Claude의 편집을 막지 않음 |

![Claude Code LSP 문제를 설치 명령 출력, /plugin Errors 탭, claude --debug 로그, LSP 도구 결과의 네 곳에서 찾는 원인과 해결 정리](https://blog.laozhang.ai/posts/ko/claude-code-lsp/img/claude-code-lsp-troubleshooting.webp)

PATH 문제일 때 `claude --debug` 로그에는 `LSP server plugin:typescript-lsp:typescript failed to start: Executable not found in $PATH: "typescript-language-server"`처럼 서버 이름과 이유가 함께 찍힙니다. 언어 서버를 설치한 뒤에는 Claude가 다음에 맞는 파일을 편집할 때 다시 시도하지만, `claude`를 띄운 셸의 PATH에 그 경로가 없다면 경로가 잡힌 셸에서 새 세션을 열어야 합니다. 프로젝트에 `typescript`가 없는 경우는 2026년 11월 2일 테스트에서 debug 로그에만 이유가 남았고, 플러그인 README의 전역 설치 명령은 `typescript-language-server`와 `typescript`를 함께 설치하므로 README 명령을 그대로 썼다면 대개 이 문제를 피합니다.

`server is starting` 오류는 2026년 11월 2일 mock 엔드포인트로 첫 편집 직후 곧바로 `goToDefinition`, `findReferences`, `hover`, `workspaceSymbol`을 부른 테스트에서 모두 `Cannot send notification to LSP server 'plugin:typescript-lsp:typescript': server is starting`으로 나왔고, 4초 기다린 뒤에는 정상 결과가 돌아왔습니다. mock은 밀리초 단위로 답하기 때문에 실제 모델이 이렇게 빨리 부르는 일은 드물지만, 시작 중인 구간이 있다는 점은 알아 둘 만합니다. 클라우드와 로컬 세션을 구분하는 방법은 [Claude Code 웹판이 있나요: 클라우드 Web, Remote Control, Desktop을 먼저 나눠야 합니다](https://blog.laozhang.ai/ko/posts/claude-code-web-interface)에 정리되어 있습니다.

`/reload-plugins`로 LSP 도구가 추가되거나 빠지면 Claude Code는 `This reload adds the LSP tool`(또는 `removes`)로 시작하는 경고를 띄우고 `--force`를 붙여야 적용합니다. 도구 목록이 바뀌면 프롬프트 캐시가 깨져 다음 메시지가 대화 전체를 다시 읽기 때문인데, 비용이 어떻게 달라지는지는 [Claude Code 캐시 미스 토큰 비용: 한 turn 이 갑자기 비싸지는 이유](https://blog.laozhang.ai/ko/posts/claude-code-cache-miss-token-costs)를 참고하고, 대화가 길다면 새 세션을 여는 편이 낫습니다. 설정이 꼬여 Claude Code가 제대로 뜨지 않을 때는 `CLAUDE_CODE_SAFE_MODE=1` 또는 `--safe-mode`로 LSP 서버를 건너뛴 채 시작해 원인을 좁힐 수 있습니다.

## 첫 `findReferences`가 1건만 나올 때: `useSyntaxServer` 우회

TypeScript에서 세션의 첫 `findReferences`가 정의 자체 1건만 돌려준다면, `typescript-lsp` 서버 설정에 `"initializationOptions": {"tsserver": {"useSyntaxServer": "never"}}`를 더하는 우회가 통합니다. 2026년 11월 2일 파일 3개짜리 테스트 프로젝트에서 공식 플러그인 그대로 세션 3개를 열어 `priceWithTax`의 참조를 세 번씩 물었더니 결과가 1, 5, 5 / 1, 1, 1 / 1, 1, 5건으로 첫 호출은 3개 세션 모두 `Found 1 reference: src/price.ts:1:17`이었습니다(정답은 3개 파일의 5건). 같은 설정에 이 옵션만 더한 로컬 플러그인으로는 세션 2개 모두 5, 5, 5건이 나왔습니다.

[Scott Spence의 2026년 10월 10일 테스트](https://scottspence.com/posts/revisiting-lsp-in-claude-code)도 같은 현상을 보고합니다. 그의 SvelteKit 저장소에서 새 세션의 첫 호출은 처음 19개 세션 중 18개, 시간을 잰 13개 세션 전부에서 틀렸고, 원인은 Claude Code가 프로젝트 로딩이 끝나기 전에 질문하고 `typescript-language-server`가 그동안 열린 파일만 아는 가벼운 syntax server로 답하기 때문이라고 설명합니다. Python 언어 서버에서도 "처음엔 1건, 다음엔 전부"라는 보고가 있어 Claude Code 저장소에 열린 이슈로 추적되고 있다고 하며, 옵션을 넣은 뒤 그의 12개 세션은 첫 호출부터 맞았습니다. 대신 첫 호출이 로딩을 기다리느라 그의 프로젝트에서 약 2초로 느려졌고, 메모리는 4개 프로세스 약 935MB에서 3개 프로세스 약 725MB로 줄었습니다.

옵션을 넣은 서버 설정은 공식 플러그인의 TypeScript 항목에 `initializationOptions` 한 블록을 더한 것입니다.

```json
{
  "typescript": {
    "command": "typescript-language-server",
    "args": ["--stdio"],
    "extensionToLanguage": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact", ".mts": "typescript", ".cts": "typescript", ".mjs": "javascript", ".cjs": "javascript" },
    "initializationOptions": { "tsserver": { "useSyntaxServer": "never" } }
  }
}
```

이 설정을 넣는 방법은 Scott이 소개한 두 가지입니다. 첫째는 `~/.claude/plugins/marketplaces/claude-plugins-official/.claude-plugin/marketplace.json`에서 `lspServers` 아래 `typescript` 항목을 찾아 `initializationOptions` 블록을 직접 더하는 방법인데, 마켓플레이스가 업데이트되면 덮어써질 수 있습니다. 둘째는 위 내용을 `.lsp.json`으로 가진 별도 플러그인을 만들어 설치하고 `/plugin disable typescript-lsp@claude-plugins-official`로 공식 플러그인을 끄는 방법으로, 두 플러그인이 같은 확장자를 맡기 때문에 하나만 켜 둡니다. 위 테스트의 5, 5, 5건은 두 번째 방식으로, 이 `.lsp.json`을 담은 로컬 플러그인을 `--plugin-dir`로 불러오고 공식 플러그인을 끈 상태에서 나온 결과입니다.

이 우회는 TypeScript 서버에만 해당하고, Claude Code 쪽에서 버그가 고쳐지면 공식 플러그인으로 되돌리면 됩니다. 테스트 프로젝트가 파일 3개뿐이었으므로 큰 저장소에서 첫 호출이 얼마나 더 기다리는지는 따로 확인해야 합니다.

## "LSP plugin recommendation" 창: 네 가지 선택지와 되돌리는 법

"LSP plugin recommendation"(LSP 플러그인 권장) 창은 내 컴퓨터에 언어 서버는 있는데 그것을 쓰는 플러그인이 설치되지 않았을 때 Claude Code가 플러그인 설치를 제안하는 대화상자이고, 그 언어를 계속 쓸 생각이라면 **Yes, install**을 고르면 됩니다. 2026년 11월 2일 대화형 세션에서 `typescript-lsp`를 제거하고 `typescript-language-server`만 PATH에 둔 채 Claude가 `.ts` 파일을 쓰게 하자, 턴이 끝나자마자 `Plugin: typescript-lsp`, `Marketplace: claude-plugins-official`, `Triggered by: .ts files`를 보여 주는 창이 떴습니다. 같은 조건에서 플러그인을 제거하지 않고 비활성화만 해 두었을 때는 창이 뜨지 않았습니다.

| 선택지 | 결과 |
| --- | --- |
| 1. Yes, install (설치) | 사용자 계정 범위로 플러그인을 설치하고 `installed · restart to apply`를 출력합니다. 새 세션을 열어야 서버가 로드됩니다 |
| 2. No, not now (나중에) | 창만 닫히고 나중 세션에서 다시 제안될 수 있습니다. Esc도 같습니다 |
| 3. Never for this plugin (이 플러그인은 다시 묻지 않기) | 그 플러그인은 다시 제안하지 않고, 다른 언어 플러그인은 계속 제안합니다 |
| 4. Disable all LSP recommendations (모든 권장 끄기) | 어떤 언어에 대해서도 창이 뜨지 않습니다 |

창은 세션당 한 번, Claude가 처음 편집하는 해당 확장자 파일에서만 뜨고, 여러 마켓플레이스가 같은 확장자의 플러그인을 가지면 공식 마켓플레이스 쪽을 제안합니다. 30초 동안 아무것도 고르지 않으면 무시한 것으로 세고, 무시가 세션을 넘어 5번 쌓이면 4번을 고른 것처럼 권장이 멈춥니다. 다시 켜려면 Claude Code 자체 설정 파일인 `~/.claude.json`에서 `lspRecommendationDisabled`와 `lspRecommendationIgnoredCount` 키를 지우고, 3번으로 막은 플러그인 하나만 되살리려면 `lspRecommendationNeverPlugins` 목록에서 `typescript-lsp@claude-plugins-official` 같은 `name@marketplace` 항목을 지웁니다. 클라우드 세션(`claude --cloud`)에 연결된 터미널에서는 이 창이 뜨지 않습니다.

## 공식 플러그인 없는 언어: `.lsp.json` 작성과 `--plugin-dir` 로드

YAML이나 Svelte처럼 공식 표에 없는 언어는 언어 서버 명령과 확장자를 적은 `.lsp.json` 파일 하나로 플러그인을 만들어 붙입니다. 2026년 11월 2일 `yaml-language-server --stdio`를 `.yaml`, `.yml`에 연결하는 플러그인 `yaml-lsp-local`을 만들어 불러온 과정은 다음과 같습니다(언어 서버 자체는 설치하지 않고 설정 로드까지만 확인).

1. 플러그인 폴더를 만들고 `.claude-plugin/plugin.json`에 이름을 적습니다. 테스트에서는 `{ "name": "yaml-lsp-local", "version": "0.1.0", "description": "yaml-language-server for .yaml/.yml" }`를 썼습니다.
2. 플러그인 폴더 최상위에 `.lsp.json`을 만듭니다.
3. `claude --debug --plugin-dir ./yaml-lsp-local`처럼 `--plugin-dir`로 한 세션 동안 불러오고, debug 로그에 `Loaded 1 LSP server(s) from plugin: yaml-lsp-local`이 찍히는지 봅니다.
4. 계속 쓰려면 마켓플레이스에 게시해 일반 플러그인처럼 설치합니다.

```json
{
  "yaml": {
    "command": "yaml-language-server",
    "args": ["--stdio"],
    "extensionToLanguage": { ".yaml": "yaml", ".yml": "yaml" }
  }
}
```

[Claude Code 플러그인 레퍼런스의 lspServers 항목](https://code.claude.com/docs/en/plugins-reference#lspservers)에 따르면 필수 필드는 `command`와 `extensionToLanguage` 두 개입니다. `command`에는 `/`로 시작하는 경로가 아니면 공백을 넣을 수 없어 인자는 `args`로 분리하고, `extensionToLanguage`의 키는 `".go"`처럼 점으로 시작해야 합니다. 선택 필드로는 `env`, `initializationOptions`, `settings`, `workspaceFolder`, `startupTimeout`, `shutdownTimeout`, `requestTimeout`(기본 60000ms, 2.1.288부터), `restartOnCrash`(기본 true), `maxRestarts`, `diagnostics`(편집 후 진단, 기본 true)가 있고, 목록에 없는 키가 하나라도 있으면 설정 전체가 거부됩니다.

함정은 `claude plugin validate`가 `.lsp.json` 내용을 검사하지 않는다는 점입니다. 같은 날 올바른 파일과, 일부러 망가뜨린 세 가지(없는 키 `extensions`, 공백이 들어간 `command`, 점 없는 확장자 키) 모두에 대해 validate는 "Validation passed with warnings"를 출력했고, 경고는 README, LICENSE, 아이콘이 없다는 내용뿐이었습니다. 실제로 `--plugin-dir`로 불러오자 `extensions` 키를 쓴 파일은 debug 로그에 `LSP config validation failed for .lsp.json in plugin yaml-lsp-local`과 `Unrecognized key: "extensions"`가 남고 서버가 로드되지 않았습니다. 그러니 validate 통과가 아니라 debug 로그의 `Loaded 1 LSP server(s)` 줄로 확인합니다. 플러그인으로 무엇을 할 수 있고 남이 만든 LSP 플러그인 모음을 설치하기 전에 무엇을 볼지는 [Claude Code mods 시작하기: 설치 전 validate 점검과 첫 mod 만들기](https://blog.laozhang.ai/ko/posts/claude-code-mods)에서 이어서 다룹니다.

## Claude Code LSP를 계속 켜 둘지: 메모리, VS Code, grep

LSP를 켜 둘지는 언어 서버가 쓰는 메모리, 쓰는 환경이 터미널인지 VS Code인지, 그리고 Claude가 실제로 LSP를 얼마나 쓰는지에 따라 달라집니다. 편집 후 진단은 grep이 대신할 수 없는 기능이라 대부분의 경우 켜 둘 가치가 있지만, 아래 세 조건에서는 판단이 바뀝니다.

### 언어 서버 메모리가 부담될 때

`rust-analyzer`와 `pyright`처럼 프로젝트 전체를 인덱싱하는 언어 서버가 메모리를 많이 쓴다면, [공식 문제 해결 문서](https://code.claude.com/docs/ko/plugins/troubleshooting)대로 세션에서 `/plugin disable pyright-lsp@claude-plugins-official`처럼 그 플러그인만 끄고 Claude의 기본 검색 도구에 맡깁니다. 끄면 그 언어의 편집 후 진단도 함께 사라지므로, 메모리가 넉넉한 기기에서는 켜 두고 큰 저장소나 메모리가 적은 기기에서만 끄는 편이 낫습니다. Linux와 WSL에서는 언어 서버가 `CLAUDE_CODE_TOOL_MEMORY_LIMIT` 상한에 포함될 수 있고, `CLAUDE_CODE_TOOL_MEMORY_CGROUP_EXCLUDE=lsp`로 언어 서버를 그 상한에서 뺄 수 있습니다.

### VS Code에서 Claude Code를 쓸 때

VS Code에서 쓰더라도 편집 후 자동 진단과 `LSP` 탐색 도구를 원한다면 플러그인을 설치해야 합니다. [Claude Code VS Code 문서](https://code.claude.com/docs/ko/vs-code)를 보면 VS Code와 연결된 Claude Code는 `mcp__ide__getDiagnostics`, 채팅 패널(2.1.285 이상)에서는 `mcp__claude-vscode__getDiagnostics`로 VS Code 문제(Problems) 패널의 오류를 읽을 수 있는데, 이것은 편집기가 쓰는 언어 서버의 결과를 Claude가 요청할 때 읽어 오는 별도 구조입니다. 그래서 플러그인 없이도 VS Code 문제 패널 정보는 받을 수 있지만, 편집할 때마다 들어오는 진단과 기호 탐색 도구는 플러그인을 설치해야 생깁니다(문서 구조에서 나오는 판단입니다).

### LSP를 설치해도 Claude가 grep을 쓸 때

LSP를 설치해도 Claude는 정의나 참조를 찾을 때 여전히 grep을 자주 고르고, 그것이 꼭 손해는 아닙니다. Scott Spence의 기록에서 LSP를 켠 뒤 약 650개 세션 중 LSP 호출은 15개 세션의 32번뿐이었고, `CLAUDE.md`에 "LSP를 먼저 쓰라"는 규칙을 넣으면 기호를 묻는 프롬프트 12개 중 12개에서 LSP를 썼지만 규칙을 빼면 절반 정도로 줄었습니다. 같은 글의 54개 세션 비교에서는 참조 찾기에서 grep만 쓴 경우가 매번 맞으면서 가장 빠르고 저렴했고, LSP `hover`는 정확한 타입을 한 번에 알려 주는 데 강했습니다.

Scott은 그 결과를 보고 규칙을 뒤집어 "사용처는 grep으로 찾고, 정확한 타입이 중요할 때는 LSP `hover`를 쓰며, 시그니처를 바꾸거나 지우기 전에는 `findReferences` 결과를 grep으로 대조한다"로 바꿨습니다. 그의 실험은 작은 SvelteKit 프로젝트, 모델 하나, 질문별 3회 반복이었으므로 이름이 겹치는 기호가 많은 큰 코드베이스에서는 결과가 다를 수 있습니다. 이런 우선순위를 `CLAUDE.md` 규칙으로 둘지 skill이나 hook으로 강제할지는 [Claude Code Hooks·Skills·슬래시 명령어 차이와 사용 예제](https://blog.laozhang.ai/ko/posts/claude-code-hooks-slash-commands-skills)를 보고 고르면 됩니다.

## Claude Code LSP 설정에 대한 그 밖의 질문

### Claude Code는 몇 버전부터 LSP를 지원하나요?

[Claude Code 변경 로그](https://code.claude.com/docs/en/changelog)를 보면 `LSP` 도구는 2.0.74(2025년 12월 19일)에 들어왔고, 2026년 3월 12일 2.1.74에서 Windows에서 파일 URI가 잘못 만들어지던 문제가 고쳐졌으며, 2026년 10월 2일 2.1.288부터는 LSP 요청이 60초 뒤 시간 초과되고 `requestTimeout`으로 이 값을 바꿀 수 있습니다. 2026년 10월 31일 나온 2.1.316이 11월 2일 기준 최신이므로, 오래된 버전에서 Windows나 시간 초과 문제를 겪는다면 먼저 업데이트합니다.

### `claude -p --bare`로 돌리는 스크립트에서도 진단이 들어오나요?

들어오지 않습니다. Claude Code 문서에 따르면 `--bare`는 스크립트용 `-p` 실행에서 LSP 서버를 건너뛰므로, 진단이나 `LSP` 도구가 필요한 자동화라면 `--bare` 없이 실행해야 합니다.

### `Read` 권한 규칙이 LSP 도구에도 적용되나요?

적용됩니다. Claude Code 도구 레퍼런스에 따르면 `Read(...)` 경로 규칙으로 막은 파일은 `LSP` 도구로도 조회되지 않고, `LSP` 도구 자체는 읽기 전용이라 실행할 때 권한 확인 창을 띄우지 않습니다.

## 참고 자료

이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026-11-02.

- [Claude Code 공식 코드 인텔리전스 플러그인 문서](https://code.claude.com/docs/ko/plugins/code-intelligence) (code.claude.com)
- [Karan Bansal의 2026년 2월 28일 Claude Code LSP 설정 글](https://karanbansal.in/blog/claude-code-lsp/) (karanbansal.in)
- [2026년 10월 10일 Claude Code LSP 재검토 글](https://scottspence.com/posts/revisiting-lsp-in-claude-code) (scottspence.com)
- [Claude Code 플러그인 문제 해결 문서](https://code.claude.com/docs/ko/plugins/troubleshooting) (code.claude.com)
- [Claude Code 플러그인 레퍼런스의 lspServers 항목](https://code.claude.com/docs/en/plugins-reference) (code.claude.com)
- [Claude Code VS Code 문서](https://code.claude.com/docs/ko/vs-code) (code.claude.com)
- [Claude Code 변경 로그](https://code.claude.com/docs/en/changelog) (code.claude.com)
