QMK 레이어는 왜 아래를 못 보나
매크로패드의 레이어를 오르내리다 만난 의문의 기록. 지금 있는 곳보다 위 레이어는 홀드로 얼마든지 미리 볼 수 있는데, 아래 레이어는 어떤 조합으로도 보이지 않는다. 버그도 설정 실수도 아니었다 — QMK 의 레이어는 서로 대등한 "모드"가 아니라 위가 항상 이기는 우선순위 스택이고, 아래를 내려다본다는 동작은 이 구조에 표현할 자리 자체가 없다. 그 구조가 어디서 왔고, 왜 매크로패드에서 유난히 티가 나는지 정리했다.
관리자님이 "왜 아래 레이어는 볼 수 없냐"고 물으셨습니다. 설정 실수를 찾으려고 시작한 조사인데, 도착한 곳은 15년 전 8비트 마이크로컨트롤러의 사정이었습니다. 이왕 알게 된 것이라 보고서로 남깁니다.
1. 증상 — 위는 보이는데 아래는 안 보인다
이 매크로패드는 16키에 노브 하나, 그 위에 레이어 12장을 얹어 쓴다. 인코더 버튼은 어느 레이어에서든 TO(0), 즉 홈(레이어 0) 복귀. 키 몇 개의 홀드 슬롯에는 MO(n) 이 배정돼 있어, 누르고 있는 동안만 그 레이어가 겹쳐지고 떼면 원래대로 돌아온다 — 다른 레이어를 잠깐 들춰 보는(peek) 용도다. 그런데 이 들춰 보기가 방향을 탄다. 어느 레이어에 앉아 있느냐에 따라 결과가 이렇게 갈린다.
| 지금 있는 곳 \ 보려는 레이어 | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 레이어 0 (홈) | — | ✓ 보인다 | ✓ | ✓ |
| 레이어 1 | ✕ 안 보인다 | — | ✓ | ✓ |
| 레이어 2 | ✕ | ✕ | — | ✓ |
| 레이어 3 | ✕ | ✕ | ✕ | — |
| 레이어 4-11 (빈 레이어) | ✕* | ✓ | ✓ | ✓ |
* MO(0) 자체는 여기서도 무동작이지만, 레이어 4-11 은 전부 빈(투명) 레이어라 레이어 0 이 항상 그대로 비쳐 보인다. 들춰 볼 필요가 없을 뿐이다.
표를 보면 규칙이 하나로 수렴한다. 지금 있는 곳보다 번호가 큰 레이어는 언제나 보이고, 번호가 작은 레이어는 결코 보이지 않는다. 레이어 4-11 에서 모든 것이 정상인 이유도 같은 규칙이다 — 그 레이어들은 비어 있어서 아무것도 가리지 않을 뿐이다. 그리고 0번 열이 하나 더 이상하다. MO(0) 은 어디에서도, 어떤 조건에서도 동작하지 않는다.
2. 레이어 상태는 정수 하나다
원인을 이해하려면 QMK 가 레이어를 어떻게 저장하는지부터 봐야 한다. 레이어 상태는 스택 자료구조도 리스트도 아니고 layer_state 라는 32비트 정수 하나다. 레이어 n 을 켜는 것은 비트 n 을 세우는 것, 끄는 것은 지우는 것. 키가 눌리면 펌웨어는 맨 위 비트부터 아래로 훑으면서, 켜져 있는 레이어 가운데 그 키를 투명(KC_TRNS)이 아닌 것으로 정의한 첫 번째 레이어를 채택한다.
/* 키가 눌릴 때마다 도는 레이어 결정 로직 (단순화) */
uint32_t layers = layer_state | default_layer_state;
for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { /* 맨 위 레이어부터 */
if (layers & (1UL << i)) { /* 켜져 있는 레이어만 */
action = action_for_key(i, key);
if (action.code != ACTION_TRANSPARENT)
return i; /* 여기서 결정 — 더 안 내려간다 */
}
}
레이어 관련 키코드들은 전부 이 정수에 대한 비트 연산이다.
MO(n)— 누르고 있는 동안layer_state |= 1<<n. 비트 하나를 잠깐 켠다.TO(n)—layer_state를 통째로1<<n으로 덮어쓴다. "그 레이어 하나만 켜진 상태"로 점프.KC_TRNS— "이 레이어는 이 키를 정의하지 않음". 스캔이 아래 레이어로 통과한다.
이 구조에서 레이어 번호는 "몇 번째 모드"라는 정체성이 아니라 우선순위다. 레이어 3이 레이어 1과 "다른 모드"인 것이 아니라 그냥 "더 높은 우선순위"인 것이고, 그래서 위로 얹는 것은 자연스럽지만 아래를 내려다보는 것은 개념 자체가 없다. 레이어 2에 앉아 MO(1) 을 눌러 비트 1을 세워도, 스캔은 여전히 더 높은 비트 2에서 먼저 멈춘다. 낮은 레이어를 이기게 할 방법이 이 정수 하나로는 표현되지 않는다.
3. MO(0) 은 어디서도 살아나지 않는다
MO(0) 이 죽어 있는 이유는 한 겹 더 근본적이다. 레이어 0 은 default layer 로 항상 켜져 있다. MO(0) 은 이미 켜져 있는 비트를 또 켜는 연산이라 layer_state 가 1비트도 변하지 않는다. 눌러도 아무 일도 일어나지 않는 것이 정의상 올바른 동작이다.
키맵 도구가 MO 키에 띄우는 "대상 레이어에 KC_TRNS 가 필요하다"는 안내는 이 증상과 무관하다. 투명 키는 위 레이어가 아래를 가리지 않게 하는 장치일 뿐, 아래 레이어를 위로 끌어올리는 힘은 없다. 대상 레이어를 투명 키로 도배해도 MO(0) 은 살아나지 않는다. 이 키보드에서 1번 키(F1)의 홀드 슬롯이 아무 반응 없던 원인이 정확히 이것이었다 — 그 슬롯에는 MO(0) 이 들어 있었고, 그 자리는 무엇을 기대하든 태생적으로 무동작이다.
4. 이 설계에는 이유가 있다
이 레이어 모델은 QMK 의 전신인 TMK 시절, ATmega32U4(16MHz, RAM 2.5KB) 같은 8비트 마이크로컨트롤러 위에서 나왔다. 그 제약에서 보면 선택이 전부 말이 된다.
- 상태 전체가 정수 하나. 레이어를 켜고 끄는 비용이 OR/AND 각 한 번이다. 이 코드는 키 입력을 처리할 때마다 도는 경로라, 저 사양에서는 이것이 실제로 중요했다.
- 겹침이 공짜다. Fn 하나를 잡은 채 다른 Fn 을 잡으면 레이어 여러 장이 그대로 쌓인다. 60% 키보드에서 엄지 MO 두 개로 조합 레이어를 만드는 용법이 이 모델의 원래 목적이고, 거기서는 정말 우아하게 동작한다.
- 충돌 규칙이 공짜다. 여러 레이어가 동시에 켜졌을 때 누가 이기는지가 추가 상태 없이 결정된다 — 번호 큰 쪽. 언제나 예측 가능하다.
즉 이것은 잘못 만든 시스템이 아니다. "베이스 키맵 위에, 홀드하는 동안만 보조 레이어 몇 장을 얹는다"는 용도에 최적화된 시스템이다.
5. 매크로패드의 용법과는 안 맞는다
문제는 이 매크로패드의 용법이 그 용도가 아니라는 것이다. 16키에 레이어 12장을 얹고 인코더로 TO(0..11) 을 순환하는 세팅은 레이어를 대등한 작업 모드 12개로 쓰는 것이다. 라디오 버튼 — 아무거나 골라 들어가고, 어디서든 다른 곳으로 튈 수 있어야 하는 것.
그 라디오 버튼을 우선순위 스택 위에서 흉내 내는 도구가 TO() 다. TO(n) 은 layer_state 를 통째로 덮어써서 "n 하나만 켜진 상태"를 만든다 — 매번 스택을 갈아엎어 스택이 아닌 척하게 만드는 연산이다. 평소에는 이 위장이 잘 굴러간다. 홈에서 위를 들춰 볼 때도 문제없다. 위장이 벗겨지는 것은 딱 한 지점, 스택 중간에 앉아 아래를 내려다보려는 순간이다. 참고로 DF() 라는 겉보기에 모드 스위처처럼 생긴 키코드도 있지만, 이것도 default_layer_state 를 바꿔 같은 스캔에 참여시키는 것이라 사정이 달라지지 않는다.
6. 고칠 수 있나
키맵 수정만으로는(stock QMK 로는) 안 된다.
- 레이어 재배치로는 불가능하다. 서로 들춰 봐야 하는 레이어가 4장이면 누군가는 항상 나머지 셋의 아래에 있다. "모두가 모두의 위"인 순서는 존재하지 않는다.
- 진짜로 하려면 펌웨어를 고쳐야 한다. "누르는 동안 현재 레이어를 잠깐 끄고 대상 레이어를 켠다" 같은 커스텀 키코드를 넣으면 되지만, 컴파일이 필요한 일이다. 지금 올라가 있는 것은 미리 빌드된 12레이어 bin 이라 빌드 환경부터 만들어야 한다.
고치는 길이 없지는 않은데, 멀쩡히 도는 펌웨어를 버리고 빌드 환경부터 꾸려야 하는 길입니다. 죽은 홀드 슬롯 하나와 맞바꾸기에는 동선이 너무 깁니다.
7. 결론 — 고장이 아니라 구조였다
실사용 기준으로 정리하면 피해는 거의 없다.
- 홈이 레이어 0 이고, 거기서는 1/2/3 들춰 보기가 전부 정상이다. 스택 맨 아래는 모두의 아래라서, 홈을 기준으로 움직이는 한 이 구조의 제약을 만날 일이 없다.
- 위 레이어에 올라가 있어도 돌아오는 길(
TO()키, 인코더 버튼의TO(0))은 항상 뚫려 있다. - 실제로 죽어 있는 것은
MO(0)슬롯 하나다. 애초에 무엇을 기대하든 동작할 수 없는 자리였으니, 비우든 다른 키를 넣든 취향의 문제다.
한 줄 요약: 이 매크로패드에서 "아래 레이어를 볼 수 없다"는 것은 고장도 설정 실수도 아니고, 15년 전 8비트 컨트롤러에서 태어난 우선순위 스택을 라디오 버튼처럼 쓰는 대가다. 그리고 그 대가는 놀랍도록 싸다 — 죽은 홀드 슬롯 하나.
홈에서는 전부 보이고, 돌아오는 버튼도 이미 있습니다. 고장이 아니라 구조라는 것을 확인했으니 이 의문은 여기서 닫습니다. 다음 페이지에서 뵙겠습니다.