개발/Visual Studio Code

커맨드 팔레트 47부: VS Code Task 단축키를 물리 키 위치로 고정하기

VS CODE 초보자 시리즈 · 커맨드 팔레트 47부

커맨드 팔레트 47부: VS Code Task 단축키를 물리 키 위치로 고정하기

레이아웃이 바뀌어도 같은 물리 키 위치로 Target Task만 종료되도록 단축키를 고정합니다.

keybindings.json의 key만 ctrl+[KeyK] ctrl+alt+[KeyT]로 바꾸고 command·args·when은 유지합니다.

완료하면 현재 레이아웃에서 Target만 종료되고 Guard는 계속 실행되며, 실습 규칙과 레이아웃을 원상 복구합니다.

1. 시작하기 전에

예상 시간은 20~30분입니다. 독자는 Workspace Task 실행과 User keybindings.json 편집, Terminal 포커스·텍스트 선택·Find 상태를 이미 확인할 수 있어야 합니다.

준비할 것

  • 직접 만든 빈 연습 폴더 — 기존 tasks.json과 업무 파일이 없어야 합니다.
  • 현재 User 단축키 전체 백업 — 첫 쓰기 전에 원본과 비교합니다.
  • Windows 11 · VS Code Stable 1.137.0 · Windows PowerShell — 이 Run의 로컬 commit은 645f29cc3176500b4b5762ba887cf2a7f0ffdf2c입니다.
  • 선택 사항: 이미 설치된 두 번째 Windows 키보드 레이아웃 — 없으면 설치하지 않고 교차 레이아웃 결과를 UNCONFIRMED로 둡니다.
안전하게 시작하기 User 단축키는 모든 폴더와 동기화된 기기에 영향을 줄 수 있습니다. 출력·대기만 하는 두 연습 Task에서만 시험하고, 업무 서버·빌드·배포 Task가 열린 창에서는 진행하지 않습니다. 중단 조건: 백업 불일치, 기존 파일, 예상 밖 명령, 다른 Task 종료, 레이아웃 식별 실패.

2. 알아둘 핵심 개념

FACT — 문자 키와 물리 위치는 같은 개념이 아닙니다

일반 표기 k와 t는 현재 레이아웃이 해석한 virtual key를 따릅니다. [KeyK]와 [KeyT]는 키보드의 물리 위치를 나타내는 scan code 표기입니다. Microsoft 문서는 scan code 단축키가 레이아웃 변경에도 바뀌지 않는다고 설명합니다. 이 글은 텍스트 입력 동작이 아니라 단축키 선택에만 적용됩니다. [SRC-01] [SRC-04]

FACT — 대괄호와 대소문자도 문법입니다

key 속성은 String입니다. 이 실습의 두 stroke는 ctrl+[KeyK]와 ctrl+alt+[KeyT]이며 한 칸 공백으로 chord를 구분합니다. [KeyK]·[KeyT]는 공식 허용 범위 [KeyA]-[KeyZ]에 들어갑니다. 괄호를 빼거나 [K]처럼 줄이지 않습니다. [SRC-01] [SRC-02] [SRC-03]

FACT — command·args·when은 그대로 유지합니다

바꾸는 필드는 key 하나뿐입니다. command는 workbench.action.tasks.terminate, args는 정확한 실행 중 label인 JCOS Scan Lab Target, when은 45부까지 만든 다섯 조건을 유지합니다. 물리 위치 고정은 Target 선택이나 활성 조건을 넓히지 않습니다. [SRC-01] [SRC-05] [SRC-06]

RECOMMENDATION — 레이아웃 전환은 검증 단계에서만 합니다

Windows 입력 언어 전환은 다른 앱의 입력에도 영향을 줄 수 있습니다. 먼저 현재 레이아웃 이름을 기록하고, 두 번째 레이아웃이 이미 설치된 경우에만 전환 시험을 합니다. 새 언어 팩 설치는 이 글의 범위 밖입니다. [SRC-01] [SRC-04]

