ch10. 조건 분기와 변수 -- Slack 상태, 헤드폰/모니터 분기
IfThenElse 조건문과 변수를 활용하여 하나의 매크로가 상황에 따라 다르게 동작하도록 만드는 방법을 배운다.
이런 불편함, 겪어보셨나요?
회사 맥북과 개인 맥북을 함께 쓰는 사람이 있다. 같은 단축키를 눌렀는데, 회사 맥북에서는 회사 헤드폰으로, 개인 맥북에서는 개인 스피커로 오디오가 전환되면 좋겠다. 매번 시스템 설정을 열어서 오디오 출력 장치를 바꾸는 건 번거롭다.
Slack 상태도 마찬가지다. 출근 시간에 맞춰서 Slack 상태를 "업무 중"으로 바꾸고 싶은데, 회사 맥북에서만 동작해야 한다. 개인 맥북에서는 다른 상태를 설정하거나, 아예 동작하지 않아야 한다.
Obsidian에 메모를 쓰다가 앱을 닫을 때, 자동으로 git commit이 실행되면 편리하다. 하지만 이것도 특정 컴퓨터에서만 동작해야 한다.
이런 상황의 공통점은 무엇인가. "조건에 따라 다르게 동작해야 한다"는 것이다. Keyboard Maestro의 IfThenElse 조건문과 변수가 이 문제를 해결한다.
변수의 개념
매크로에서 변수(Variable)란, 값을 저장해두는 이름표다.
computerName이라는 변수에 %MacName%을 저장하면, 이후 액션에서 이 값을 꺼내 쓸 수 있다.
KM에서 변수를 설정하는 가장 기본적인 액션은 SetVariableToText다.
변수명: computerName
값: %MacName%
%MacName%은 KM의 내장 토큰이다.
현재 Mac의 컴퓨터 이름을 반환한다.
회사 맥북이 "Work-MacBook"이고 개인 맥북이 "Personal-MacBook"이라면, 같은 매크로라도 어떤 컴퓨터에서 실행하느냐에 따라 computerName 변수의 값이 달라진다.
이렇게 저장한 변수는 IfThenElse 조건문에서 비교 대상이 된다.
IfThenElse 조건문의 구조
IfThenElse는 "만약 ~이면 A를 실행하고, 아니면 B를 실행한다"는 흐름 제어 액션이다. ch03에서 앱 종류에 따라 분기하는 것을 간단히 다뤘다. 이 챕터에서는 변수 값을 비교하는 심화 패턴을 살펴본다.
기본 구조는 다음과 같다.
If [조건]
Then: 조건이 참일 때 실행할 액션
Else: 조건이 거짓일 때 실행할 액션
조건으로 사용할 수 있는 것은 다양하다. 변수 값 비교, 현재 앱 확인, 클립보드 내용, 윈도우 제목 등이 있다. 이 챕터의 네 매크로는 모두 "변수 값 비교" 조건을 사용한다.
패턴을 정리하면 이렇다.
- 변수에 현재 환경 정보를 저장한다 (컴퓨터 이름, 날짜 등).
- IfThenElse로 변수 값을 비교한다.
- 조건에 따라 서로 다른 액션을 실행한다.
이 패턴을 "환경 분기 패턴"이라 부르겠다. 네 매크로 모두 이 패턴을 따른다.
매크로 분석: 00. Slack 상태 변경
무엇을 하는 매크로인가
설정된 시간에 자동으로 Slack 상태를 변경한다. 컴퓨터 이름에 따라 회사용 상태와 개인용 상태를 다르게 설정한다.
트리거
| 트리거 타입 | 값 | 설명 |
|---|---|---|
| Time | 설정된 시간 | 지정된 시간에 자동 실행 |
액션 흐름
그림 10-1. Slack 상태 변경 매크로 흐름도
- SetVariableToText --
computerName변수에%MacName%값을 저장한다. 현재 매크로가 실행되는 컴퓨터의 이름을 알아내는 단계다. - IfThenElse --
computerName값을 확인한다. 회사 맥북인지, 개인 맥북인지 판별한다. - Then (회사 맥북) -- AppleScript로 Raycast 딥 링크를 실행한다. 회사용 Slack 상태 프리셋을 적용한다.
- Else (개인 맥북) -- 마찬가지로 Raycast 딥 링크를 실행하되, 개인용 Slack 상태 프리셋을 적용한다.
핵심 기술 해설
Time 트리거
Time 트리거는 특정 시간에 매크로를 자동 실행한다. 출근 시간에 맞춰 09:00에 실행하도록 설정하면, 매일 아침 Slack 상태가 자동으로 바뀐다. ch12에서 시간 기반 트리거를 더 자세히 다룬다.
변수와 토큰의 차이
%MacName%은 KM 토큰이다.
토큰은 실행 시점에 자동으로 값이 결정되는 자리표시자(placeholder)다.
변수는 사용자가 이름을 정해서 값을 저장하는 공간이다.
이 매크로에서 %MacName% 토큰의 값을 computerName 변수에 저장하는 이유가 있다.
IfThenElse 조건에서 직접 토큰을 비교할 수도 있지만, 변수에 저장해두면 디버깅이 쉽다.
KM 에디터 하단의 변수 목록에서 현재 값을 바로 확인할 수 있기 때문이다.
Raycast 딥 링크와 AppleScript
이 매크로는 Slack API를 직접 호출하지 않는다. 대신 Raycast의 Slack Status 확장 기능을 딥 링크로 호출한다.
set raycastDeepLink to "raycast://extensions/petr/my-slack-status/setStatus?context=..."
-- open 명령을 사용하여 딥 링크 실행
do shell script "open " & quoted form of raycastDeepLink
do shell script "open ..."은 macOS의 open 명령어를 AppleScript에서 실행하는 방식이다.
URL 스킴을 열면 해당 앱이 응답한다.
KM에서 AppleScript를 실행하고, AppleScript에서 셸 명령어를 실행하고, 셸 명령어가 Raycast를 호출하는 3단계 구조다.
활용 팁
- 퇴근 시간에도 Time 트리거를 추가하면, 퇴근 시 자동으로 "자리 비움" 상태로 전환할 수 있다.
- Raycast 외에 Slack Webhook URL을 직접 호출하는 방식도 가능하다. 셸 스크립트에서
curl로 Slack API를 호출하면 된다. %MacName%대신%IPAddress%를 쓰면 네트워크 위치(회사 Wi-Fi, 집 Wi-Fi)에 따라 분기할 수도 있다.
매크로 분석: A. 헤드폰
무엇을 하는 매크로인가
단축키를 누르면 오디오 출력 장치를 헤드폰으로 전환한다. 컴퓨터 이름에 따라 서로 다른 헤드폰 장치를 선택한다.
트리거
| 트리거 타입 | 값 | 설명 |
|---|---|---|
| HotKey | Key105 | 키보드의 특수 키(한/영 키 등)를 단축키로 사용 |
액션 흐름
그림 10-2. 헤드폰/모니터 전환 매크로 흐름도 (충돌 팔레트 포함)
- SetVariableToText --
computerName변수에%MacName%값을 저장한다. - IfThenElse --
computerName값으로 어떤 컴퓨터인지 확인한다. - Then -- 해당 컴퓨터에 연결된 헤드폰 장치로 오디오 출력을 전환한다.
- Else -- 아무 동작도 하지 않는다. 등록되지 않은 컴퓨터에서는 실행을 건너뛴다.
핵심 기술 해설
SetAudioDevice 액션
macOS의 오디오 입출력 장치를 프로그래밍 방식으로 변경하는 액션이다. 시스템 설정의 "사운드" 패널을 열지 않고도 출력 장치를 바꿀 수 있다. AirPods, 외장 스피커, 모니터 내장 스피커 등 macOS가 인식하는 모든 장치를 대상으로 한다.
Key105 트리거
Key105는 키보드의 물리적 키 코드다. 한/영 전환 키나 기타 특수 키에 해당한다. 일반적인 알파벳/숫자 키가 아니라 키보드 레이아웃에 따라 다른 기능을 하는 키다. 이런 특수 키를 트리거로 활용하면, 기존 단축키와 충돌 없이 매크로를 실행할 수 있다.
Else가 비어있는 조건문
이 매크로의 Else 블록에는 액션이 없다. "조건을 만족하면 실행하고, 아니면 아무것도 하지 않는다"는 패턴이다. 모든 IfThenElse가 Then과 Else 양쪽에 액션을 가져야 하는 것은 아니다. 한쪽만 사용하는 것도 유효한 설계다.
활용 팁
- 같은 단축키에 "A. 헤드폰"과 "B. 모니터" 두 매크로를 모두 할당하면, KM이 매크로 팔레트를 표시한다. A/B 중 선택할 수 있다.
- Bluetooth 헤드폰의 경우, 연결 상태에 따라 장치 이름이 달라질 수 있다.
SetAudioDevice에 정확한 장치 이름을 입력해야 한다.
매크로 분석: B. 모니터
무엇을 하는 매크로인가
단축키를 누르면 오디오 출력 장치를 모니터(또는 외장 스피커)로 전환한다. 헤드폰 매크로와 동일한 구조이되, 전환 대상이 모니터 내장 스피커다.
트리거
| 트리거 타입 | 값 | 설명 |
|---|---|---|
| HotKey | Key105 | 헤드폰 매크로와 동일한 단축키 |
액션 흐름
헤드폰 매크로와 동일한 3단계 구조다.
- SetVariableToText --
computerName변수에%MacName%값을 저장한다. - IfThenElse --
computerName값으로 분기한다. - Then -- 모니터 스피커로 오디오 출력을 전환한다.
핵심 기술 해설
동일 단축키에 복수 매크로 할당
"A. 헤드폰"과 "B. 모니터"는 같은 트리거(Key105)를 공유한다. KM에서 같은 트리거를 가진 매크로가 여러 개 있으면, 충돌 팔레트(Conflict Palette)가 나타난다. 사용자가 A 또는 B를 선택하면 해당 매크로가 실행된다.
이 방식의 장점은 하나의 키로 여러 기능에 접근할 수 있다는 것이다. 트리거를 누르면 선택지가 나타나고, 한 글자만 더 누르면 실행된다. "A"를 누르면 헤드폰, "B"를 누르면 모니터다.
헤드폰과 모니터 매크로의 설계 원칙
두 매크로를 하나로 합칠 수도 있었다. IfThenElse 안에 다시 IfThenElse를 넣어서 "헤드폰인지 모니터인지"를 묻는 방식이다. 그러나 별도 매크로로 분리한 이유가 있다.
첫째, 충돌 팔레트가 자연스러운 선택 UI를 제공한다. 둘째, 매크로 하나당 하나의 역할이라는 단일 책임 원칙을 지킨다. 셋째, 나중에 장치가 추가되면 "C. 외장 스피커" 매크로를 하나 더 만들면 된다.
활용 팁
- 새로운 오디오 장치가 추가되면, 같은 패턴으로 "C. 블루투스 스피커" 매크로를 만들 수 있다.
- Else 블록에 기본 장치(내장 스피커 등)로 전환하는 액션을 넣으면, 미등록 컴퓨터에서도 안전하게 동작한다.
매크로 분석: Commit
무엇을 하는 매크로인가
Obsidian 앱이 비활성화될 때 자동으로 셸 스크립트를 실행하여 git commit을 수행한다. 특정 컴퓨터에서만 동작하도록 조건 분기가 걸려 있다.
트리거
| 트리거 타입 | 값 | 설명 |
|---|---|---|
| Application | Obsidian | Obsidian 앱이 비활성화(deactivate)될 때 실행 |
액션 흐름
- SetVariableToText --
computerName변수에%MacName%값을 저장한다. - IfThenElse --
computerName값을 확인한다. - Then (대상 컴퓨터) -- 셸 스크립트를 실행한다. Obsidian 볼트 디렉토리로 이동해서
auto_commit.sh스크립트를 실행한다. - Else -- 아무 동작도 하지 않는다.
핵심 기술 해설
Application 트리거
Application 트리거는 특정 앱의 상태 변화에 반응한다. 앱이 실행될 때, 종료될 때, 활성화될 때, 비활성화될 때 등 다양한 이벤트를 감지한다. 이 매크로는 Obsidian이 비활성화될 때 실행되도록 설정되어 있다.
단축키를 누르거나 시간을 지정하는 것이 아니라, 앱의 상태 변화가 트리거다. "사용자가 Obsidian에서 다른 앱으로 전환할 때"가 실행 시점이 된다. 메모를 작성하다가 다른 작업으로 넘어가는 순간, 변경사항이 자동으로 저장된다.
셸 스크립트와 git 자동 커밋
cd "/Users/jaesik.lee/jaesik.lee/product/second brain"
scripts/auto_commit.sh
Obsidian 볼트 디렉토리로 이동한 뒤, 미리 작성해둔 자동 커밋 스크립트를 실행한다.
이 스크립트는 git add, git commit을 자동으로 수행한다.
KM의 ExecuteShellScript 액션은 기본적으로 /bin/sh을 사용하므로, 스크립트 내부에서 필요한 환경 변수나 경로 설정을 해줘야 한다.
환경 분기 패턴의 반복
네 매크로 모두 같은 패턴을 사용한다.
1. computerName = %MacName%
2. If computerName == "특정 컴퓨터"
Then: 실행
Else: 건너뜀 (또는 다른 동작)
이 패턴이 반복된다는 것은, 이것이 KM에서 "환경별 분기"를 구현하는 표준적인 방법이라는 뜻이다. 변수에 환경 정보를 저장하고, 조건문으로 분기하는 것이다.
활용 팁
auto_commit.sh에 커밋 메시지를 자동 생성하는 로직을 넣으면 더 유용하다. 예를 들어 날짜와 시간을 메시지에 포함시킬 수 있다.- 비활성화 트리거 대신 종료 트리거를 쓰면, Obsidian을 완전히 닫을 때만 커밋이 실행된다. 용도에 따라 선택하면 된다.
- 같은 방식으로 VS Code에서 프로젝트를 전환할 때 자동 커밋하는 매크로도 만들 수 있다.
네 매크로의 공통 구조
네 매크로를 나란히 놓으면 구조가 거의 동일하다.
| 매크로 | 변수 | 조건 | Then | Else |
|---|---|---|---|---|
| Slack 상태 변경 | computerName | 컴퓨터 이름 | 회사 Slack 상태 | 개인 Slack 상태 |
| A. 헤드폰 | computerName | 컴퓨터 이름 | 헤드폰으로 전환 | (없음) |
| B. 모니터 | computerName | 컴퓨터 이름 | 모니터로 전환 | (없음) |
| Commit | computerName | 컴퓨터 이름 | git commit 실행 | (없음) |
모두 computerName 변수를 사용하고, 모두 %MacName% 토큰으로 값을 설정한다.
차이는 Then/Else에서 실행하는 액션뿐이다.
이것이 변수와 조건문의 힘이다. 매크로의 뼈대(변수 설정 -> 조건 비교 -> 분기 실행)는 같고, 살(실제 액션)만 다르다. 새로운 "환경에 따라 다르게 동작하는 매크로"가 필요하면, 이 뼈대를 복사해서 액션만 바꾸면 된다.
직접 만들어보기
가장 실용적인 "헤드폰/모니터 전환" 매크로를 직접 만들어보자.
- KM 에디터에서 새 매크로를 만든다. 이름을 "A. 헤드폰"으로 설정한다.
- 트리거를 추가한다. Hot Key Trigger 를 선택하고, 원하는 키 조합을 설정한다. 잘 쓰지 않는 키를 권장한다.
- 첫 번째 액션을 추가한다. Set Variable to Text 를 선택한다.
- Variable:
computerName - To:
%MacName%
- Variable:
- 두 번째 액션을 추가한다. If Then Else 를 선택한다.
- 조건: The variable
computerNameis내 컴퓨터 이름 - 컴퓨터 이름은 시스템 설정 > 일반 > 정보에서 확인할 수 있다.
- 조건: The variable
- Then 블록 안에 액션을 추가한다. Set Audio Output Device 를 선택한다.
- 사용하려는 헤드폰 장치 이름을 선택한다.
- 같은 방법으로 "B. 모니터" 매크로도 만든다. 동일한 트리거를 설정하되, Then 블록의 오디오 장치만 모니터 스피커로 바꾼다.
- 테스트: 설정한 단축키를 누른다. 충돌 팔레트가 나타나면 "A"를 선택한다. 오디오 출력이 헤드폰으로 바뀌는지 확인한다.
이 챕터에서 배운 것
- 변수에 환경 정보를 저장하고 조건문에서 비교하는 "환경 분기 패턴"
- KM 토큰(
%MacName%등)과 사용자 변수의 차이 - IfThenElse에서 Else를 비워두는 설계 방식
- SetAudioDevice로 오디오 출력 장치를 프로그래밍 방식으로 변경하는 방법
- Application 트리거를 활용한 앱 상태 기반 자동화
- 동일 단축키에 복수 매크로를 할당하여 충돌 팔레트를 활용하는 기법
다음 챕터 예고
ch11에서는 서브매크로와 모듈화를 다룬다. 여러 매크로에서 반복되는 동작을 하나의 서브매크로로 분리하여 재사용하는 방법을 배운다. 업무 프로그램 위치 설정, 로그인 서브루틴 등 실전 예제를 통해 매크로 설계의 구조화를 익힌다.