개발/Visual Studio Code

커맨드 팔레트 44부: VS Code Terminal 텍스트 선택 중 Task 종료 단축키 잠그기

반응형
VS CODE 초보자 시리즈 · 커맨드 팔레트 44부

Terminal 텍스트 선택 중에는 Task 종료 단축키 잠그기

Task Terminal의 출력을 선택해 복사하는 동안에는 종료 단축키를 막고, 선택을 해제하면 다시 켜지는 안전한 User 단축키를 만듭니다.

!terminalTextSelected를 추가해 선택 없음 → ON, 텍스트 선택 → OFF 전환을 확인하고 실습 설정을 원복합니다.

출력을 복사하려다 종료 chord를 눌러 실행 중인 Task를 끊는 실수를 줄이는 것이 목표입니다.

1. 시작하기 전에

난이도는 초급 후반입니다. User 범위 JSON 한 곳과 Workspace 범위 Task 두 개를 다루며, 실제 종료 전에 네 Context Key와 Target label을 확인해야 합니다.

준비할 것

  • Windows 11, VS Code Stable 1.137.0, PowerShell — Help > About과 $PSVersionTable로 확인합니다.
  • 신뢰 가능한 연습 폴더 — File > Open Folder로 열고 Restricted Mode가 아닌지 확인합니다.
  • User keybindings.json 백업 — Preferences: Open Keyboard Shortcuts (JSON)에서 전체 파일을 별도 위치에 복사합니다.
  • 기존 .vscode/tasks.json — 파일이 있으면 전체 덮어쓰기 없이 예제 객체만 tasks 배열에 병합합니다.

적용 환경 한국어 초보자 · Windows 11 · VS Code Stable 1.137.0 · Windows PowerShell

안전하게 시작하기 Task 종료는 자식 프로세스와 미저장 작업을 끊을 수 있습니다. 배포·백업·데이터 변환 대신 즉시 다시 만들 수 있는 연습용 Task만 사용하세요. 기존 User 단축키, 기존 Task, 복사하려는 출력이 보호 대상입니다. 중단 조건: Restricted Mode, chord 충돌, JSON 오류, Target 불일치, 종료하면 안 되는 active Task입니다.

2. 알아둘 핵심 개념

terminalTextSelected와 논리 NOT !

terminalTextSelected는 활성 Terminal에 텍스트 선택 영역이 있으면 true입니다. 앞의 !는 Boolean을 뒤집으므로 !terminalTextSelected는 선택이 없을 때 true, 선택이 있을 때 false입니다.

네 Context Key가 만드는 gate

  • taskRunning: 하나 이상의 Task가 실행 중입니다.
  • terminalFocus: 통합 Terminal이 키보드 포커스를 가집니다.
  • taskTerminalActive: 활성 Terminal이 Task가 만든 Terminal입니다.
  • terminalTextSelected: 활성 Terminal에 선택된 텍스트가 있습니다.

&&는 모든 조건을 요구합니다. 따라서 전체 식은 실행 중 Task Terminal에 포커스가 있고 선택이 없을 때만 종료 rule을 허용합니다. 하지만 이 gate는 args의 Target이 실행 중인지까지 보장하지 않으므로 Target 부재 Quick Pick을 따로 확인해야 합니다.

3. 순서대로 진행하기

각 단계의 정상 결과를 확인한 뒤 다음 단계로 이동합니다. Ctrl+K Ctrl+Alt+T는 예시 chord이며 충돌하면 미사용 chord로 바꾸세요.

1. User 단축키를 백업하고 충돌 확인하기

목적 기존 단축키를 보호하고 예제 chord의 선점 여부를 확인합니다.

  1. Ctrl+K Ctrl+S를 열어 ctrl+k ctrl+alt+t를 검색하고 Show Same Keybindings를 확인한 뒤 User keybindings.json 전체를 별도 백업 파일에 복사합니다.