3. 순서대로 진행하기

각 단계의 정상 결과를 확인한 뒤 다음 단계로 이동합니다.

1. 빈 연습 폴더를 준비합니다

목적 기존 프로젝트의 Task 설정을 보호합니다.

주의·되돌리기 낯선 저장소를 신뢰하거나 기존 폴더를 비우지 않습니다. 되돌리기: 폴더를 닫습니다. 자동 삭제하지 않습니다.
  1. 직접 만든 빈 JCOS-VSC47-Scan-Lab 폴더를 File > Open Folder...로 엽니다.

입력 위치 VS Code 메뉴와 Explorer; Workspace Folder 범위

폴더 이름: JCOS-VSC47-Scan-Lab
정상 결과 Explorer 최상위에 연습 폴더만 보입니다.

확인 기존 .vscode/tasks.json과 업무 파일이 0개인지 확인합니다.

실패 신호 다른 프로젝트 파일이나 기존 Task 정의가 보입니다.

복구와 재합류 아무 파일도 쓰지 말고 폴더를 닫은 뒤 새 빈 폴더에서 STEP-01로 재합류합니다.

근거 [SRC-05]

2. 현재 환경과 레이아웃을 기록합니다

목적 시험 전 기준 상태를 남깁니다.

주의·되돌리기 언어 팩·키보드 레이아웃을 새로 설치하지 않습니다. 되돌리기: 변경이 없으므로 Rollback이 없습니다.
  1. 별도 PowerShell에서 code --version을 실행하고 Windows 작업 표시줄의 현재 입력 언어 표시를 메모합니다.

입력 위치 Shell: Windows PowerShell; 실행 위치: 임의

code --version
현재 입력 언어: <화면에 보이는 실제 이름>
정상 결과 VS Code 버전·commit과 레이아웃 이름을 기록했습니다.

확인 이 Run 기준 1.137.0과 로컬 commit을 대조합니다. Placeholder는 실제 화면 이름으로 치환합니다.

실패 신호 code를 찾지 못하거나 현재 레이아웃을 식별할 수 없습니다.

복구와 재합류 Help > About으로 버전을 확인합니다. 레이아웃 이름이 불명확하면 교차 레이아웃 시험을 생략하고 STEP-03으로 이동합니다.

근거 [SRC-07] [SRC-08]

3. User 단축키를 백업합니다

목적 전역 설정 변경을 되돌릴 기준을 만듭니다.

주의·되돌리기 User 범위는 다른 폴더에도 적용되고 Settings Sync로 전파될 수 있습니다. 되돌리기: 실습 규칙만 제거하는 것이 기본입니다. 다른 변경이 없을 때만 전체 백업으로 복원합니다.
  1. Preferences: Open Keyboard Shortcuts (JSON)을 열고 전체 내용을 연습 폴더의 keybindings-before.jsonc로 복사합니다.

입력 위치 Command Palette와 현재 Profile의 User keybindings.json

keybindings-before.jsonc
정상 결과 백업과 원본의 첫 줄·마지막 줄·객체 수가 같습니다.

확인 원본과 백업을 나란히 비교합니다.

실패 신호 백업이 비었거나 기존 항목이 누락됐습니다.

복구와 재합류 User 파일을 수정하지 말고 백업을 다시 만든 뒤 STEP-03으로 재합류합니다.

근거 [SRC-01]

4. 두 연습 Task를 저장합니다

목적 종료 Target과 보존 Guard를 구별합니다.

