QMK Tap Dance·Combo 실전 활용 예제
키 하나로 여러 동작을, 두 키 조합으로 새로운 기능을 만드는 법
- QMK Tap Dance는 한 키를 탭 횟수·홀드 여부에 따라 다른 기능으로 동작시키는 기능입니다.
- QMK Combo는 여러 키를 동시에 눌러 새로운 동작을 실행하는 기능입니다.
- 둘 다 rules.mk에서 활성화하고, keymap.c에 코드를 추가해야 동작합니다.
- TAPPING_TERM·COMBO_TERM 값에 따라 오작동 여부가 크게 달라집니다.
- 실전 코드 예제와 함께, 자주 겪는 실수와 해결법까지 정리했습니다.
키보드 레이아웃을 줄이고 싶은데, 자주 쓰는 기능은 그대로 남겨두고 싶었던 적이 있을 겁니다. 40% 키보드나 분할 키보드를 쓰다 보면 키 개수가 부족해서 레이어를 여러 겹 쌓게 되는데, 레이어가 늘어날수록 오히려 손가락이 헷갈립니다. QMK의 Tap Dance와 Combo는 이 문제를 물리 키 개수를 늘리지 않고 해결하는 대표적인 방법입니다.
Tap Dance는 키 하나에 여러 동작을 숨기는 방식이고, Combo는 여러 키를 동시에 눌러 새 동작을 만드는 방식입니다. 이 글에서는 두 기능을 실제로 어떻게 설정하고, 어떤 상황에 어떤 코드를 써야 하는지 구체적인 예제로 보여드립니다. rules.mk 설정부터 keymap.c 코드, 자주 하는 실수까지 순서대로 따라오시면 됩니다.
1. QMK Tap Dance란 무엇이고 언제 쓰는가
Tap Dance는 세미콜론 키를 예로 들면 이해가 빠릅니다. 한 번 탭하면 세미콜론이, 빠르게 두 번 탭하면 콜론이 입력되는 식입니다. QMK 공식 문서에 따르면 이 기능은 algernon이라는 개발자가 만들어 QMK 풀리퀘스트로 병합한 커뮤니티 기여 기능입니다.
탭 횟수뿐 아니라 홀드 여부도 구분할 수 있습니다. 키를 한 번 눌렀다가 계속 누르고 있으면 “홀드”로 인식하고, 짧게 눌렀다 떼면 “탭”으로 인식합니다. 이 두 가지 축(탭 횟수 × 홀드 여부)을 조합하면 키 하나로 4개, 많게는 그 이상의 동작을 만들 수 있습니다.
Tap Dance는 모든 키에 어울리는 기능은 아닙니다. 공식 문서도 알파벳처럼 자주 타이핑하는 키보다는 Z, Q, X, J, K, V, B 같은 키나 기능키, Home/End, 콤마, 세미콜론처럼 상대적으로 덜 쓰이는 키에 적용하길 권장합니다. “p”에 Tap Dance를 걸면 “pepper” 같은 단어를 칠 때마다 오작동할 수 있기 때문입니다.
실무에서 Tap Dance가 특히 유용한 상황은 세 가지입니다. 자주 쓰는 기능인데 전용 키를 두기엔 아까운 경우, Esc와 Caps Lock처럼 서로 관련 있는 두 기능을 한 키에 묶고 싶은 경우, 레이어 전환을 탭/더블탭/홀드로 세분화하고 싶은 경우입니다.
2. Tap Dance 실전 설정 방법
Tap Dance는 기본적으로 꺼져 있는 기능입니다. 키보드 폴더 안 rules.mk 파일에 아래 한 줄을 추가해야 합니다.
TAPPING_TERM은 탭과 탭 사이를 얼마나 빠르게 눌러야 “연속 탭”으로 인식할지 정하는 값입니다. 밀리초(ms) 단위이며, 공식 문서 예제에서는 175ms로 설정한 경우, 175ms 안에 두 번 탭해야 더블탭으로 인식하고 그보다 늦으면 각 탭이 따로따로 입력됩니다. 손가락이 느린 편이라면 200~250ms로 늘리는 게 안전합니다.
동시에 활성화할 수 있는 Tap Dance 키 개수도 제한이 있습니다. 기본값은 3개이며, 그 이상 동시에 누르는 상황이 예상되면 TAP_DANCE_MAX_SIMULTANEOUS 값을 늘려야 합니다. 일반적인 사용자는 기본값 3개로 충분합니다.
설정이 끝나면 keymap.c에 실제 동작을 정의합니다. 가장 간단한 형태는 ACTION_TAP_DANCE_DOUBLE로, 한 번 탭할 때와 두 번 탭할 때 각각 다른 키코드를 보냅니다.
ACTION_TAP_DANCE_DOUBLE에는 기본 키코드만 넣을 수 있습니다. 커스텀 키코드나 매크로를 쓰고 싶다면 처음부터 ACTION_TAP_DANCE_FN_ADVANCED로 넘어가는 게 나중에 다시 뜯어고치는 수고를 덜어줍니다.
3. Tap Dance 실전 코드 예제 3가지
예제 1. Esc / Caps Lock 전환 — 자주 안 쓰는 Caps Lock을 Esc와 한 키에 묶는 가장 기본적인 형태입니다.
enum으로 TD_ESC_CAPS를 선언하고, tap_dance_actions 배열에 ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS)을 넣은 뒤, 키맵의 해당 위치에 TD(TD_ESC_CAPS)를 넣으면 끝입니다. QMK 공식 예제로도 소개될 만큼 가장 무난한 활용법입니다.
예제 2. 세미콜론 탭 / 콜론 홀드 — 탭과 홀드를 구분해서 쓰고 싶을 때는 별도의 finished·reset 함수 쌍이 필요합니다. 홀드 상태에서는 콜론을, 탭 상태에서는 세미콜론을 register_code16으로 직접 등록하고, 키를 뗄 때 reset 함수에서 unregister_code16으로 해제하는 구조입니다. 이렇게 하면 홀드 중에는 다른 키와 조합해 Shift+세미콜론 같은 동작도 자연스럽게 이어집니다.
탭-홀드형 Tap Dance는 홀드 판정 기준에 permissive hold가 반영되지 않습니다. 공식 문서에서도 Tap Dance로는 “permissive hold” 동작을 흉내 낼 수 없다고 명시하고 있으니, 빠른 타건 중 홀드가 씹히는 느낌이 든다면 이 한계 때문일 수 있습니다.
예제 3. 레이어 이동 + 토글 병행 — 따옴표 키 하나로 1탭은 따옴표, 홀드는 특정 레이어로 이동(MO), 2탭은 그 레이어를 토글(TG)하는 방식입니다. cur_dance() 함수로 상태를 TD_SINGLE_TAP, TD_SINGLE_HOLD, TD_DOUBLE_TAP 세 가지로 분류하고, ql_finished()에서 각 상태에 맞는 동작을 실행합니다. 레이어 전용 키를 따로 두지 않아도 되니 40% 키보드에서 특히 효율적입니다.
세 예제 모두 tap_dance_actions 배열 안에서 인덱스만 다르게 관리하면 되므로, 하나의 키맵 파일 안에 여러 Tap Dance를 동시에 넣어도 문제없습니다. 다만 개수가 늘어날수록 TAP_DANCE_MAX_SIMULTANEOUS 값을 함께 점검해야 합니다.
4. QMK Combo란 무엇이고 Tap Dance와 뭐가 다른가
Tap Dance가 “한 키를 여러 번”이라면, Combo는 “여러 키를 동시에”입니다. A와 S를 같이 누르면 Esc가 입력되는 식으로, 물리적으로 존재하지 않는 새 키를 만들어내는 기능입니다. QMK 공식 문서는 이를 코드 방식(chording)의 커스텀 액션 추가 기능이라고 설명합니다.
둘의 차이는 손가락 움직임에 있습니다. Tap Dance는 같은 손가락으로 반복 입력해야 하니 타이핑 속도가 빠른 사람에게는 오히려 방해가 될 수 있습니다. 반대로 Combo는 서로 다른 손가락으로 동시에 누르는 방식이라, 이미 익숙한 두 키의 조합을 그대로 몸이 기억하게 만들 수 있습니다. 그래서 복사·붙여넣기처럼 손이 이미 익힌 조합에는 Combo가, Esc/Caps Lock처럼 단일 키의 역할 확장에는 Tap Dance가 더 잘 맞습니다.
Combo와 Tap Dance는 동시에 써도 충돌하지 않습니다. Mod-Tap이나 Tap Dance로 만든 키코드도 Combo 시퀀스 안에 그대로 넣을 수 있습니다. 다만 이 경우 짧은 키코드가 아니라 TD(TD_ESC_CAPS)처럼 전체 키코드를 Combo 정의에 그대로 넣어야 인식됩니다.
5. Combo 실전 설정 방법
Combo도 기본적으로 꺼져 있습니다. rules.mk에 COMBO_ENABLE = yes를 추가하는 것부터 시작합니다.
COMBO_COUNT는 몇 개의 Combo를 쓸 것인지 미리 알려주는 값입니다. Combo를 추가할 때마다 이 숫자를 같이 바꿔줘야 해서 번거로운데, config.h에 COMBO_COUNT를 아예 정의하지 않고 코드에서 COMBO_LEN 변수로 자동 계산하게 만드는 방법도 있습니다. Combo 개수가 자주 바뀌는 실험 단계에서는 이 방식이 관리하기 편합니다.
COMBO_TERM은 Combo를 인식하는 동시 입력 허용 시간입니다. 기본값은 TAPPING_TERM과 동일하게 200ms로 맞춰지며, 별도로 정의하면 그 값을 우선 적용합니다. 손가락이 빠르지 않은데 COMBO_TERM이 너무 짧으면 동시에 눌러도 순차 입력으로 인식되니, 오작동이 잦다면 250~350ms로 늘려보는 게 첫 번째 점검 포인트입니다.
keymap.c에는 키 배열을 COMBO_END로 끝맺고, key_combos 배열에 COMBO() 매크로로 결과 키코드를 연결합니다.
6. Combo 실전 코드 예제
예제 1. 복사·붙여넣기 Combo — Z+C를 누르면 복사, X+V를 누르면 붙여넣기가 실행되도록 만드는 예제입니다. 단순한 키코드 매핑이 아니라 실제 동작을 함수로 처리해야 하므로 COMBO_ACTION과 process_combo_event()를 함께 씁니다. combo_index로 어떤 조합인지 구분하고, pressed 값이 true일 때 tap_code16(LCTL(KC_C))처럼 실제 단축키를 보내는 방식입니다.
예제 2. 자주 쓰는 기호 Combo — J와 K처럼 오른손 검지·중지로 가까이 있는 키를 조합해 Tab이나 괄호를 배치하는 방식입니다. 별도 심볼 레이어로 넘어가지 않고도 자주 쓰는 기호를 바로 입력할 수 있어, 코딩할 때 레이어 전환 텀을 줄이는 데 효과적입니다.
예제 3. 긴급 리셋 Combo — 펌웨어를 다시 플래시해야 할 때 물리 리셋 버튼을 누르기 번거로운 분할 키보드라면, 잘 안 겹치는 세 키 조합(예: 왼쪽 상단 세 키)에 리셋 기능을 걸어두면 편리합니다. 다만 이런 조합은 실수로 눌릴 가능성이 낮은 자리를 골라야 안전합니다.
Combo가 너무 많아지면 EXTRA_LONG_COMBOS나 EXTRA_EXTRA_LONG_COMBOS를 config.h에 정의해서 한 Combo에 들어가는 키 개수 제한을 늘릴 수 있습니다. 기본 상태에서는 조합 가능한 키 개수에 제한이 있으니, 3키 이상 조합을 시도하다 컴파일 에러가 나면 이 옵션부터 확인해보세요.
7. 자주 하는 실수와 해결법
Tap Dance와 Combo를 처음 도입할 때 가장 자주 나오는 문제 세 가지를 정리했습니다.
Tap Dance 키는 홀드 상태에서도 동시에 최대 개수(기본 3개) 제한을 받습니다. 여러 Tap Dance 키를 겹쳐 누르는 게임패드형 키맵을 만들 계획이라면 TAP_DANCE_MAX_SIMULTANEOUS를 처음부터 넉넉히 잡아두는 게 좋습니다.
FAQ
네, 서로 충돌하지 않습니다. 다만 Combo 시퀀스에 Tap Dance 키코드를 넣을 때는 TD(TD_이름) 형태로 전체 키코드를 그대로 사용해야 합니다.
공식 예제 기준 175ms가 출발점입니다. 손가락이 느리다고 느껴지면 200~250ms로 늘리고, 오히려 늦게 반응한다고 느껴지면 조금씩 줄여가며 본인 타건 속도에 맞추는 게 정석입니다.
개수가 아주 많지 않다면 큰 문제는 없습니다. Tap Dance 기능 자체가 추가하는 용량도 1KB 미만으로 알려져 있어, 일반적인 사용 범위에서는 용량보다 오작동 여부를 더 신경 쓰는 게 맞습니다.
같은 물리 키가 여러 Combo에 겹쳐 있으면 우선순위 문제가 생길 수 있습니다. 겹치는 조합이 있다면 둘 중 하나를 다른 키로 옮기거나, COMBO_TERM을 조정해 인식 순서를 안정시켜야 합니다.
Vial은 GUI에서 Tap Dance 항목을 직접 편집할 수 있습니다. 다만 설정 가능한 개수는 키보드 마이크로컨트롤러의 EEPROM 용량에 따라 정해지며, 이 한도는 컴파일 시점에만 조정할 수 있습니다.
📚 함께 보면 좋은 글
Tap Dance·Combo로 레이어 부담을 줄였다면, 아래 글에서 다른 방식의 키 절약 팁도 함께 확인해보세요.
🔗 공식 자료
📖 출처
QMK Firmware 공식 문서 – Tap Dance (docs.qmk.fm/features/tap_dance)
QMK Firmware 공식 문서 – Combos (docs.qmk.fm/features/combo)
QMK Firmware GitHub 저장소 (github.com/qmk/qmk_firmware)
Thomas Baart, “QMK Basics: Tap dance” (thomasbaart.nl)
Vial 공식 매뉴얼 – Tap Dance (get.vial.today)
Tap Dance는 키 하나에 여러 동작을, Combo는 여러 키의 동시 입력에 새 동작을 담는 기능입니다. TAPPING_TERM과 COMBO_TERM 값을 본인 타건 속도에 맞추면 오작동 없이 레이어 없는 효율적인 키맵을 만들 수 있습니다.