입력 위치 Keyboard Shortcuts UI, User keybindings.json, 사용자가 선택한 로컬 백업 폴더

C:\Users\<사용자이름>\Documents\keybindings.backup-20260912.json

<사용자이름>은 실제 Windows 계정 폴더명으로 바꿉니다. 이 경로는 파일에 입력하는 설정이 아니라 백업 위치 예시입니다.

정상 결과 충돌 rule과 적용 조건을 확인했고 백업의 첫 줄과 마지막 줄이 보입니다.

확인 백업을 다시 열어 JSON 전체가 읽히는지 확인합니다.

실패 신호 빈 백업, JSON 잘림, 중요 명령과 chord 충돌

주의 충돌을 무시하면 다른 명령이 먼저 실행될 수 있습니다. 되돌리기: 아직 설정을 저장하지 말고 다른 미사용 chord를 정한 뒤 Step 1을 반복합니다.

2. 두 연습용 process Task 추가하기

목적 종료 Target과 Target 부재 확인용 Guard를 분리합니다.

  1. .vscode/tasks.json의 tasks 배열에 아래 두 객체를 추가하고 저장합니다.

입력 위치 연습 Workspace의 .vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "JCOS Selection Lock Target",
      "type": "process",
      "command": "powershell.exe",
      "args": [
        "-NoProfile",
        "-Command",
        "$id=[guid]::NewGuid().ToString('N').Substring(0,8); Write-Output ('SELECTION_LOCK_TARGET RUN_ID='+$id); for($i=0;$i -lt 30;$i++){ Write-Output ('SELECTION_LOCK_TARGET HEARTBEAT='+$i); Start-Sleep -Seconds 1 }"
      ],
      "problemMatcher": [],
      "presentation": { "reveal": "always", "panel": "dedicated", "clear": true }
    },
    {
      "label": "JCOS Selection Lock Guard",
      "type": "process",
      "command": "powershell.exe",
      "args": [
        "-NoProfile",
        "-Command",
        "$id=[guid]::NewGuid().ToString('N').Substring(0,8); Write-Output ('SELECTION_LOCK_GUARD RUN_ID='+$id); for($i=0;$i -lt 30;$i++){ Write-Output ('SELECTION_LOCK_GUARD HEARTBEAT='+$i); Start-Sleep -Seconds 1 }"
      ],
      "problemMatcher": [],
      "presentation": { "reveal": "always", "panel": "dedicated", "clear": true }
    }
  ]
}
정상 결과 Tasks: Run Task 목록에 JCOS Selection Lock Target과 JCOS Selection Lock Guard가 보입니다.

확인 JSON parser 오류가 없고 두 label이 정확히 일치합니다. type은 String, args는 String Array, problemMatcher는 Array입니다.

실패 신호 Expected comma, End of file expected, Task가 목록에 없음

주의 기존 tasks.json 전체를 덮어쓰지 마세요. 되돌리기: 기존 배열을 복원하고 예제 객체를 하나씩 병합하며 오류 원문을 보존합니다.

3. Target Task를 실행하고 선택 없음 확인하기

목적 Task Terminal과 관찰 가능한 RUN_ID/HEARTBEAT를 만들고 선택 없는 기준 상태를 확인합니다.

  1. Ctrl+Shift+P > Tasks: Run Task > JCOS Selection Lock Target을 선택하고 Terminal의 빈 곳을 한 번 클릭합니다.

입력 위치 Command Palette와 자동으로 열린 전용 Terminal

SELECTION_LOCK_TARGET RUN_ID=<8자리 값>
SELECTION_LOCK_TARGET HEARTBEAT=<증가 숫자>
정상 결과 RUN_ID 한 줄 뒤 HEARTBEAT가 1초마다 증가하고 텍스트 선택 영역이 없습니다.

확인 Developer: Inspect Context Keys에서 taskRunning=true, terminalFocus=true, taskTerminalActive=true, terminalTextSelected=false를 확인합니다.