주의·되돌리기 Human Gate: 두 command 전체를 읽기 전에는 Task를 실행하지 않습니다. 되돌리기: 이미 실행했다면 정확한 연습 label만 Tasks: Terminate Task로 종료합니다.
  1. .vscode/tasks.json 전체를 아래 JSON으로 저장합니다.

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

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "JCOS Scan Lab Target",
      "type": "process",
      "command": "powershell.exe",
      "args": [
        "-NoLogo",
        "-NoProfile",
        "-Command",
        "$id=[guid]::NewGuid().ToString('N').Substring(0,8); Write-Output ('SCAN_TARGET RUN_ID='+$id); 0..120 | ForEach-Object { Write-Output ('SCAN_TARGET HEARTBEAT='+$_); Start-Sleep -Seconds 1 }"
      ],
      "problemMatcher": [],
      "presentation": {
        "reveal": "always",
        "panel": "dedicated",
        "clear": true
      }
    },
    {
      "label": "JCOS Scan Lab Guard",
      "type": "process",
      "command": "powershell.exe",
      "args": [
        "-NoLogo",
        "-NoProfile",
        "-Command",
        "$id=[guid]::NewGuid().ToString('N').Substring(0,8); Write-Output ('SCAN_GUARD RUN_ID='+$id); 0..120 | ForEach-Object { Write-Output ('SCAN_GUARD HEARTBEAT='+$_); Start-Sleep -Seconds 1 }"
      ],
      "problemMatcher": [],
      "presentation": {
        "reveal": "always",
        "panel": "dedicated",
        "clear": true
      }
    }
  ]
}
정상 결과 Target과 Guard 두 label이 JSON 오류 없이 저장됩니다.

확인 command가 powershell.exe이고 출력·대기 외 삭제·다운로드·외부 전송이 없는지 읽습니다.

실패 신호 빨간 JSON 오류, 기존 파일 덮어쓰기, 예제 밖 명령이 보입니다.

복구와 재합류 실행하지 말고 오류 원문을 보존합니다. 새 폴더·쉼표·따옴표를 고친 뒤 STEP-04로 재합류합니다.

근거 [SRC-05]

5. 논리 키 규칙을 기준으로 확인합니다

목적 바꾸기 전 key 필드를 분리해서 봅니다.

주의·되돌리기 이 단계는 설명용이며 저장하지 않습니다. 되돌리기: 변경이 없으므로 Rollback이 없습니다.
  1. 아래 logical_rule을 읽고 key 외 command·args·when 값을 기록합니다. 아직 User 파일에 추가하지 않습니다.

입력 위치 읽기 전용 메모

{
  "key": "ctrl+k ctrl+alt+t",
  "command": "workbench.action.tasks.terminate",
  "args": "JCOS Scan Lab Target",
  "when": "taskRunning && terminalFocus && taskTerminalActive && !terminalTextSelected && !terminalFindVisible"
}
정상 결과 기준 key는 ctrl+k ctrl+alt+t이며 네 필드가 분리됩니다.

확인 다음 단계 규칙과 비교할 기준을 한 줄씩 기록합니다.

실패 신호 args label이나 when이 앞선 편과 다릅니다.

복구와 재합류 예제 원문으로 되돌리고 STEP-05에서 다시 비교합니다.

근거 [SRC-01] [SRC-06]

6. scan-code 규칙으로 key만 바꿉니다

목적 같은 명령을 물리 위치 기반 chord에 연결합니다.

주의·되돌리기 전역 User 설정입니다. 백업·동기화 영향·미사용 chord 확인이 Human Gate입니다. 되돌리기: 실습 끝에 이 객체 하나만 제거합니다.
  1. User keybindings.json 배열 끝에 아래 객체 하나를 추가합니다. 기존 항목이 있으면 바깥 대괄호를 복사하지 않습니다.

입력 위치 현재 Profile의 User keybindings.json

{
  "key": "ctrl+[KeyK] ctrl+alt+[KeyT]",
  "command": "workbench.action.tasks.terminate",
  "args": "JCOS Scan Lab Target",
  "when": "taskRunning && terminalFocus && taskTerminalActive && !terminalTextSelected && !terminalFindVisible"
}
정상 결과 [KeyK]와 [KeyT]가 대괄호를 포함해 저장되고 JSON 오류가 없습니다.