실패 신호 즉시 종료, PowerShell 경로/정책 오류, 다른 Task label, 선택 영역 잔존

주의 종료 전에 label과 RUN_ID를 확인하세요. 되돌리기: Esc로 선택을 해제합니다. Task 자체가 실패하면 연습 Target만 종료하고 Step 2 정의를 확인한 뒤 Step 3으로 돌아옵니다.

4. 네 조건을 가진 종료 rule 저장하기

목적 Task Terminal의 텍스트 선택 중에는 Target 종료 명령을 비활성화합니다.

  1. User keybindings.json 배열에 다음 객체를 추가하거나 이전 편 객체의 when만 교체합니다.

입력 위치 Preferences: Open Keyboard Shortcuts (JSON), User 범위

[
  {
    "key": "ctrl+k ctrl+alt+t",
    "command": "workbench.action.tasks.terminate",
    "args": "JCOS Selection Lock Target",
    "when": "taskRunning && terminalFocus && taskTerminalActive && !terminalTextSelected"
  }
]
정상 결과 Keyboard Shortcuts 검색 결과에 명령, chord, 네 조건이 한 User rule로 표시됩니다.

확인 key, command, args, when은 모두 String입니다. && 앞뒤 공백과 terminalTextSelected 앞의 !를 확인합니다.

실패 신호 빨간 밑줄, 쉼표 오류, 같은 rule 중복, terminalTextSelected 오탈자

주의 User 범위 변경은 모든 Workspace에 적용됩니다. 되돌리기: 저장을 취소하고 백업을 복원한 뒤 객체 하나만 다시 추가해 Step 4로 돌아옵니다.

5. 선택 없음에서 rule 활성 확인하기

목적 모든 조건이 true일 때 종료 rule이 활성인 기준선을 만듭니다.

  1. Target Task Terminal 본문을 클릭하고 Esc를 눌러 선택을 비운 뒤 Context Key와 Target RUN_ID를 기록합니다.

입력 위치 Target Task Terminal, Developer: Inspect Context Keys

terminalTextSelected = false
!terminalTextSelected = true
종료 rule = ON
정상 결과 Keyboard Shortcuts UI에서 rule이 활성이고 네 Context Key가 기대값과 일치합니다.

확인 실제 종료는 아직 하지 않고 Developer: Toggle Keyboard Shortcuts Troubleshooting을 켜 로그 준비 상태만 확인합니다.

실패 신호 terminalTextSelected=true가 남아 있거나 rule이 비활성

주의 이 단계에서는 chord를 누르지 않습니다. 되돌리기: Esc로 선택을 지우고 Terminal 본문을 다시 클릭한 뒤 Step 5를 반복합니다.

6. 텍스트 선택으로 종료 chord 잠그기

목적 복사하려는 출력이 선택된 동안 종료 명령이 dispatch되지 않음을 확인합니다.

  1. Target Terminal에서 RUN_ID 줄 일부를 마우스로 드래그해 선택하고 Context Key를 다시 검사한 뒤 chord를 한 번 누릅니다.

입력 위치 Target Task Terminal과 Keyboard Shortcuts Troubleshooting Output

terminalTextSelected = true
!terminalTextSelected = false
종료 rule = OFF
정상 결과 종료 rule은 match되지 않고 동일 RUN_ID의 HEARTBEAT가 계속 증가합니다.

확인 Troubleshooting 로그에 종료 command 미호출이 보이고 2초 뒤 Target 출력이 증가합니다.

실패 신호 Target 종료, 다른 명령 실행, 선택 영역 소실

주의 예상과 다르면 추가 입력을 멈추고 로그를 보존하세요. 되돌리기: rule을 제거하고 백업을 복원한 뒤 Tasks: Terminate Task로 연습 Target만 정리합니다.

7. Ctrl+C 복사와 선택 해제 후 재활성 확인하기