확인 STEP-05와 비교해 key만 다르고 command·args·when은 동일한지 확인합니다.

실패 신호 [K], KeyK, 따옴표 누락, 중첩 배열 또는 기존 객체 삭제가 보입니다.

복구와 재합류 추가한 객체만 취소하고 백업과 기존 항목을 대조한 뒤 STEP-06으로 재합류합니다.

근거 [SRC-01] [SRC-02] [SRC-03]

7. 같은 chord 충돌을 확인합니다

목적 기존 명령을 덮지 않게 합니다.

주의·되돌리기 조직 또는 확장 규칙을 임의 삭제하지 않습니다. 되돌리기: 실습 객체 제거로 원상 복귀합니다.
  1. Keyboard Shortcuts에서 Record Keys를 켜고 실제 물리 K 자리와 T 자리로 chord를 입력한 뒤 Show Same Keybindings를 확인합니다.

입력 위치 Preferences: Open Keyboard Shortcuts

검색 대상: ctrl+[KeyK] ctrl+alt+[KeyT]
정상 결과 실습 규칙 외 보호할 동일 chord가 없습니다.

확인 Keybinding·When·Source 열을 모두 봅니다.

실패 신호 기본·확장·업무 User 규칙이 같은 chord에서 활성화됩니다.

복구와 재합류 기존 규칙을 삭제하지 말고 미사용 물리 chord를 선택해 두 scan code와 문서의 실제 입력을 함께 바꾼 뒤 STEP-07로 재합류합니다.

근거 [SRC-01]

8. Guard와 Target을 차례로 실행합니다

목적 선택 종료 전 비교 대상을 만듭니다.

주의·되돌리기 실무 Task가 있는 창에서는 시험하지 않습니다. 종료 직전 Target과 Guard label을 다시 확인합니다. 되돌리기: Tasks: Terminate Task에서 각 연습 label을 선택합니다.
  1. Tasks: Run Task로 Guard를 먼저, Target을 다음에 한 번씩 실행합니다.

입력 위치 Command Palette와 각 전용 Task Terminal

SCAN_GUARD RUN_ID=<실제 값>
SCAN_TARGET RUN_ID=<실제 값>
정상 결과 두 Terminal에서 서로 다른 RUN_ID와 증가하는 HEARTBEAT가 보입니다.

확인 두 label·RUN_ID·현재 heartbeat를 메모합니다.

실패 신호 하나만 실행되거나 marker가 다르거나 예상 밖 명령이 실행됩니다.

복구와 재합류 정확한 연습 Task만 종료하고 STEP-04 정의를 재검토한 뒤 STEP-08로 재합류합니다.

근거 [SRC-05]

9. 현재 레이아웃에서 물리 chord를 누릅니다

목적 scan-code 규칙이 Target에 연결되는지 확인합니다.

주의·되돌리기 Target 외 Task가 종료되면 즉시 시험을 중단합니다. 되돌리기: Guard는 다음 단계 검증이 끝난 뒤 수동 종료합니다.
  1. Terminal Find를 닫고 선택 텍스트를 해제한 Target Terminal에 포커스를 둔 뒤 물리 K 자리와 T 자리로 chord를 누릅니다.

입력 위치 Target Task Terminal

입력: Ctrl+[KeyK], 이어서 Ctrl+Alt+[KeyT]
정상 결과 Target heartbeat가 멈추고 Guard heartbeat는 계속 증가합니다.

확인 Tasks: Show Running Tasks와 두 Terminal 출력으로 Target 없음·Guard 실행 중을 교차 확인합니다.

실패 신호 Quick Pick이 뜨거나 Guard가 끝나거나 아무 반응이 없습니다.

복구와 재합류 오류 원문과 두 출력 상태를 보존합니다. 잘못된 label·when·chord를 확인한 뒤 필요하면 STEP-06 또는 STEP-08로 재합류합니다.