목적 선택 보호가 복사 흐름을 방해하지 않고 선택 해제 후 종료 rule이 다시 활성화되는지 확인합니다.

  1. 선택이 유지된 상태에서 Ctrl+C로 복사해 저장하지 않을 새 임시 편집기에 붙여넣고, Terminal로 돌아와 Esc로 선택을 해제합니다.

입력 위치 Target Task Terminal과 새 임시 텍스트 편집기

복사 결과 = 선택한 RUN_ID 문자열
terminalTextSelected = true → false
종료 rule = OFF → ON
정상 결과 붙여넣은 문자열이 선택한 출력과 일치하고 Esc 뒤 rule이 다시 활성화됩니다.

확인 Context Key에서 terminalTextSelected=false를 확인하고 Target HEARTBEAT가 계속 증가하는지 봅니다.

실패 신호 복사 내용 불일치, Esc 뒤 선택 잔존, rule 비활성

주의 임시 편집기에는 비밀·개인정보를 복사하지 마세요. 되돌리기: 임시 편집기를 저장하지 않고 닫고, Terminal 본문에서 Terminal: Clear Selection 또는 Esc를 사용한 뒤 Step 7을 반복합니다.

8. 선택 없음에서 Target 종료하기

목적 보호할 선택이 없을 때만 Target을 종료합니다.

  1. 선택 영역이 없고 label/RUN_ID가 맞는지 확인한 뒤 chord를 한 번 누릅니다.

입력 위치 Target Task Terminal

Human Gate
label = JCOS Selection Lock Target
terminalTextSelected = false
RUN_ID = <Step 3에서 기록한 값>
정상 결과 Target만 종료되고 동일 RUN_ID의 출력이 더 이상 증가하지 않습니다.

확인 2초 뒤 출력 길이가 그대로이며 Tasks: Show Running Tasks에 Target이 없습니다.

실패 신호 Quick Pick 열림, 다른 Task 종료, 새 RUN_ID 생성

주의 잘못 종료한 중요한 Task를 임의 재실행하지 마세요. 되돌리기: Quick Pick은 Esc로 취소하고 label/args를 맞춘 뒤 Step 3부터 다시 수행합니다.

9. Target 부재 fallback을 취소하고 원복하기

목적 gate가 Target 존재를 보장하지 않는 한계를 확인하고 실습 상태를 제거합니다.

  1. Guard Task를 실행하고 선택이 없는 Guard Terminal에서 chord를 누른 뒤 나타난 Quick Pick을 Esc로 닫습니다. 이어 Guard를 수동 종료하고 keybinding 객체와 두 Task 객체를 제거합니다.

입력 위치 Guard Task Terminal, Select a task to terminate Quick Pick, User keybindings.json, Workspace .vscode/tasks.json

Target = 없음
Guard = 실행 중
Quick Pick = Esc로 취소
최종 User rule / 예제 Task = 없음
정상 결과 Esc 취소 뒤 Guard가 계속 실행되고, 정리 후 실행 중 연습 Task·User rule·예제 label이 모두 없습니다.

확인 Tasks: Show Running Tasks, Keyboard Shortcuts @source:user, Problems를 교차 확인합니다.

실패 신호 Guard 종료, All Running Tasks 선택, JSON 오류, User rule 또는 예제 label 잔존

주의 Quick Pick에서는 아무 항목도 누르지 않고 Esc로 취소합니다. 되돌리기: Guard는 label을 확인해 종료하고 백업에서 keybindings.json을 복원합니다. tasks.json은 예제 객체만 제거합니다.

4. 완료 확인하기