근거 [SRC-01] [SRC-05] [SRC-06]

10. 다른 기존 레이아웃에서 같은 자리를 시험합니다

목적 표시 문자가 달라도 물리 위치가 유지되는지 관찰합니다.

주의·되돌리기 시스템 레이아웃 설치·삭제는 범위 밖입니다. IME 조합 중에는 chord를 시험하지 않습니다. 되돌리기: 원래 입력 언어로 되돌립니다.
  1. 두 번째 Windows 키보드 레이아웃이 이미 설치된 경우에만 입력 언어를 전환하고 Target을 다시 실행한 뒤 같은 물리 K·T 자리를 누릅니다.

입력 위치 Windows 입력 언어 전환과 VS Code Target Terminal

레이아웃 B: <이미 설치된 실제 이름>
같은 물리 위치: [KeyK] → [KeyT]
정상 결과 레이아웃 B에서도 Target만 종료되고 Guard는 계속 실행됩니다.

확인 전환 전후 레이아웃 이름, Target RUN_ID와 Guard heartbeat 증가를 기록합니다.

실패 신호 레이아웃을 전환할 수 없거나 입력 위치를 확신할 수 없습니다.

복구와 재합류 UNCONFIRMED로 기록하고 억지로 설치하지 않습니다. 기본 완료 조건은 현재 레이아웃 시험과 JSON 비교로 유지하며 STEP-11로 이동합니다.

근거 [SRC-01] [SRC-04]

11. Guard를 종료하고 규칙을 제거합니다

목적 실습 프로세스와 User 변경을 정리합니다.

주의·되돌리기 전체 파일 덮어쓰기는 다른 변경을 잃을 수 있으므로 마지막 수단입니다. 되돌리기: 정확한 실습 객체 제거와 Guard 종료가 기본 Rollback입니다.
  1. Tasks: Terminate Task에서 JCOS Scan Lab Guard만 종료한 뒤 User keybindings.json에서 실습 객체 하나만 삭제합니다.

입력 위치 Command Palette와 User keybindings.json

삭제 대상 command: workbench.action.tasks.terminate
args: JCOS Scan Lab Target
key: ctrl+[KeyK] ctrl+alt+[KeyT]
정상 결과 실행 중인 Scan Lab Task가 없고 실습 객체가 사라집니다.

확인 Tasks: Show Running Tasks와 keybindings-before.jsonc를 대조합니다.

실패 신호 다른 User 규칙이 함께 삭제됐거나 Guard가 계속 출력합니다.

복구와 재합류 편집을 중단하고 Undo로 실습 객체 삭제 직전으로 돌아갑니다. 다른 변경이 없을 때만 백업 전체를 복원하고 STEP-11을 재검증합니다.

근거 [SRC-01] [SRC-05]

12. 원래 레이아웃과 완료 조건을 재확인합니다

목적 환경과 설정이 실습 전 상태로 돌아왔는지 확인합니다.

주의·되돌리기 확인되지 않은 상태에서 업무 Task를 실행하지 않습니다. 되돌리기: 백업·기록에 따라 실습 범위만 복원합니다.
  1. Windows 입력 언어를 STEP-02의 이름으로 되돌리고, User 파일과 실행 중 Task를 다시 확인합니다.

입력 위치 Windows 작업 표시줄, Keyboard Shortcuts, Tasks: Show Running Tasks

현재 레이아웃=<STEP-02 실제 이름>
Scan Lab Task=0
실습 User 규칙=0
정상 결과 Target만 선택 종료됐던 기록, Guard 지속 기록, 최종 0개 상태가 모두 있습니다.

확인 레이아웃 이름, keybindings-before.jsonc, Tasks: Show Running Tasks를 서로 대조합니다.

실패 신호 레이아웃 이름·User 규칙·실행 Task 중 하나가 실습 전과 다릅니다.

복구와 재합류 원인을 UNKNOWN으로 두고 현재 상태와 오류 원문을 보존합니다. 새 변경을 하지 말고 해당 차이를 복원한 뒤 STEP-12로 재합류합니다.

근거 [SRC-01] [SRC-04] [SRC-05]

4. 완료 확인하기

  • FILE — User 규칙의 key가 정확히 ctrl+[KeyK] ctrl+alt+[KeyT]이고 command·args·when이 기준 규칙과 같습니다.
  • BEHAVIOR — 현재 레이아웃에서 같은 물리 K·T 자리로 Target만 종료됩니다.
  • REGRESSION — Guard의 RUN_ID는 유지되고 heartbeat가 계속 증가합니다.
  • VARIANT — 두 번째 레이아웃이 이미 있으면 같은 물리 위치에서 반복 확인합니다. 없으면 UNCONFIRMED를 유지합니다.
  • ROLLBACK — Scan Lab Task 0개, 실습 User 규칙 0개, 원래 입력 언어로 복귀했습니다.
완료 기준 key 한 필드만 scan-code chord로 바뀌었고, Target 선택 종료·Guard 보존·최종 Rollback을 서로 독립된 화면에서 확인했습니다.

5. 문제가 생겼다면

대괄호 표기에 빨간 오류가 납니다

먼저 확인 [KeyK]·[KeyT]의 대소문자, 대괄호, 두 stroke 사이 공백을 원문과 비교합니다.

복구 key를 ctrl+[KeyK] ctrl+alt+[KeyT]로 되돌립니다.

재합류 STEP-06

아무 반응이 없거나 Quick Pick이 열립니다

먼저 확인 오류 원문을 보존하고 Target label, 실행 상태, Terminal 포커스, 선택·Find 상태를 확인합니다. 원인은 확인 전 UNKNOWN입니다.

복구 하나씩 정상화하고 같은 물리 위치로 다시 시험합니다.

재합류 STEP-08 또는 STEP-09

다른 Task가 종료됐습니다

먼저 확인 두 Terminal의 label·RUN_ID와 User rule args 원문을 보존합니다.

복구 실습을 중단하고 User 규칙을 제거합니다. args가 Target label과 정확히 같은지 확인 전 재실행하지 않습니다.

재합류 STEP-06

레이아웃 B에서 같은 위치인지 확신할 수 없습니다

먼저 확인 작업 표시줄의 레이아웃 이름과 실제 물리 키 위치를 기록합니다.

복구 결과를 UNCONFIRMED로 두고 새 레이아웃을 설치하지 않습니다.

재합류 STEP-11

핵심 판단 원인을 확인하지 못하면 현재 keybindings.json, Task 출력, 레이아웃 이름과 오류 원문을 보존하고 임의 변경 없이 중단합니다.

6. 핵심 정리와 공식 자료

  • 일반 문자 표기와 [KeyK] 같은 scan code 표기는 단축키가 따라가는 기준이 다릅니다.
  • 이 실습에서는 key만 바꾸고 Target 선택 args와 다섯 when 조건은 유지합니다.
  • 두 번째 레이아웃이 없으면 설치하지 않고 Variant를 UNCONFIRMED로 남기는 것이 올바른 완료입니다.
  • 마지막에는 Guard 종료, User 규칙 제거, 원래 입력 언어 복귀를 모두 확인합니다.

공식 자료

아래 자료는 2026-09-15 KST에 접근했습니다. Stable 1.137.0과 Windows 11 범위이며, 키보드 하드웨어·IME·조직 정책·확장 규칙 차이는 독자 환경에서 확인해야 합니다.

다음 편 예고 커맨드 팔레트 48부 — 현재 키보드 레이아웃의 키 매핑을 원문으로 확인하기: Developer: Inspect Key Mappings 결과에서 scan code·virtual key·현재 레이아웃 매핑을 읽고 원문 Evidence로 남깁니다.
이 글이 유용했다면 링크를 공유해 보세요.