입력 화면과 독립된 Context Key, Troubleshooting 로그, Task 출력 수명주기로 교차 확인합니다.

  • 선택 없음 — taskRunning/terminalFocus/taskTerminalActive=true, terminalTextSelected=false, 종료 rule ON
  • 선택 있음 — terminalTextSelected=true, !terminalTextSelected=false, 종료 rule OFF, 같은 RUN_ID의 HEARTBEAT 유지
  • 복사 — Ctrl+C로 붙여넣은 문자열이 선택한 출력과 일치하고 Target이 계속 실행
  • 선택 해제 — Esc 뒤 terminalTextSelected=false와 종료 rule ON으로 복귀
  • 종료 — 2초 뒤 같은 RUN_ID 출력이 멈추고 Running Tasks에서 Target이 사라짐
  • 원복 — User rule과 두 연습 Task가 제거되고 Problems의 JSON 오류가 없음
완료 기준 선택 없음 → ON, 텍스트 선택 → OFF, 복사 → 유지, 선택 해제 → ON 전환을 실제 Context Key와 출력으로 확인하고 Target 부재 fallback을 취소한 뒤 User 설정과 Workspace Task를 원복했습니다.

5. 문제가 생겼다면

텍스트를 선택했는데 terminalTextSelected가 false입니다

먼저 확인 활성 Terminal 본문에 실제 선택 영역이 있는지, Inspect Context Keys에서 Terminal 본문 요소를 검사했는지 확인합니다.

복구 선택을 유지한 채 Terminal 본문을 다시 검사합니다. 계속 재현되면 버전, 확장 목록, Context 객체를 보존하고 원인을 UNKNOWN으로 둡니다.

재합류 Step 6

선택 중에도 종료 rule이 match됩니다

먼저 확인 when에 && !terminalTextSelected가 정확히 있고 Troubleshooting 로그의 실제 매칭 rule과 source가 무엇인지 확인합니다.

복구 같은 chord의 중복 User rule을 제거하거나 미사용 chord로 바꾸고 백업과 비교합니다.

재합류 Step 4

Ctrl+C가 복사 대신 프로세스에 전달됩니다

먼저 확인 선택 영역이 남아 있고 terminalTextSelected=true인지 확인합니다.

복구 Command Palette의 Terminal 복사 명령으로 비교하고 선택 문자열, Context Key, 로그를 보존합니다. Evidence가 없으면 원인을 단정하지 않습니다.

재합류 Step 7

Target이 없는데 Quick Pick이 열립니다

먼저 확인 Target이 Running Tasks에 없고 Guard만 실행 중인지 확인합니다.

복구 이는 String args 불일치 시의 fallback일 수 있습니다. 아무 항목도 선택하지 않고 Esc로 닫습니다.

재합류 Step 8

핵심 판단 원인을 확인하지 못하면 Context Key 객체, Keyboard Shortcuts Troubleshooting 원문, Task label과 RUN_ID를 보존하고 임의 변경 없이 중단합니다.

6. 핵심 정리와 공식 자료

  • terminalTextSelected는 활성 Terminal의 텍스트 선택 유무를 나타냅니다.
  • !terminalTextSelected를 추가하면 선택 중 종료 chord를 잠글 수 있습니다.
  • Windows Ctrl+C 복사와 Esc 선택 해제를 확인해 복사와 종료 흐름을 분리합니다.
  • gate는 Target 전용이 아니므로 Target 부재 Quick Pick은 Esc로 취소합니다.
  • 실습 후 User rule과 두 Task 객체를 제거해 원복합니다.

공식 자료

아래 자료는 2026-09-12 Asia/Seoul에 확인했습니다. 공식 Context Key 목록은 비완전 목록이며 일부 내부 Key는 향후 바뀔 수 있어 Stable commit 고정 소스로 정의와 기본값을 보완했습니다.

다음 편 예고 커맨드 팔레트 45부에서는 Terminal Find 상자가 열린 동안에도 종료 chord를 잠그도록 !terminalFindVisible 조건을 추가해 검색 입력과 종료 동작의 충돌을 줄입니다.
반응형
이 글이 유용했다면 링크를 공유해 보세요.